# Creating a theme

A theme is responsible for the front-end's appearance. It's a `templates/<slug>/` folder with a `theme.json` manifest and a set of `.tpl` files. PHP in templates is forbidden — only [template-engine tags](/docs/code/templating).

## Quick start: a blank theme

Don't write from scratch — download a ready-made skeleton:

**[Download the blank theme (zip)](/public/assets/plugins/handbook/celena-starter-theme.zip)**

Inside: `theme.json`, `_partials/head.tpl` and `foot.tpl`, the base `home.tpl`, `page.tpl`, `news_list.tpl`, `news_full.tpl`, `search.tpl`, `404.tpl` and `assets/theme.css`. Unzip so the `starter-theme/` folder lands in `templates/`, activate the theme in **Settings → Templates**, and rename it to your own (the folder and the `slug` in `theme.json`).

## theme.json

```json
{
  "name": "My Theme",
  "slug": "mytheme",
  "version": "1.0.0",
  "author": "Author name",
  "description": "Short description",
  "regions": ["header", "main", "footer"]
}
```

`slug` matches the folder name and is used in the `theme` option.

## Minimal set of templates

| File | When it's called |
|------|------------------|
| `home.tpl` | home page |
| `page.tpl` | static page `/p/{slug}` |
| `news_list.tpl` | news list / category / search |
| `news_full.tpl` | single article page |
| `search.tpl` | search results |
| `404.tpl` | "not found" page |

Plus reusable pieces in `_partials/` (e.g. `head.tpl`, `header.tpl`, `footer.tpl`) and assets in `assets/`.

## Quick start: "your own theme in an hour"

1. Copy `templates/default/` → `templates/mytheme/`.
2. Edit `theme.json`.
3. Replace the styles in `assets/theme.css`.
4. Rewrite `_partials/head.tpl` and the footer to fit your markup.
5. If needed, override `home.tpl`, `news_list.tpl`, `news_full.tpl`, `page.tpl`.
6. Activate the theme in **Settings → Templates**.
7. Check responsiveness and dark mode.

## Assets and versioning

Put all css/js in `templates/<slug>/assets/` (external CDNs are forbidden by the CSP policy). Include them in `_partials/head.tpl`:

```html
<link rel="stylesheet" href="/templates/mytheme/assets/theme.css?v=1">
<script src="/templates/mytheme/assets/theme.js?v=1" defer></script>
```

> In production `nginx` caches static files for a long time. After editing `.css`/`.js`, **bump the version** (`?v=1` → `?v=2`), otherwise returning visitors get the old file from cache.

## Dark mode

Themes inherit the core's CSS variables (`--bg`, `--surface`, `--text`, `--accent`, etc.). Dark mode is toggled with the `data-theme="dark"` attribute on `<html>`. Toggle buttons:

```html
<button data-celena-theme="light">☀</button>
<button data-celena-theme="dark">☾</button>
<button data-celena-theme="auto">A</button>
```

## Overriding plugin templates

A theme can override any plugin template without touching the plugin itself. Just create a file at:

```
templates/<mytheme>/plugins/<slug>/<path>.tpl
```

The engine looks for a plugin template in this order: active-theme override → default-theme override → plugin original. Delete the theme file and the original returns. More — [Building a plugin](/docs/code/plugin-create).

## Template cache

After editing a `.tpl` in production, clear the compiled-template cache (`storage/cache/tpl/*`) — otherwise the old version is served. Locally the cache invalidates itself by mtime; the admin has **Settings → Performance → Clear cache**.
