-
Notifications
You must be signed in to change notification settings - Fork 0
Themes
Sardine CMS is design-agnostic: themes are packages, discovered at runtime, and the builder never hardcodes HTML. The bundled ph7x-reference theme is one example, not the product.
Themes register a Python entry point in the sardine.themes group:
# pyproject.toml of a theme package
[project.entry-points."sardine.themes"]
my-theme = "my_theme:MyTheme"theme = "my-theme" in sardine.toml selects it. A theme provides two things: assets() (a mapping of relative paths → bytes, shipped verbatim with hashed URLs) and render(kind, context) for the page kinds page, article, listing, not_found. JinjaTheme is the batteries-included base: point it at a template directory and it renders <kind>.html.j2 with autoescape on.
Every page receives head (canonical, hreflang cluster, OG, optional JSON-LD), nav (home_url, menu, languages — the language switcher keeps the reader on the current page wherever a translation exists), footer (text, menu, optional admin_url/admin_label) and asset_urls (hashed). Kind-specific context:
| Kind | Extra context |
|---|---|
page |
page (title, description), sections (key, kind, data fields, images), latest articles |
article |
article (title, body_html, date, category, tags, cover, reading time) |
listing |
listing (entries, page/pages, prev/next, filters, search index URL, labels) |
not_found |
localized head + not_found.home_url
|
UI strings come from the localized label system (cms_build.ui, overridable via [site.labels]) — templates never hardcode editorial text.
A section's kind names the template branch that renders it; unknown kinds get a graceful generic rendering (conformance-tested). The authoring contract is spec-based (ADR-0037): a SectionKindSpec declares flat fields, Markdown-capable fields (delivered to templates as safe HTML) and the columns of the unbounded section.rows items group — no template may cap repetition, and the conformance suite proves a ten-item FAQ renders in every theme. Pages expose page.body_html for long-form Markdown. The bundled gallery — the authoring contract SECTION_KIND_GALLERY in cms_build.themes, documented kind-by-kind in the repository's THEME_GUIDE — ships nine kinds implemented by both bundled themes: hero, story, expertise, latest-articles, quote (pull quote), faq (native <details>, no JavaScript), cta (per-language target URL), gallery (srcset-aware image grid) and contact. The admin section editor suggests exactly these fields and merges kinds advertised by activated extensions.
Article contexts may carry an optional comments object (label, thread_url, island_url) when the project configures a provider. Themes render a plain localized link (the no-JS surface) inside a <site-comments> element plus a module script for the same-origin island; ignoring the key keeps working.
A project can override individual templates and assets of the active theme locally (layered lookup) without forking the package.
The reference theme's stylesheets contain only rules its templates actually emit, documented in English; load-bearing decisions (the [hidden] first rule, the sticky-footer flex trap, build-time code highlighting) are commented in place.
Native web platform only: no frameworks, no build step. Interactivity ships as small Web-Component islands (ES modules) and every page must be complete without JavaScript. The framework ships one island: <site-search> (per-language JSON index, same-origin fetch, aria-live results). Total JS budget for a theme: ≤ 20 KB, enforced by tests. The reference theme itself adds zero JavaScript — its effects (aurora, grain, reveals, constellation field, cards/list toggle) are modern CSS only.
Design tokens only, local fonts (Inter, Newsreader — OFL, subset), inline SVG, zero inline styles, images with dimensions, no horizontal scroll, editorial dark theme, WCAG 2.2 AA (enforced by the axe gate in CI), and flow-relative CSS only — logical properties, never -left/-right — so a pack-declared RTL language mirrors the whole layout (ADR-0034). Mechanical rules land as tests in the theme conformance suite; the flow-relative rule is one of them, so third-party themes inherit it.
With [build] image_widths = [480, 960] (and sardine-cms-build[images] installed), the builder generates deterministic resized variants and hands themes a ready srcset on every image context — both bundled themes render it out of the box.
Sardine CMS — multilingual, static-first CMS framework · Repository · Live demo · Apache-2.0