# Theme structure ``` themes/my-theme/ ├── theme.json # { title, config.default_template, template: layout→.twig } ├── base.twig # Main layout (head, header, nav, breadcrumb, footer) ├── full_content.twig # Layout: full width ├── left_sidebar.twig # Layout: sidebar on the left ├── right_sidebar.twig # Layout: sidebar on the right ├── custom1.twig # Layout: custom ├── guide.twig # Layout: guide with sidebar (Navigation plugin) ├── partials/ │ ├── header.twig │ ├── navigation.twig │ └── footer.twig └── assets/ ├── scss/theme.scss # SCSS source (the only CSS source) ├── css_compiled/ # Generated by scssphp (read-only, do not edit manually) ├── css/ # External CSS (bootstrap.min.css, bootstrap-icons.css, mobile.css) ├── js/ # app.js, bootstrap.bundle.min.js ├── fonts/ # bootstrap-icons.woff, woff2 └── img/ # favicon, icon, world-map ``` ## SCSS is the only CSS source - **ALWAYS** edit `assets/scss/theme.scss` — this is the only CSS source - `ThemeManager` compiles SCSS at runtime to `assets/css_compiled/theme.css` via scssphp - `assets/css_compiled/` is **read-only** — do not edit manually - **NEVER** create or edit `assets/css/theme.css` manually; this file must not exist - `ThemeManager::getCssUrl()` priority: 1) `assets/css/theme.css` (manual), 2) `assets/css_compiled/theme.css` (compiled). If `theme.css` exists, the SCSS is ignored. - After SCSS changes: remove `assets/css_compiled/theme.css` and `.mtime` to force recompilation ```bash rm themes/my-theme/assets/css_compiled/theme.css themes/my-theme/assets/css_compiled/.mtime ``` ## guide.twig Special layout for guides. Injects the Navigation plugin into the sidebar for sidebar navigation. Automatically used for pages in the `guide/` folder. ## Plugin CSS loading Plugin CSS is automatically loaded after theme CSS in `base.twig`, so themes can override plugin styling: ```twig {% for cssUrl in plugin_css_urls|default([]) %} {% endfor %} ```