---
url: https://panomc.com/docs/theme/structure.md
---
# Theme Structure

When you scaffold a theme, you get a folder with 17 files. That can look like a lot, but most of them are not yours to worry about. This page explains what each one is for, and which ones you actually edit.

## The big idea

Think of a Pano theme as two parts working together:

* **The engine** (`@panomc/theme-core`) — this does everything that *works*: login, registration, plugins, loading data from your server, and building the site. You do not write any of this. It arrives as a package and you update it like any other package.
* **Your theme** — this is only the *look*: colors, fonts, layout, and text. That is the part you own and edit.

::: tip vanilla-theme is not a template
`vanilla-theme` is the **built-in default look** that Pano ships with. It is **not** a starting point to copy or fork. Always start a new theme with `bunx @panomc/theme-core new`, and let the engine do the heavy lifting.
:::

## The files

Here is a scaffolded theme, with a note on each part:

```text
my-theme/
├─ manifest.json          ← YOURS   name, version, author, screenshots
├─ theme.config.js        ← YOURS   your view overrides + extra settings
├─ core-meta.json         ← auto    engine version and the data Pano reads about your theme
├─ plugin-contracts/      ← auto    what plugin views expect (commit it)
├─ package.json           ← auto    dependencies (svelte pinned to the engine)
├─ svelte.config.js       ← auto    one-line call to the engine
├─ vite.config.js         ← auto    one-line call to the engine
├─ lang-overrides/        ← YOURS   only the text you want to change (also per plugin)
├─ screenshots/           ← YOURS   preview images of your theme
├─ static/                ← YOURS   your images, fonts, and other assets
├─ src/
│  ├─ styles/tokens.scss  ← YOURS   your colors, fonts, sizes
│  ├─ styles/style.scss   ← YOURS   your extra CSS
│  ├─ views/              ← YOURS   your layout overrides (when you need them)
│  ├─ routes/             ← auto    generated on install and update — never edit
│  ├─ lib/                ← auto    generated on install and update — never edit
│  ├─ hooks.server.js     ← auto    generated
│  └─ hooks.client.js     ← auto    generated
└─ lang/                  ← auto    base text files — never edit
```

### Files that are yours

These are the files you edit. They are what make your theme *your* theme.

| File or folder | What you use it for |
|---|---|
| `manifest.json` | Your theme's name, version, and details (see below). |
| `theme.config.js` | Registers view overrides (engine and plugin), controller pins, claims, routes, the home page options, `provides` and extra settings. |
| `src/styles/tokens.scss` | Your design values — colors, fonts, radii, shadows. |
| `src/styles/style.scss` | Any extra CSS you want to add. |
| `src/views/` | Custom layout, when colors alone are not enough. |
| `lang-overrides/` | Only the words and phrases you want to change. |
| `screenshots/` | Preview images shown for your theme. |
| `static/` | Your images, fonts, and other files. |

### Files that are generated

These files are created **for** you by the engine. Never edit them by hand — the next install, `theme-core sync` or engine update will overwrite them, and your changes will disappear.

| File or folder | What it is |
|---|---|
| `src/routes/` | Page wiring, rebuilt from the engine. |
| `src/lib/` | Helper code and bridges, rebuilt from the engine. |
| `lang/` | The base text of every language (change text via `lang-overrides/` instead). |
| `hooks.server.js`, `hooks.client.js` | Tiny setup files that call the engine. |
| `plugin-contracts/` | A copy of the contracts of installed plugin views, written by `theme-core contracts pull`. |
| `core-meta.json`, `package.json`, `svelte.config.js`, `vite.config.js` | Config the scaffolder set up for you. |

::: warning Put every change in a file that is yours
If you edit a generated file, your work is gone the next time you install or update. Only edit the files marked "yours" above.
:::

## The manifest

`manifest.json` describes your theme to Pano. It has a small set of fields:

| Field | What it means |
|---|---|
| `id` | A unique name for your theme. It **cannot** be `vanilla-theme`. |
| `title` | The friendly name people see. |
| `description` | One or two sentences about the theme. |
| `version` | Your theme's version, e.g. `1.0.0`. |
| `author` | Your name. |
| `panoVersion` | The Pano version your theme is built for. |
| `screenshots` | A list of preview images from your `screenshots/` folder. |
| `premium` | `true` if your theme is paid, `false` if it is free. |

## What "the engine updates" means for you

Because the engine is a package, updating it is just two commands:

```sh
bun update @panomc/theme-core
bunx @panomc/theme-core sync
```

The first line pulls the newest engine. The second regenerates the "auto" files above to match it.

::: tip Your look stays
Everything in the "yours" list — your colors, your text, your assets — is untouched by an update. You get the engine's new features and fixes while your theme keeps looking exactly the way you made it.
:::
