Theme registry
An agency registers signed/approved theme versions before a client can select them. A site pins one theme version at a time. Theme switching always begins with a registry migration preview, then writes a separate draft document after all missing/incompatible slots are resolved.
ThemeRegistry resolves the developer-deployed theme definitions used for preview and migration. The Cloudflare adapter now persists each site’s draft and published theme selection in its tenant Durable Object through TenantWorkspaceThemeStore; theme source code remains deployed with the Astro application.
Theme selection and content are a pair. switchDraft() writes the schema-validated migrated document and target theme pin in one SQLite transaction with independent expected versions. publishSite() atomically publishes the matching draft document/theme pair. Public rendering therefore cannot observe new content under an old layout or an incompatible theme under old content.
The example developer catalog contains an appearance-only alternative and a compact layout that intentionally removes known slots. The editor selects an exact deployed id@version; it never accepts an arbitrary theme URL or stylesheet. Theme code is trusted as part of the site deployment, while future third-party theme distribution will need the same signed-release discipline as plugins.
Appearance values map to CSS custom properties, so plain CSS and Tailwind can consume the same tokens. Tailwind remains natural but optional and no Tailwind runtime is required.