Everything that decides how the public site looks: the theme, its options, navigation and widgets, and the one-click website templates and template library.
In the user guide: the Themes & Appearance chapter.
The public theme is echo (APP_FRONT_THEME, config key dotartisan.front_theme). It extends default. Its theme.json is both a theme manifest and the schema of its options: the defaults object lists 160+ options, each with a type (color, text, select, switch, spacing, image-select, number, font, radio, textarea, file, range), a default, a label, a help tooltip and a tab.
| Piece | Class / file | Role |
|---|---|---|
| Schema | ThemeOptionsSchema | Reads theme.json (cached per file fingerprint), converts it into settings pages grouped by tab (Light colours, Dark colours, Header, Footer, Typography, Top bar, Breadcrumbs, Components, Layout, Navigation) |
| Store | ThemeOptionStore | Persists per-theme option values in the theme_options setting; supports request-scoped overrides |
| Settings screen | Appearance → Theme options | A normal settings section (theme-options) whose pages come from the schema; saving routes through SettingsController::handleThemeOptions() |
| CSS compiler | ThemeCssCompiler | Turns changed colour/typography options into a compiled stylesheet (storage/app/public/css/themes/echo/app.css) |
| Dynamic CSS | DynamicCss | Tells FrontTheme which compiled stylesheet to load and registers theme fonts |
| Helpers | theme_option(), set_theme_option(), override_theme_options() | Read an option (stored value → schema default → caller default); override it for one request |
Details and how to add your own options: Theme options and CSS pipeline and the option catalogue.
theme_option('header_preset')): logo-left, centered, split, pill, fullscreen, commerce, contact, tag, index. Each is a Blade file in resources/themes/echo/components/headers/; application-header.blade.php maps legacy ids to current ones.headers/partials/actions.blade.php): account icon, cart icon (when TruCommerce is enabled), then one call-to-action button.data-nav-fit) and Sass generated per preset — no JavaScript measuring.TopbarHtml::clean()) or a flat menu.footer-1…6) plus nine layouts (columns, wide-brand, centered, banner, wide-end, two-up, lead-stack, cards, ruled), solid, gradient or image backgrounds, and twelve top-edge shapes. See Presets, SCSS and assets.settings JSON can override header and breadcrumb options for that page only.See Content. Menus (including mega menus) are selected by id in theme options (primary_menu, secondary_menu, user_nav_menu, footer_menu); widget areas are filled in Appearance → Widgets.
Appearance → Website templates lists complete, ready-made sites (pages, blog posts, menus, footers, logo, theme options, settings and, where relevant, Booking/TruCommerce demo data). Each built-in template is a niche seeder (database/seeders/Niches/*Seeder.php, dozens exist) extending NicheSeeder; the catalogue rows are published to the website_templates table by WebsiteTemplatesSeeder (keyed by content hash).
WebsiteTemplateImporter): keep adds the template's pages beside existing ones; replace deletes all current pages and their menu entries first. Both run in one transaction.requiredModules(); the importer reports missing_modules and refuses to import when a required module is not enabled.version(); sites that applied an older version see Update available.NichePalette derives every other colour, NicheStyles holds per-niche presentation (header preset, footer kind, page recipes).Never import on a database you care about
Importing a template overwrites the homepage, menus, widgets and theme options. The niche seeders are intentionally not part of DatabaseSeeder.
Appearance → Template library browses the page-builder layouts (sections and full pages) by category with previews and lets administrators export and import them. The same data powers the editor's Templates panel. See Page builder.
.trucms.zip)Both website templates and library layouts can be exported to, and imported from, a .trucms.zip package (app/Services/WebsiteTemplates/Packages). Imports are two-step (analyse, then import) and gated by import website templates.
PackageContentValidator rejects Blade/PHP syntax ({{, @php, <?, non-shortcode <x-*> tags, :dynamic shortcode attributes) in every string.PackageAllowList.trucms-asset://{id}; remote downloads go only through RemoteAssetFetcher (public IPs, pinned DNS, manual redirects, size caps).config/template_packages.php (upload size, archive entries, compression ratio, per-asset size, remote file counts).