# Theme manifest

Every theme ships `theme.json` in its directory root: `public/themes/{slug}/theme.json`.

**Without a valid manifest the theme does not exist.** The loader returns nothing, every view override is ignored, and the site silently renders the default theme. It does not error — it just looks like your theme was never installed.

## Fields

| Field | Required | Purpose |
|---|---|---|
| `directions` | **yes** | Writing directions the theme supports: `["rtl"]`, `["ltr"]`, or both |
| `assets.css` | **in practice** | Stylesheets to load. **Nothing is auto-discovered** — an undeclared stylesheet is never loaded |
| `assets.js` | | Scripts to load, same rules |
| `version` | | Theme version. Defaults to `1.0.0` |
| `min_core` | | Minimum Quaeriva version |
| `author` | | Attribution shown in the panel |
| `description` | | Shown in the theme list |
| `name` | | **Ignored.** The loader always uses the directory name |

## Example

```json
{
  "name": "my-theme",
  "version": "1.0.0",
  "min_core": "0.7.1",
  "author": "Example",
  "description": "A compact reading-first theme.",
  "directions": ["rtl", "ltr"],
  "assets": {
    "css": ["assets/css/theme.css"],
    "js": []
  }
}
```

## The rules that decide whether your theme loads

**1. `directions` must be present and valid.**
Values are trimmed, lowercased, then filtered against `rtl` and `ltr`. Anything else is dropped. **If the list ends up empty, the whole manifest is discarded** and the theme falls back to default.

| Written as | Result |
|---|---|
| `["rtl", "ltr"]` | both directions |
| `["RTL "]` | RTL — trimmed and lowercased |
| `["rtl", "sideways"]` | RTL; the unknown value is dropped |
| `"rtl"` | **manifest discarded** — a string is not an array |
| `[]` or missing | **manifest discarded** |
| `["auto"]` | **manifest discarded** — nothing survives the filter |

**2. The theme only applies in a direction it declares.**
A theme declaring `["ltr"]` renders **core views for every Arabic page**. This does not look broken — it looks like the default theme. Declare both directions and test in Arabic, or declare one honestly.

**3. The directory name is the identity.**
It must match `^[a-z0-9][a-z0-9_-]{0,63}$` — lowercase letters, digits, hyphen, underscore. The `name` field in the JSON is overwritten by the directory name, so a mismatch is not an error; it is simply ignored.

**4. Assets must be declared, and must survive validation.**
Each entry must:
- end in `.css` or `.js`
- match `^[A-Za-z0-9_/-]+\.(css|js)$` — no spaces, no dots in directory names, no query strings
- contain no `..`
- **exist on disk**

An entry failing any of these is dropped silently. A stylesheet you forgot to declare is simply never loaded, which is the most common reason a new theme appears unstyled.

**5. `min_core` is enforced, not documentation.**
A theme requiring a newer Core will not activate — it falls back to the default theme silently.

Mind pre-release versions. Comparison follows `version_compare()`, which ranks a release candidate **below** the final release:

| Core | `min_core` | Loads |
|---|---|---|
| `0.9.0-rc1` | `0.7.1` | yes |
| `0.9.0-rc1` | *(omitted)* | yes |
| `0.9.0-rc1` | `0.9.0` | **no** — `0.9.0-rc1` < `0.9.0` |
| `0.9.0` | `0.9.0` | yes |

Set `min_core` to the oldest version you actually support, or leave it out.

## Fields that do nothing

`parent` appears in some shipped manifests. **No code reads it.** There is no child-theme mechanism — a theme either overrides a view or inherits the core view, and that is the whole inheritance model.

Any other key you add is ignored too. The manifest is read into a fixed shape; it is not a free-form configuration file.

## Design tokens are not in the manifest

Colours, typography, shape and layout presets live in a **theme profile**, a separate JSON file the operator imports at `Appearance → Profiles`. Ship it as `public/themes/{slug}/{slug}.json` and it is offered automatically when the theme is selected.

See [Theme packages](../04-themes/THEME-PACKAGES.md) for the profile format and [Appearance tokens](../04-themes/APPEARANCE-TOKENS.md) for the token list.

## Related

[Building a theme](../04-themes/BUILDING-A-THEME.md) ·
[Template overrides](../04-themes/TEMPLATE-OVERRIDES.md) ·
[Theme resolution](../07-internals/THEME-RESOLUTION.md)
