Skip to main content

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

  1. Open Themes in the sidebar.
  2. Click the Activate button on an inactive theme's card.
  3. A confirmation modal explains the switch will:
    • Update settings.activeThemeId in 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.)
  4. Click Switch & regenerate to confirm.
  5. 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-sitemaps re-emits sitemaps with the new theme's URL conventions)
  6. 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>.css is 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 imageFormats catalog.
  • ✗ 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 magazine theme registers magazine/hero-split, magazine/most-read, magazine/promo-card
  • The corporate theme registers corporate/hero-overlay, corporate/services-grid, etc.
  • The default theme 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:

  1. Open the affected post.
  2. The block shows as "unknown block" in the editor — delete it or replace with a corporate-equivalent.
  3. 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>.css is 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:

  1. Themes → Regenerate site → Everything — re-runs the full regen with the now-active theme
  2. 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>.css from the bundle's embedded cssText

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