Your own theme: folder, theme.json, templates and packing
What a theme consists of, which files you can replace, how to edit them in the panel and how to pack a theme as an archive; a working example.
A theme is a folder in themes/: a description, styles and, if needed, your own page templates. You do not have to write PHP for a theme: templates are written with the engine's ready-made tags, and everything else comes from the shared markup. A theme with no templates at all is still a full theme: it only recolours and rearranges the styles.
What goes in the folder
themes/my-theme/
├── theme.json
├── assets/
│ ├── css/theme.css
│ └── screenshot.png
├── views/
│ ├── layouts/main.tpl.html
│ ├── errors/404.tpl.html
│ └── news/index.tpl.html
└── locales/theme.json— description and configurable values (required).assets/css/theme.css— theme styles, loaded on every page.assets/screenshot.png— image for the theme card (optional).views/— your own page templates (optional): the site framelayouts/main.tpl.html, the “not found” pageerrors/404.tpl.html, the news listnews/index.tpl.htmland others.locales/— the theme's own words (optional):en.json,ru.jsonand so on.
The folder name is lowercase Latin letters, digits, hyphen and underscore, starting with a letter.
A minimal example
A theme of three files: a description, styles and your own “not found” page. The site draws everything else with the engine's shared markup.
{
"name": "my-theme",
"version": "1.0.0",
"title": {"en": "My theme", "ru": "Моя тема", "uk": "Моя тема", "no": "Mitt tema", "pl": "Mój motyw", "sv": "Mitt tema", "lt": "Mano tema"},
"description": {
"en": "A light theme with one green accent.",
"ru": "Светлая тема с одним зелёным акцентом.",
"uk": "Світла тема з одним зеленим акцентом.",
"no": "Et lyst tema med én grønn aksent.",
"pl": "Jasny motyw z jednym zielonym akcentem.",
"sv": "Ett ljust tema med en grön accent.",
"lt": "Šviesi tema su vienu žaliu akcentu."
},
"author": "Your name",
"engine": ">=0.9.9",
"variables": {
"color_accent": {
"type": "color",
"default": "#1a7f5a",
"label": {"en": "Accent colour", "ru": "Основной цвет", "uk": "Основний колір", "no": "Hovedfarge", "pl": "Kolor główny", "sv": "Huvudfärg", "lt": "Pagrindinė spalva"}
}
}
}:root {
--color-accent: #1a7f5a;
}
body {
border-top: 4px solid var(--color-accent);
}
h1,
h2 {
color: var(--color-accent);
}<section class="error error--404">
<p class="error__code">{status}</p>
<h1>{message}</h1>
<div class="error__find">{search}</div>
<p><a href="{home}">← {site_name}</a></p>
</section>You do not need to write the third file from scratch. Create the theme and ask the engine for a template starter:
php nex1on theme:files my-theme
php nex1on theme:file my-theme errors/404The first command prints the list of all pages the theme can replace and shows which of them are already yours. The second creates the file views/errors/404.tpl.html from the starter: edit it and the page picks the file up at once.
Then you can turn the theme on: “Design → Themes”, the “Make active” button on the “My theme” card (or php nex1on theme:use my-theme). Open any address that does not exist: there is a green stripe at the top and the heading is green.
theme.json: fields
| Field | What it is |
|---|---|
name | required, matches the folder name |
version | required: "1.0.0" |
title, description | name and description per language; if a language is missing, English is used |
author, engine | the author and the engine versions the theme works with: ">=0.9.9" |
screenshot | path to the picture for the card: "assets/screenshot.png" |
variables | values the owner changes under “Design” without editing files: colours, fonts, sizes, choice lists |
regions | places for module pieces (side column, footer…) that are filled in later in the panel: a key and a name in several languages |
Each variable has a type (color, size, text, choice), a default value, a label in several languages and, optionally, a hint. A choice also gets options. The name color_accent becomes the CSS variable --color-accent (underscore becomes hyphen).
Important. A value the owner has not changed is not printed on the page by the engine: it assumes the theme supplies it. So for each variable of your own, write the default value in theme.css in the :root block, as in the example. Otherwise, until anything is changed, var(--color-accent) is empty and the browser drops the whole rule.
Page templates
Each template is a file views/<folder>/<name>.tpl.html: plain HTML with tags in curly braces ({site_name}, {menu}, {content}) and blocks ([each:menu]…[/each], [if:user.logged]…[/if]). Which template is responsible for which page is shown by theme:files:
| File | What it is responsible for |
|---|---|
views/layouts/main.tpl.html | the frame of all pages: header, menu, the content place {content}, footer |
views/partials/header, footer, sidebar, card | parts of the frame and the entry card |
views/news/index, show | the news list and a single news item |
views/pages/show | an ordinary page |
views/auth/login, register, profile… | sign-in, registration, profile |
views/errors/404, 403, 500, 503 | error pages and the “site under maintenance” page |
views/search | search results |
views/forum/…, shop/…, downloads/… | module pages: forum, shop, downloads and so on (the full list is given by theme:files) |
If your theme has no file, the engine uses its own ready-made page, so you can replace templates one at a time. If the tag file is missing or broken (a block is not closed), the standard view works and the site stays up. Tags and page examples are in the articles Theme on tags and The site’s main template on tags; for module pages, see “Views on tags”.
Editing in the panel
Templates can be edited without files too: “Design → Theme code” (the theme editor). It is off by default: only the site owner can turn it on, with a repeated password. While it is off, no theme file is changed from the panel. In the editor your theme is the ready-made theme plus only the files you changed, so updates of the ready-made theme keep reaching you. The editor checks a template before saving, shows a preview, and the previous version of a file can be restored. Files created in the panel live in the theme folder, so such a theme can be packed afterwards.
The theme's words
If templates need labels, do not write them straight into the HTML: put them in the theme's locales/<code>.json and use them by key. Files are per language, as in a module; if a language is missing, English is used. Labels inside the engine's ready-made tags (member menu, sign-in, search, language choice) are already translated into all seven languages, so a theme that uses only them works in any language without translations of its own.
What a theme must not contain
- PHP files: in a theme without a Nex1on signature the installer rejects them, and tag-based templates need no PHP.
- The tags
form,scriptandstyleand event handlers in the markup: only the engine draws forms, scripts and protection keys. - Files of types other than php, json, md, txt, html, xml, csv, css, js, png, jpg, gif, webp, ico, woff, woff2. svg images are accepted only in an archive signed by Nex1on; in your own theme use png or webp.
Packing
php nex1on theme:pack my-themeThe command builds the archive my-theme-1.0.0.zip (the name carries the version from theme.json) and prints its path: by default the folder nex1on-moduli/zip two levels above the site folder; you can change it with the key app.release_directory in config/local.php. The archive is unsigned: this is how you install your own themes. How to put it on a site is in the article “Installing your own add-on”. Before packing, raise version if you are updating a theme that is already installed.