Skip to content
Docs

Developer guide

Building a theme package

A theme package is Zittme's way of bundling a layout and several module skins into one set for distribution and application. When a user installs and applies a single theme, the layout and the skins for each module, such as boards and members, change together as one matching set.

A theme is not a new kind of resource. It is a wrapper that bundles existing layouts and skins. You build each component the way you normally would.

1. Folder structure: everything in its own folder

A theme keeps all of its components inside themes/{theme name}/. The internal structure mirrors the original paths exactly.

themes/heritage/
├── theme.xml                              ← 테마 정보와 구성 목록
├── assets/                                ← (선택) 구성요소가 공유하는 CSS 등
├── layouts/
│   └── heritage_default/                  ← 일반 레이아웃과 완전히 같은 구조
│       ├── layout.html
│       ├── conf/info.xml
│       ├── css/  js/
└── modules/
    ├── board/skins/heritage_default/      ← 일반 게시판 스킨과 같은 구조
    └── member/skins/heritage_default/

The reason for this is that there are no conflicts. Even if a theme's board skin has the same name as a board skin from another resource, they live in different folders, so neither overwrites the other. Deleting a theme removes just one folder.

2. theme.xml

<?xml version="1.0" encoding="UTF-8"?>
<theme schema="1.0">
	<title xml:lang="ko">헤리티지</title>
	<description xml:lang="ko">레이아웃·게시판·회원 스킨이 한 벌로 맞춰진 테마입니다.</description>
	<version>1.0.0</version>
	<date>2026-08-04</date>
	<author email_address="you@example.com" link="https://example.com">제작자</author>
	<license>GPLv2</license>

	<components>
		<component type="layout" name="heritage_default" />
		<component type="module-skin" target="board" name="heritage_default" />
		<component type="module-skin" target="member" name="heritage_default" />
	</components>

	<apply>
		<layout name="heritage_default" />
		<skin module="board" name="heritage_default" />
		<skin module="member" name="heritage_default" />
	</apply>
</theme>
  • components: Declares what is inside this theme folder. type is layout or module-skin (in which case target specifies the module).
  • apply: Defines what gets applied where when the user clicks "Apply theme". Before applying, the list of changes is shown to the user for confirmation.

Missing modules are skipped

Even if a theme includes commerce skins, on a site without the commerce module installed only those entries are quietly skipped. It is safe to include skins for optional modules in the set.

Responsive themes

To declare a theme as responsive, every component skin and layout must carry the <responsive>true</responsive> flag. If even one is missing, validation rejects the theme. (See Responsive views and responsive display.)

3. Build components the usual way

Layouts and skins inside a theme use exactly the same syntax and conventions as regular resources. The only difference is that they live inside the theme folder.

  • Layout: layout.html + conf/info.xml (including extra_vars, menu declarations, and repeat fields)
  • Skin: the same set of template files as the module's default skin

Shared assets: To make the whole theme use the same color and font system, put common CSS in themes/{name}/assets/ and load it from each component with a relative path. If you collect colors into CSS variables, you can change the colors of the entire theme in one place.

/* themes/heritage/assets/heritage.css */
:root {
	--hr-brand: #6c5ce0;
	--hr-ink: #10151f;
	...
}
/* 게시판 스킨 css 에서 */
@import url("../../../../../assets/heritage.css");

4. Installation and apply behavior

  • Installation validates everything first, then extracts everything. If even one component has a problem, nothing is installed.
  • The apply scope is limited to the selected site.
  • Before applying, a list of what will change is shown for confirmation.

5. Build checklist

  • Do the components in theme.xml match the actual folder contents?
  • Does each component work correctly on its own? (A theme is only a wrapper.)
  • If declared responsive, does every component have <responsive>true</responsive>?
  • If you use template v2, did you avoid multi-line {{-- --}} comments? Only single-line comments are stripped, so multi-line comments cause a server error. Use HTML comments for multi-line notes.
  • Does the layout CSS declare a background on html, body? If you paint the background only on the top-level div, a white strip remains at the edges of the screen in dark mode.