Themes and templates
What a SeedWebs theme holds, what each kind of theme part is, how a template is chosen for each URL, and how to change colours, fonts and Tailwind.
Last updated 2026-08-11
Everything about how your public site looks comes from a theme, stored inside your own site. A theme holds the HTML of the header and footer, the global CSS and JavaScript, and the smaller pieces — theme parts — that decide how a post, a product or a category page is rendered.
This guide covers what a theme holds, where to edit it, and the order in which SeedWebs picks a template for a URL.
Themes are managed at Settings → Themes (/admin/settings/themes).
What one theme holds
Each theme carries these values of its own. The first five are edited on the General tab of the theme editor; Thumbnail is in the right sidebar, visible from every tab.
| Field | Label on screen | What it does |
|---|---|---|
header_html | Header | The header HTML shown on every page |
footer_html | Footer | The footer HTML shown on every page |
global_css | Global Styles | Everything placed in <head> — Google Fonts <link> tags, the Tailwind script, <style> blocks |
global_js | Global JavaScript | A script placed at the end of <body> on every page. Write the code only, no <script> tag |
body_class | Body class | Tailwind classes applied to the <body> tag, such as background colour and font |
thumbnail | Thumbnail | The cover image on the theme card in the list. .webp only, up to 2 MB |
Header, Footer, Global Styles, Global JavaScript and Body class each hold up to about 1 MB. Over that, the save is refused and you are told which field is too big.
The tabs in the theme editor
Opening a theme shows pill tabs at the top.
| Tab | URL | Contents |
|---|---|---|
| General | /admin/settings/themes/{id} | Header, Footer, Global Styles, Global JavaScript, Body class |
| Nav | /admin/settings/themes/{id}/nav | The elements that build the menu (slugs starting nav-) |
| Elements | /admin/settings/themes/{id}/elements | Reusable elements, such as a post card or product card |
| Templates | /admin/settings/themes/{id}/templates | The template for each kind of page |
| Emails | /admin/settings/themes/{id}/emails | Email templates. Only present when Newsletters is enabled under Settings → General → Admin Menu |
Newsletters requires the Business plan or the trial, and the per-site experimental flag. Without both, the Emails tab does not appear at all. See Plans and billing.
Every tab shares the same right sidebar: the status box (Active / Inactive), the theme name, its slug, the save button, the Thumbnail box, and an Options box holding a pop-out tag reference and the Export Theme button.
Expanding a theme part’s card gives three sub-tabs:
- Content — edit the text and images in the code without touching HTML
- Style — edit each element’s Tailwind classes
- HTML — edit the code directly, with a format button
Collapsed, a card shows a small rendered preview. Click the preview to expand, and the pencil icon in the card header to change that part’s name and slug.
Kinds of theme part
In the database a theme part’s type is one of header, footer, element, template or email.
In practice, in the current version:
- element — a piece called from elsewhere with
{{> slug}}, such aspost-cardinside a post-list loop. Elements whose slug startsnav-are split out into the Nav tab; the rest live under Elements. - template — the shell for one whole page, such as
post-listfor the post listing. - email — the body of a system email, such as the subscription confirmation.
- header and footer — still accepted by the API, but the header and footer actually rendered come from
header_htmlandfooter_htmlon the theme itself, not from parts. That is why there are no Headers or Footers tabs, and why importing a theme from a ZIP skips parts of those two types.
A part’s slug has to be unique within one theme and one type — so an element called post-detail and a template called post-detail can coexist.
The Elements and Templates lists hide parts belonging to content types you have switched off under Settings → General → Admin Menu, going by the slug prefix (post-, event-, product-, book-, staff-, doc-, slider-, member-). Parts not tied to a content type — page, category, tag, search-results, not-found — are always shown.
That filter does not cover slugs starting tour-, so tour templates always remain in the list. Tours are in no plan’s permissions; the SeedWebs team has to turn on the experimental flag for your site before they do anything. Until then, editing a tour template changes nothing, because no page calls it.
How a template is chosen
When somebody opens a URL, SeedWebs picks a template through three nested fallbacks.
Layer 1 — the active theme, then the default theme
Parts are taken from the Active theme first, and the gaps filled from the theme whose slug is default, matching on the pair of type + slug. That is why a brand-new theme with no parts at all still renders a complete site: it borrows every part from the default theme. Create a part with the same name in your own theme and yours immediately wins.
Layer 2 — a specific slug, then the general one
A category page looks for a template named for that category first, and falls back to the general one. The category news looks for category-news, and failing that uses category. This is how you make one category look different from the others without touching the shared template.
Layer 3 — type template, then type element
Once the slug is settled, SeedWebs looks for a part of type template first, and failing that a part of type element with the same slug.
The order per URL
{slug} below is the slug of the category, brand or page template being viewed.
| Page | Search order |
|---|---|
| A Page written in Article mode | page-{page template slug} → page |
/posts | post-list |
/posts/:slug | post-detail-page → post-detail |
/category/:slug (or /category/:parent/:slug, nested) | category-{slug} → category |
/tag/:slug | tag |
/events | event-list |
/events/:slug | event-detail-page → event-detail |
/products | product-list |
/products/:slug | product-detail-page → product-detail |
/product-categories/:slug | product-category-{slug} → product-category |
/product-brands/:slug | product-brand-{slug} → product-brand |
/tours | tour-list |
/tours/:slug | tour-detail-page → tour-detail |
/tour-category/:slug | tour-category-{slug} → tour-category |
/tours/bookings/:booking_number | tour-thankyou |
/staffs | staff-list |
/staffs/:slug | staff-detail-page → staff-detail |
/staff-categories/:slug | staff-category-{slug} → staff-category → staff-list |
/authors | author-list |
/authors/:slug | author-detail-page → author-detail |
/books | book-list |
/books/:slug | book-detail-page → book-detail |
/book-categories/:slug | book-category-{slug} → book-category |
/docs/:slug | doc-detail-page → doc-detail |
/search | search-results |
/cart | cart — only while the store is on (Store settings → Checkout enabled + a payment gateway); otherwise 404 |
/checkout | checkout — same condition |
/orders/:order_number | order-received |
| A page that does not exist (404) | not-found |
A page of your own slugged cart, checkout or orders is served instead of the store page — pages come first, as everywhere else. A WooCommerce import brings such pages along; set them to draft to let the store pages through.
If nothing in the order matches, that content page answers 404 — except Pages, which still render their content plainly with no template. For not-found, a missing template falls back to a built-in page. The not-found template supports {{site_name}} and {{> partial}} (so a shared sidebar or footer block still appears); item tags are not rendered there, because a 404 has no item.
The tags used inside templates are documented in Template tags.
What the default theme ships with
Every new site gets a theme called Default (slug default), with this factory set of parts.
Templates
page · post-list · post-detail-page · category · tag · event-list · event-detail-page · product-list · product-detail-page · product-category · product-brand · tour-list · tour-detail-page · tour-category · tour-thankyou · staff-list · staff-detail-page · staff-category · author-list · author-detail-page · book-list · book-detail-page · book-category · doc-detail-page · search-results · not-found · order-received · cart · checkout
Elements
post-card · event-card · product-card · tour-card · staff-card · book-card · author-card · post-detail · event-detail · language-switcher
Elements on the Nav tab
nav-item · nav-submenu · nav-mega-header · nav-mega-column · nav-mobile-item · nav-mobile-submenu · nav-mobile-mega · nav-mobile-mega-column · nav-mobile-drawer
Emails
email-confirm · email-welcome · email-newsletter · email-unsubscribe · subscribe-form
The Templates tab also groups a Page Templates heading at the top, listing the page templates your site has (two come as standard, Default and Landing). Where one has never been customised you see a dashed box saying it still uses the default layout, with a Customize button. That button creates a new template called page-default or page-landing for you to edit. Default is seeded with a copy of the page template; Landing starts from an empty shell with no header or footer, because a landing page is meant to control the whole page itself.
Putting {{header}} and {{footer}} in a page template inserts the theme’s header and footer at exactly that point, and SeedWebs then does not insert them again. The exception is a page using the Landing page template, where both tags render as nothing.
The default theme: resettable, not deletable
The default theme differs from the others in three ways.
- It cannot be deleted. The bin icon in the corner of the status box becomes a reset button instead, and a delete through the API is refused.
- It cannot be deactivated. Pressing Inactive while the default theme is the Active one warns you to activate another theme first.
- Its factory parts cannot be deleted. Parts that shipped with the platform are protected, with a message saying they are built in and to use Reset instead. Parts you added to this theme yourself delete normally.
Reset to default is the circular-arrow icon at the right of the status box. It restores the theme name to Default, overwrites Header, Footer, Global Styles and Body class with the factory values, empties Global JavaScript, then deletes every theme part in this theme and re-inserts the factory set. Everything you had customised in the default theme, including parts you created, is gone. To experiment without that risk, create a new theme and work in it.
Any theme other than default can be deleted, and deleting the Active theme switches back to the default theme automatically. Media library images the theme referenced are not deleted with it.
The theme library
Settings → Themes shows a Theme library strip with themes that ship with SeedWebs. Clicking Install creates an ordinary theme on your site — not active until you activate it, and editable, exportable and deletable like any theme you made. A theme in the library overrides only the parts it cares about; everything else falls back to Default, so it keeps working as new content types arrive.
| Theme | What it changes | Notes |
|---|---|---|
| Shop | Header with search and cart icon, footer with menu and subscribe form, image-first product cards with an Add-to-cart button, gallery-first product page, product category/brand/tag archives with sort links, styled cart, checkout, order and search pages, 404, page | Browse-only until Store → Settings → Enable Checkout and a payment method are set — the same theme then sells. Install also creates a draft page Shop home (hero, new arrivals, best sellers) for you to edit and set as the homepage. Takes its accent from Settings → General → Primary colour |
Installing a second time is refused while a theme with that slug exists — delete yours first if you want the factory version back.
Creating a theme, and importing from a ZIP
Add Theme
Settings → Themes → Add Theme (/admin/settings/themes/new). Enter a name and press Create Theme.
The Import HTML field on that page is optional. Paste a single page of HTML and SeedWebs tries to split it up: <script> tags, font and CSS <link> tags and <style> blocks from <head> become Global Styles; a <nav> pinned to the top of the viewport, or a <header>, becomes the header; <footer> becomes the footer; and the contents of <main> or <body> become a home page (slug home), with a checkbox for whether to replace the existing one.
A theme created here is activated immediately and has no theme parts of its own, so it borrows all of them from the default theme.
The Import HTML button at the right of the tab bar in the theme editor does the same thing for a theme that already exists.
Upload Theme (ZIP)
The Upload Theme button on the theme list takes a .zip. The structure it reads is:
theme.json required — name, slug, header_html, footer_html, global_css, global_js
header.html optional — overrides the value in theme.json
footer.html optional
parts/element-post-card.html named {type}-{slug}.html
parts/element-post-card.json metadata — name, slug, type, sort_order
Limits: the ZIP itself up to 2 MB, at most 100 files inside, and up to 5 MB of extracted content. Without theme.json the upload is refused.
If the slug collides with an existing theme, a number is appended — mytheme-2. An imported theme is not activated; press Activate yourself.
Export Theme
In the Options box of the right sidebar in the theme editor. It downloads {slug}.zip.
In the current version that file contains a theme.json with the name, slug, Global Styles and Global JavaScript. The header, the footer and the theme parts in parts/ are not yet included, so do not use this file as a backup. To back up the whole site, use Tools → Backup (/admin/tools/backup).
Tailwind: CDN or Optimize
Public pages are styled with the Tailwind classes written into your theme’s HTML, so the browser has to get the CSS for those classes from somewhere. Two buttons at the bottom of the HTML tab of the Global Styles editor handle this.
Use CDN adds the browser build of Tailwind v4 to Global Styles, along with a <style type="text/tailwindcss"> block containing an @theme starter with two colours (foreground and background) to build on. An older Tailwind v3 script is removed, and if v4 is already there you are told so and nothing is duplicated. Classes are compiled in the visitor’s browser, which is convenient while designing, but every visitor loads an extra external file.
Optimize scans all of this theme’s HTML — header, footer, every theme part, page content written as HTML, and the Body class — compiles only the classes actually used into a <style>/* Tailwind CSS (built) */…</style> block, puts it back into Global Styles, removes the CDN script, and saves immediately. Pages load faster and depend on no external file, which is what you want in production.
The catch with Optimize is that it compiles what exists at the moment you press it. Every time you add a new Tailwind class to a theme part or a page, press Optimize again, or that class has no CSS behind it.
Changing colours and fonts (Global Styles)
The Global Styles editor reads the colours and fonts out of your code for you. Collapsed, it shows a row of colour swatches and an “Aa” font sample. Expand it for three tabs.
Colors lists every declared colour. Click a swatch to open a colour picker; the value is written straight back into the code. Add colour creates a new one (names may use English letters, digits, hyphens and underscores), and the bin icon that appears on hover removes it. A colour’s name becomes a usable class — a colour called accent gives you bg-accent and text-accent.
The default theme comes with five: foreground, background, card, muted, primary.
Fonts lists the declared fonts with a Thai sample sentence. Change opens a Google Fonts search (hover a name to preview it before choosing). Add font adds another, starting with a “key” — the key becomes the class, so a key of heading gives you font-heading.
Whenever you change, add or remove a font, SeedWebs rewrites the whole Google Fonts <link> tag itself, requesting weights 400, 500, 600 and 700 and the latin and thai subsets. There is no need to edit that link by hand.
The font picker includes the Thai fonts people use most — Noto Sans Thai, Sarabun, Kanit, Prompt, Mitr, Niramit, IBM Plex Sans Thai, Bai Jamjuree, Pridi, Itim — and you can search Google Fonts for anything else.
Uploading your own font
A font that is not on Google Fonts — a brand font, or a Thai display font from a foundry — can be uploaded. At the bottom of the Fonts tab, under Uploaded fonts, press Upload font and pick the files (.woff2, .woff, .ttf or .otf; .woff2 is the smallest and loads fastest). One family can have several files, one per weight and style — Regular 400, Bold 700, Italic and so on. SeedWebs guesses the family name, weight and style from each file name (SaoChingcha-Bold.woff2 becomes Sao Chingcha, 700, normal); correct any guess, then press Save font.
The files go into your media library, and SeedWebs writes the @font-face rules (with font-display: swap) into Global Styles for you. The family then appears at the top of the font picker under Uploaded — choose it with Change for font-body, font-heading or any other key, and the fallbacks you already had (for example sans-serif) are kept. An uploaded font is never requested from Google Fonts. When it is the font-body font, its regular file is preloaded so the text appears in it sooner.
Remember to press Save on the theme afterwards. A family that a font key still uses cannot be removed — switch that key to another font first. Uploaded fonts travel with the theme when you export or import it, and with a theme created from it; the files themselves stay in this site’s media library, so do not delete them there.
If you work with an AI agent over the Business API, it can install a font the same way (set_theme_font then set_theme_font_role over MCP, or /api/themes/{id}/fonts over REST) instead of editing Global Styles by hand.
HTML is the raw editor for the whole of Global Styles, for writing your own CSS or editing the @theme block directly. The Use CDN and Optimize buttons are on this tab.
The default theme also ships a set of .prose CSS in Global Styles, which styles headings, paragraphs, lists and tables inside post content. Edit it as you like.
Who can edit themes
Themes fall under the settings.themes permission, held by two roles.
| Role | Can open Themes | Can edit / create / delete themes and parts |
|---|---|---|
| super_admin | Yes | Yes |
| admin | Yes | Yes |
| editor | No | No |
| writer | No | No |
Heavier operations are super_admin only: wiping the site’s content at Tools → Reset, and restoring from a backup at Tools → Backup (creating a backup goes up to admin). Roles are described in Users and permissions.
The theme system is not limited by plan. Every plan can edit themes, create themes and edit templates equally. What the plan governs is which content types your site can enable — which in turn hides the disabled types’ templates from the list and makes their public pages answer 404. On top of the plan there is the per-site experimental flag covering Events, Docs, Books, Staffs, Members, Newsletters and Tours. See Plans and billing.
Common misunderstandings
Edited the theme, but the site has not changed. First check that the theme you edited is the Active one: the status box in the right sidebar must say Active, and the card in the theme list shows a solid badge. The other common cause is adding new Tailwind classes after having pressed Optimize — press Optimize again.
Created a new theme and the site looks the same. That is correct. A new theme has no parts of its own, so it borrows all of them from the default theme until you create a part with the same name to override it.
Want one category to look different from the others. Do not edit the category template. Create a new template called category-{that category's slug} and SeedWebs will use it for that category only.
Reset cannot be undone. You are asked to confirm once, but confirming overwrites everything in the default theme with the factory values and deletes all of that theme’s parts. There is no undo. If work is lost, the only route back is Tools → Backup, which rolls the whole site back to a snapshot rather than just the theme — and only super_admin can restore.