Switching themes
Switching the active theme is a deliberate, all-or-nothing operation. The new theme's HTML / CSS replaces the old theme's everywhere on your site at once. There's no per-page theme override, no a/b testing.
This page walks through what happens when you switch and how to recover if it goes wrong.
The switch flow
- Open Themes in the sidebar.
- Click the Activate button on an inactive theme's card.
- A confirmation modal explains the switch will:
- Update
settings.activeThemeIdin Firestore - Upload the new theme's CSS to
/theme-assets/<new-theme-id>.css - Regenerate every published HTML page with the new theme's templates
- Re-run every plugin's regeneration target (sitemaps, RSS, search index, etc.)
- Update
- Click Switch & regenerate to confirm.
- The publisher's
regenerateAll()runs:- Re-renders every online post (
<n>files) - Re-renders every page (
<m>files) - Re-renders every category archive
- Re-renders the home page
- Re-uploads
menu.json(theme switch may change branding logo URL) - Re-uploads
posts.json(some themes have different post-card data needs) - Runs every plugin's regen target (e.g.
flexweg-sitemapsre-emits sitemaps with the new theme's URL conventions)
- Re-renders every online post (
- The publish log shows progress. Each upload takes a small fraction of a second; total time scales with the number of online posts. A site with 100 posts switches in ~30s.
What changes
After a successful switch:
- ✓ Every public page now serves with the new theme's HTML
- ✓ The new theme's CSS is at
/theme-assets/<new-theme-id>.css - ✓ The old theme's CSS at
/theme-assets/<old-theme-id>.cssis left in place (still referenced by no published page, but not deleted automatically — useful as a backup if you want to switch back) - ✓ Theme blocks from the previous theme are still present in your post bodies as
<div data-cms-block="<old-theme>/<block>">markers, but they won't render (the new theme's marker regex doesn't recognise them). Edit affected posts to remove or replace those blocks.
What doesn't change
- ✗ Your posts, pages, categories, tags, media — none of these touch on the theme
- ✗ Plugin configurations — settings page configs are theme-agnostic
- ✗ Menus — the menu builder doesn't depend on the theme; only the rendering at the public site changes
- ✗ Image variants in your media library — keep their existing variants. New uploads will use the new theme's
imageFormatscatalog. - ✗ Your settings (site title, language, baseUrl, etc.)
Theme blocks from the previous theme
Theme blocks are scoped to the theme that registered them. For example:
- The
magazinetheme registersmagazine/hero-split,magazine/most-read,magazine/promo-card - The
corporatetheme registerscorporate/hero-overlay,corporate/services-grid, etc. - The
defaulttheme registers no theme blocks (uses only core blocks)
If you've inserted a magazine/hero-split in a post and switch to corporate, that block markers stays in the post's markdown (<div data-cms-block="magazine/hero-split" data-attrs="…">) but corporate's render pipeline doesn't recognise it. The publisher leaves the marker as-is in the rendered HTML — visitors see an empty <div> where the block was.
To clean up:
- Open the affected post.
- The block shows as "unknown block" in the editor — delete it or replace with a corporate-equivalent.
- Save + re-publish.
If you have many such posts, you can do a one-time scan via Firestore: search the posts/ collection for documents whose contentMarkdown contains data-cms-block="<old-theme>/.
Switching back
The old theme's CSS is still on Flexweg (we don't auto-delete on switch). If you switch back:
- Same flow — confirmation modal, regenerate everything
- The old CSS at
/theme-assets/<old-theme-id>.cssis still there, so it's instantly served (no need to re-sync) - Theme blocks from the corporate (or whatever interim theme) still exist in posts; same cleanup applies
When the switch fails partway
regenerateAll is idempotent — it can be re-run without making things worse. If the switch fails halfway through (network blip, Flexweg API quota hit), the publish log shows which step failed. After fixing the underlying issue:
- Themes → Regenerate site → Everything — re-runs the full regen with the now-active theme
- Or just publish individual posts that are out-of-date
Some posts may temporarily be served with old-theme HTML referencing new-theme CSS (or vice versa) — visitors see a brief mismatch until the regen completes.
Activating an external theme
External themes (uploaded via Install theme) work the same way as built-ins:
- They appear as cards in the Themes list
- Clicking Activate triggers the same regenerate-all flow
- The external theme's CSS is in its bundle (uploaded along with the bundle.js); the Sync theme assets flow re-uploads it to
/theme-assets/<id>.cssfrom the bundle's embeddedcssText
Uninstall protection
If you try to uninstall the currently-active theme, the Uninstall button is disabled. Switch to a different theme first, then uninstall the previous one.
This prevents leaving the admin with no active theme, which would 404 the public site. The default theme is always available as a safe fallback (it stays bundled even when externals are uninstalled — see [Themes architecture]).
Continue
- Theme settings — customise without switching
- Sync theme assets — re-push the active theme's CSS without regenerating pages
- Installing external themes
- Built-in themes reference