Skip to content

Extensions

pH7x Systems edited this page Jul 21, 2026 · 6 revisions

Extensions

Sardine CMS grows through one contract (ADR-0028): a package exposes a single Extension object through the sardine.extensions entry-point group (or a dotted path such as my_pkg.ext:extension), and a project activates it explicitly:

extensions = ["my-extension"]

[site]
name = "My Site"
# ...

Nothing activates just by being installed — a project states what it trusts.

What an extension can contribute

Contribution Consumed by
validation_rules cms validate, the panel's publish gate and report
build_steps(config, content, artifact) after every build, deterministic, ordered by extension name
targets, storage_backends, themes the existing registries (cms export --target, create_storage, theme discovery)
cli (a Typer app) mounted as cms x <name> …
section_kinds field hints in the admin's section editor

Custom article fields

Articles carry a free-form fields map (like sections always did): edited in the panel's Custom fields card, exported in the portable JSON, exposed to themes as article.fields. Projects, extensions and themes agree on the keys; the framework only carries them.

Publishing an extension

The conformance suites (storage, theme, target) are the license to publish, and the ecosystem policy governs listing — see docs/ECOSYSTEM.md.

Comments providers (ADR-0031)

An extension may register comments integrations through Extension.comments_providers — a mapping of provider name to CommentsProvider(island_js, thread_url). The island script is vendored bytes shipped same-origin from the built artifact, and must make no request before an explicit reader action; thread_url(base, page_url) maps each article to its discussion, deterministically. A project activates one with the [comments] table in sardine.toml.

Mail transports (ADR-0032)

Extension.mail_transports maps a transport name to a factory returning a send(to, subject, body) callable. The admin selects one with SARDINE_MAIL_TRANSPORT; the factory reads its own configuration from the environment and may raise at startup when misconfigured — never at send time. This is where OAuth/passwordless provider delivery lives; the core ships only the smtp baseline.

Language packs (ADR-0034)

Extension.language_packs contributes LanguagePack objects — tag, direction (ltr/rtl), native_name, site_labels, month_names (12), date_pattern and optionally admin_catalog (gettext .po text for the panel chrome). An activated pack's tag becomes a full content language: usable in [site] source_language and [site] languages, built and labeled from the pack's data, and rendered with dir="rtl" when the pack says so. A pack carrying an admin catalog also becomes a panel language, offered in the switcher by its native name. A configured tag without its pack fails loudly. Authoring guide: Language Packs and the repository's docs/LANGUAGE_PACK_GUIDE.md (sardine-lang-<tag> naming).

Clone this wiki locally