Deploy and purge¶
The repository builds two Workers -- the site worker (src/index.ts) and the
media worker (src/media/index.ts) -- across five Wrangler environments. This
page covers the environment layout, the deploy and dry-run scripts, the secrets
each env needs, and the cache-purge endpoint including the hostname-scoped
purge.
Source:
wrangler.toml,package.json,src/admin/purge.ts,src/cache/index.ts.
Environment layout¶
wrangler.toml defines five [env.*] blocks. Three run the site worker, two
run the media worker.
| Env | Worker name | Worker | Route | Notes |
|---|---|---|---|---|
site-stage |
cms-cf-worker-stage |
site | stg.wantskicks.com/* (zone) |
Stage site worker, KV-backed. |
site-stage-mk2 |
cms-cf-worker-stage-mk2 |
site | stg2.wantskicks.com (custom_domain) |
P1 generic-engine canary on stg2; runs the CSS override. |
site-prod |
cms-cf-worker-prod |
site | wantskicks.com/* (zone) |
Production site worker. |
media-stage |
cms-cf-media-stage |
media | stg.wantskicks.com/cmp-media/*, stg2.wantskicks.com/cmp-media/* (zone) |
Serves stage and stg2 media from the stage S3 bucket. |
media-prod |
cms-cf-media-prod |
media | wantskicks.com/cmp-media/* (zone) |
Production media worker. |
A few details worth calling out:
site-stage-mk2is the stg2 canary. It deploys the data-driven engine in parallel with the legacy stage worker, on acustom_domainrather than a zone route.custom_domain = truelets Wrangler provision the stg2 DNS record and TLS cert without a manual edit on the prod zone. It also carries the CSS override env vars (see CSS override).- The media worker route is more specific than the stg2 custom domain. A
worker route at
stg2.wantskicks.com/cmp-media/*beats the custom domain for that subpath, somedia-stageserves stg2's media from the same stage bucket as stg. - Only the site worker uses KV. Each site env binds a
KVnamespace (with per-env namespace ids inwrangler.toml). The media worker is stateless -- edge Cache API only, no KV.
Site worker env vars¶
Each site env sets non-secret vars in its [env.*.vars] table:
CMS_API_BASE_URL (the CMS public v2 API base -- cms-api-stg.skyneto.com for
stage, cms-api-prd.skyneto.com for prod), CMS_SITE_ID (WK), and
PAGE_TYPE_TTLS (per-page-type cache TTLs). site-stage-mk2 additionally sets
CSS_OVERRIDE_SLUG and CSS_OVERRIDE_VERSION.
Media worker env vars¶
Each media env sets S3_BUCKET (cms-media-stg-891708857119 for stage,
cms-media-891708857119 for prod), S3_REGION (us-east-1), and
MEDIA_CACHE_TTL (604800, 7 days).
Deploy and dry-run scripts¶
package.json wraps wrangler deploy --env <env> in npm scripts:
"deploy:site-stage": "wrangler deploy --env site-stage",
"deploy:site-prod": "wrangler deploy --env site-prod",
"deploy:media-stage": "wrangler deploy --env media-stage",
"deploy:media-prod": "wrangler deploy --env media-prod",
"dry-run:site-stage": "wrangler deploy --dry-run --env site-stage",
"dry-run:site-prod": "wrangler deploy --dry-run --env site-prod",
"dry-run:media-stage": "wrangler deploy --dry-run --env media-stage",
"dry-run:media-prod": "wrangler deploy --dry-run --env media-prod"
Each dry-run:* script builds and validates the bundle for that env without
publishing -- use it as a pre-flight check before the matching deploy:*.
Deploying the stg2 canary
There is no deploy:site-stage-mk2 npm script. The stg2 canary is deployed
directly: wrangler deploy --env site-stage-mk2. This is the command the
CSS-override switch references (see CSS override).
The lint and test scripts (npm run lint, npm test) do not read docs/ and
are unaffected by the documentation package.
Required secrets¶
Secrets are never placed in the vars table or committed to source. They are
set per env with wrangler secret put <NAME> --env <env>:
| Secret | Used by | Purpose |
|---|---|---|
CMS_API_KEY |
site | Bearer token for the CMS public v2 API (cmsFetch). |
ADMIN_PURGE_SECRET |
site | Bearer token for POST /__cms/purge and the ?_preview= bypass. |
AWS_ACCESS_KEY_ID |
media | S3 credentials for media reads. |
AWS_SECRET_ACCESS_KEY |
media | S3 credentials for media reads. |
The KV namespace ids in wrangler.toml are environment-specific; create them
with wrangler kv:namespace create on first deploy and fill in the ids per env.
Cache purge: POST /__cms/purge¶
Purge clears cached pages and settings so a change becomes visible without
waiting out a TTL. The endpoint takes absolute priority in handleRequest (step
1) and bypasses every cache layer.
handlePurge (src/admin/purge.ts) requires POST and an
Authorization: Bearer <ADMIN_PURGE_SECRET> header, and host is always
required in the body. It accepts three body shapes.
Single URL¶
curl -X POST https://stg.wantskicks.com/__cms/purge \
-H "Authorization: Bearer $ADMIN_PURGE_SECRET" \
-H "content-type: application/json" \
-d '{"host": "stg.wantskicks.com", "url": "/some-article"}'
List of URLs¶
curl -X POST https://stg.wantskicks.com/__cms/purge \
-H "Authorization: Bearer $ADMIN_PURGE_SECRET" \
-H "content-type: application/json" \
-d '{"host": "stg.wantskicks.com", "urls": ["/a", "/b", "/c"]}'
A single url and a urls list are both routed to purge
(src/cache/index.ts), which deletes each (host, pathname) entry from both the
Cache API and KV. URLs are normalized to their pathname (query stripped) to match
the page cache key.
Hostname-scoped (site-wide)¶
curl -X POST https://stg.wantskicks.com/__cms/purge \
-H "Authorization: Bearer $ADMIN_PURGE_SECRET" \
-H "content-type: application/json" \
-d '{"host": "stg.wantskicks.com", "site": true}'
site: true routes to purgeSite (src/cache/index.ts), which clears the whole
host at once:
export async function purgeSite(host: string, env: SiteEnv): Promise<string[]> {
const prefix = `${host}:`;
const purged: string[] = [];
let cursor: string | undefined;
do {
const listing = await env.KV.list({ prefix, cursor });
for (const k of listing.keys) {
await env.KV.delete(k.name);
purged.push(k.name);
}
cursor = listing.list_complete ? undefined : listing.cursor;
} while (cursor);
await env.KV.delete(`site:${host}`);
purged.push(`site:${host}`);
// ... also deletes the site-settings Cache API entry
}
It enumerates every KV page entry under the <host>: prefix and deletes it, then
deletes the KV site-settings entry (site:<host>) and the Cache API
site-settings entry. KV is authoritative here; per-page Cache API entries are
best-effort because Cloudflare does not expose a list or tag API to a Worker for
deleting them in bulk.
Why hostname-scoped purge is needed to switch CSS site-wide¶
A rendered page has its stylesheet <link> baked into the cached HTML. When the
design changes (for example bumping css_version, or switching the CSS override
on stg2), the future renders link the new stylesheet, but every
already-cached page keeps the old link until it expires. Purging a single URL
fixes only that page. The hostname-scoped site: true purge clears every page
for the host in one call, so the whole site re-renders with the new link on the
next request. This is the purge that pairs with a redeploy when switching the
CSS override.
Health: POST-free /__cms/health¶
/__cms/health (handled in step 1, src/admin/health.ts) is the lightweight
liveness endpoint, also cache-bypassing. Use it for uptime checks; use the purge
endpoint for cache invalidation.