Skip to main content

Sync theme assets

The Sync theme assets action re-uploads the active theme's CSS + companion JS files to /theme-assets/ on Flexweg from the manifest's bundled cssText (with any compileCss(config) overrides applied).

It's a one-click operation when you need to:

  • Refresh the public CSS after editing theme settings
  • Recover from a partial deploy where theme-assets/ weren't uploaded
  • Re-emit the menu / posts loader scripts after they were deleted

The button lives in Themes → Sync theme assets at the top of the page.

What gets synced

For the active theme:

FileSourceUploaded to
<theme-id>.cssTheme manifest's cssText (compiled SCSS / Tailwind), processed through compileCss(config) if available/theme-assets/<theme-id>.css
<theme-id>-menu.jsManifest's jsText (when present)/theme-assets/<theme-id>-menu.js
<theme-id>-posts.jsManifest's jsTextPosts (when present)/theme-assets/<theme-id>-posts.js

Themes that don't ship jsText or jsTextPosts skip those uploads. The default / magazine / corporate themes all ship both.

Why a sync action exists

Theme settings (style overrides, font swaps) regenerate the CSS — but the regenerated CSS is uploaded automatically on save. So when does a manual sync help?

Cases:

  • After uploading a new admin build → the bundled CSS for built-in themes may have changed (bug fixes, new features). Sync ensures the public site uses the latest CSS.
  • Theme settings page is hidden (the active theme has no settings page) but you've manually edited the theme's source code → sync pushes your changes
  • /theme-assets/ was wiped by an erroneous Flexweg cleanup → sync re-creates them
  • A new theme was just installed → activating runs Sync automatically, but you can re-trigger if needed

What happens when you click

The admin runs:

async function syncThemeAssets(themes, themeConfigs, log) {
for (const theme of themes) {
if (!theme.cssText) continue;

const cssPath = `theme-assets/${theme.id}.css`;
let cssContent = theme.cssText;

// Apply compileCss(config) override if the theme has one
if (theme.compileCss && theme.settings) {
const stored = themeConfigs?.[theme.id];
const resolvedConfig = {
...theme.settings.defaultConfig,
...(stored ?? {}),
};
cssContent = theme.compileCss(resolvedConfig);
}

await uploadFile({ path: cssPath, content: cssContent });

if (theme.jsText) {
await uploadFile({
path: `theme-assets/${theme.id}-menu.js`,
content: theme.jsText,
});
}
if (theme.jsTextPosts) {
await uploadFile({
path: `theme-assets/${theme.id}-posts.js`,
content: theme.jsTextPosts,
});
}
}
}

This iterates all loaded themes (active + inactive), uploading each one's assets. Inactive themes' CSS files exist on Flexweg as well — they're not referenced by any current published page, but they're available in case you switch back.

The admin shows a progress log with one entry per file. Errors are funneled through the toast system (and FlexwegApiErrors rethrown so the calling code can react).

Sync vs Regenerate

ActionWhat it doesWhen to use
Sync theme assetsUploads theme-assets/<id>.css + -menu.js + -posts.jsAfter CSS / JS file changes
Regenerate site → All HTMLRe-renders every published HTML pageAfter template / hooks / settings changes
Regenerate site → Home page onlyRe-renders just /index.htmlAfter home-mode changes
Regenerate site → Theme assetsSame as Sync (alias)Same use cases
Regenerate site → EverythingSync + All HTML + every plugin's regen targetAfter theme switch or major settings change

If you're unsure, Everything is always safe (idempotent — running it multiple times produces the same result). It's slower for large sites but doesn't break anything.

Cache implications

Browsers may cache /theme-assets/<id>.css aggressively (HTTP caching, CDN caching). After a sync, your visitors may keep seeing the old CSS until:

  • Their browser cache TTL expires
  • They hard-refresh (Cmd+Shift+R / Ctrl+F5)
  • The CDN cache expires (configure your CDN's TTL appropriately)

The CMS does not version the theme CSS URL with a hash (would require regenerating every published page). For most cases, browser/CDN caches respect short TTLs and refresh within minutes. For sites where this is a hard problem (you need instant CSS updates):

  • Set Flexweg's Cache-Control headers to no-cache for /theme-assets/* (if your plan supports custom headers)
  • Append ?v=<timestamp> to the link in BaseLayout (would require theme code change)
  • Or live with the eventual consistency (~few minutes)

Continue