CSS override (per-worker)¶
A site's stylesheet normally follows its active template in the CMS database -- the design every worker on that site shares. The CSS override lets a single worker render a different template's stylesheet without touching that shared template, so one deployment can preview or canary a design in isolation.
Source:
src/index.ts,src/assets/serve.ts,src/layout/index.ts,wrangler.toml.
What the override does¶
Two optional env vars on the worker enable it:
CSS_OVERRIDE_SLUG-- the template slug whose CSS to serve.CSS_OVERRIDE_VERSION-- that template'scss_version.
When both are set, handleRequest cosmetically rewrites the resolved settings'
active_template in memory, after resolveSite returns:
// mk2 canary: per-worker CSS override. Render a chosen template's stylesheet
// without touching the shared site's active template (which carries layout +
// routing for every worker on this site). active_template is read only for the
// CSS <link>, so overriding its slug/css_version here is purely cosmetic and
// isolated to this worker. Idempotent: the same constant values each request.
if (env.CSS_OVERRIDE_SLUG && env.CSS_OVERRIDE_VERSION) {
settings.site_settings.active_template = {
...(settings.site_settings.active_template ?? {}),
slug: env.CSS_OVERRIDE_SLUG,
css_version: env.CSS_OVERRIDE_VERSION,
};
}
Three properties make this safe:
- Cosmetic.
active_templateis read only to build the stylesheet<link>. Layout and routing come from the descriptors, not from this field, so overriding it changes only the CSS the page links to. - Isolated to this worker. The change is to the in-memory settings of this worker's request only. The shared template row in the CMS database is never written, so other workers on the same site are unaffected.
- Idempotent. The same two constant values are applied on every request.
How the link is emitted: buildStyle¶
buildStyle (src/layout/index.ts) reads active_template.slug and
css_version and emits a versioned, immutable stylesheet link:
const active = ss.active_template;
const slug = typeof active?.slug === "string" ? active.slug : "";
const cssVersion = typeof active?.css_version === "string" ? active.css_version : "";
const linkTag =
slug && cssVersion
? `<link rel="stylesheet" href="/_assets/styles/${encodeURIComponent(slug)}/${encodeURIComponent(cssVersion)}.css">`
: `<link rel="stylesheet" href="/_assets/styles/site.css?v=${STYLESHEET_VERSION}">`;
With the override set, slug and cssVersion are the override values, so the
page links to /_assets/styles/<override-slug>/<override-version>.css. When no
template is set, it falls back to the bundled single-file stylesheet so the page
is never left without CSS.
How the CSS is served: serveTemplateCss¶
A request for /_assets/styles/<slug>/<version>.css is parsed by
parseTemplateCssPath (step 1b in src/index.ts) and served by
serveTemplateCss (src/assets/serve.ts). The bytes come from the CMS
database, fetched over the public v2 API -- not from R2:
const path = `/public/v2/templates/${encodeURIComponent(safeSlug)}/css?v=${encodeURIComponent(safeVersion)}`;
// Long edge cache on the subrequest; the versioned ?v busts it on change.
const resp = await cmsFetch(path, env, { cacheTtl: 86400 });
if (resp.status !== 200) {
return new Response("Not found", { status: 404 });
}
const css = await resp.text();
return new Response(css, {
status: 200,
headers: {
"content-type": "text/css; charset=utf-8",
"cache-control": "public, max-age=31536000, immutable",
"x-cms-css-source": "db",
},
});
Notes:
- The served response carries
x-cms-css-source: db, making the DB origin observable. - The subrequest to the CMS uses an 86400 s (
cacheTtl) edge cache (the L4cflayer; see Caching). The?v=<version>is part of the URL, so a newcss_versionis a new cache key -- the CSS propagates without waiting out the 24 h TTL and without a worker redeploy. - On any miss or upstream error,
serveTemplateCssreturns 404 and step 1b insrc/index.tsfalls back to the bundled stylesheet -- a missing asset never 500s a page.
Worked example: the stg2 mk2 canary¶
wrangler.toml runs the override on the site-stage-mk2 worker (the stg2
canary) to render the editorial-magazine design while leaving stg's WK template
untouched:
[env.site-stage-mk2.vars]
CMS_API_BASE_URL = "https://cms-api-stg.skyneto.com"
CMS_SITE_ID = "WK"
# Per-worker CSS override: stg2 renders this template's stylesheet WITHOUT
# changing WK's active template in the DB, so stg is never affected.
CSS_OVERRIDE_SLUG = "editorial-magazine"
CSS_OVERRIDE_VERSION = "07a2889d"
The wrangler comment lists the templates available to switch between:
celebrity-v1/66bcae1a (original), celebrity-sunset/3f9e9aa8 (recolor), and
editorial-magazine/07a2889d (full serif/cream reskin).
Switching the override (and why you must purge by hostname)¶
To change the stg2 palette:
- Edit
CSS_OVERRIDE_SLUG/CSS_OVERRIDE_VERSIONin thesite-stage-mk2block ofwrangler.toml. - Redeploy that env:
wrangler deploy --env site-stage-mk2. The override lives in the worker's vars, so this step is mandatory -- the change cannot take effect without it. The redeploy also clears the isolate memMap (see Caching). - Purge stg2's edge cache by hostname so every page picks up the new link, not just the homepage.
Step 3 is the subtle one. Already-rendered pages sit in the edge cache with the
old stylesheet <link> baked into their HTML. Bumping the override changes the
markup of future renders, but the cached pages keep the old link until they
expire. A per-URL purge would only fix the pages you list; a hostname-scoped
purge clears the whole site at once. That is exactly what purgeSite does -- see
the site: true purge in Deploy and purge.