Repository navigation
perf(seo): serve the trending boards from Workers Cache - #329
Merged
Merged
Conversation
Workers Cache keys on the path and query, never the host, and www routes to the same Worker. By the time the canonical host middleware runs, a route rule's edge cache headers are already on the response, so a cached page's www 301 could be stored and served to the apex URL, which would redirect to itself. The redirect now always says no-store.
wrangler dev has no Workers Cache, so nothing local can show that a page is stored or that storing it is safe. pnpm production:edge-cache checks the deployed trending boards: a repeat anonymous visit is a cache hit, no anonymous response sets a cookie, Accept: text/markdown still gets the 307, and a request with a session cookie gets the anonymous render. The deploy workflow runs it after the rollback-gated smoke. It fails the job without rolling back, because the rollback smoke re-checks the previous version, which has no cache rule to pass it with.
The first HTML in the edge cache, to prove the setup on one page family before skill, repo and category pages follow. 60 seconds fresh adds at most a minute to a feed that already caches for five. An hour of stale while revalidate lets a quiet colo serve one old copy while it refreshes, since the board's inputs move every 15 minutes at most. nuxt-skew-protection now loads before nuxt-cloudflare. Both judge each HTML response in beforeResponse, in module order. With nuxt-cloudflare first it saw the __nkpv version cookie that skew protection was about to drop and marked every browser navigation no-store, so only crawlers could have filled the cache.
2 tasks done
harlan-zw
added this pull request to stack #330
September 30, 2026 06:37
Collaborator
Author
|
🤖 Agent verification on a local
|
A failing check skipped the later DX report steps, which run on success by default. Running it last keeps them.
A hung edge blocked the deploy job until the 20 minute limit.
A failed fetch still rendered HTTP 200, so the edge would store the error state and its noindex meta.
Collaborator
Author
🤖 REVIEWING · 35% · Git worktree ready
Next: Review the diff.
Leave unchecked to finish Review after merge. |
harlan-zw
added a commit
that referenced
this pull request
Sep 30, 2026
…dge-cache-trending
The check now fails when two boards render the same title and canonical URL, and retries a transient non-200 once.
Contributor
🤖 MERGED
GitHub merged this pull request.
Review completed. No finding above 80/100. Selected findings run after merge and open separate pull requests. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #328.
❓ Type of change
📚 Description
#328 made public HTML the same for every visitor. This turns Workers Cache on for one page family,
/skills/trendingand its?range=boards, so we can watch it in production before skill, repo and category pages follow. Every other page keeps theprivate, no-storedefault.The rule is
edgeCache({ maxAge: 60, staleWhileRevalidate: 3600 }):/api/feed/trending) already caches for 300s, so the edge adds at most a minute on a busy colo.sync-x-mentions) and hourly (social mentions, X engagement). A quiet colo serves one copy up to an hour old and refreshes it in the background, instead of rendering on every visit.no-storeand ask the edge each time.The Workers Cache key is the path plus the query string (and the Worker version), so
week,monthandallnever share an entry. Parameter order matters, so a reordered or padded query is its own entry and its own render.One ordering bug showed up on a local build. nuxt-cloudflare and nuxt-skew-protection both judge each HTML response in
beforeResponse, in module order. nuxt-cloudflare ran first, saw the__nkpvversion cookie that skew protection was about to drop, and marked every browser navigationno-store. Only requests withoutSec-Fetch-Dest: document(crawlers) would have been stored, andVary: Sec-Fetch-Destkeeps browsers on a separate variant, so browsers would never have hit.nuxt-skew-protectionnow loads before@harlan-zw/nuxt-cloudflare. That ordering is implicit; it probably wants fixing in nuxt-cloudflare so the cookie check runs after other modules' hooks.The key has no host, and
www.skilld.devroutes to the same Worker since #316. A route rule's cache headers are on the event before the canonical host middleware sends its 301, so a stored www redirect could have answered the apex URL and looped. That redirect now always saysno-store. I checked production first: the www 301 on/api/clustersalready answerscf-cache-status: BYPASS, but I could not tell why, so I'd rather not rely on it.pnpm production:edge-cache(scripts/check-edge-cache.ts) proves it against the deployed site, per board:cf-cache-status: HIT,STALEorUPDATING(up to 12 tries, since the key includes the new Worker version)Varyis exactlyAccept, Sec-Fetch-DestAccept: text/markdownstill gets the 307 to/skills/trending.mdnuxt-sessioncookie gets the anonymous payload andloadStrategy: client-only, and no new session cookieThe deploy workflow runs it after
production:deploy. It fails the job but does not roll back. The rollback smoke re-runs against the previous version, and a version from before this rule could never pass it, so it can't live there.Rollout: watch the deploy's edge cache step and
cf-cache-statuson trending for a week. If it holds, a follow-up adds the same rule to skill, repo and category pages and extendsEDGE_CACHED_PATHS. Those pages render more per-skill state, so I'd check each one's payload for anything request dependent first.nuxt.config.tsoverlaps #320, #322, #323, #325 and #326. Only #320 conflicts, on the samenitro.handlersline as #328.scripts/lib/production-smoke.tsis untouched.