From 4f8d0f44fbd49fe00781fb26084985a4c094b865 Mon Sep 17 00:00:00 2001 From: documentation-specialist Date: Tue, 19 May 2026 12:04:55 -0700 Subject: [PATCH] docs(cache): set Vercel edge Cache-Control for HTML pages (RFC#562 step 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per internal#562 audit, HTML pages on docs.moleculesai.app respond with `Cache-Control: max-age=0, must-revalidate` while Vercel Edge is HITting them. That means a browser round-trip to the edge on every navigation just to get a 304 — no benefit from edge cache being warm. Adds a single `headers()` rule in next.config.mjs that sets `public, max-age=0, s-maxage=300, stale-while-revalidate=86400` on every path EXCEPT Next.js internals (/_next/static and /_next/image — already immutable and uncacheable-override per Next.js docs) and /api/* (app-controlled cache). The source pattern `/((?!_next/static|_next/image|api/).*)` uses path-to-regexp negative lookahead — same pattern Next.js's own proxy.js doc recommends for negative matching. This site has no /public/ dir so there are no unhashed brand assets to configure separately — those will inherit the same HTML cache rule, which is the right default for our content (changelog/docs MDX, not high-churn). Expected impact: edge-HIT ratio on HTML pages rises from ~0% to >90% during typical nav bursts (5 min freshness) and 99%+ for repeat visits within 24 h (stale-while-revalidate window). Hashed _next/static assets retain their `immutable, max-age=31536000` headers — Next.js sets these and they cannot be overridden in next.config. RFC: internal#562 (step 1 — Vercel side; CF cache rules tracked separately) --- next.config.mjs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/next.config.mjs b/next.config.mjs index 457dcf2..a0eb9f8 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -2,9 +2,33 @@ import { createMDX } from 'fumadocs-mdx/next'; const withMDX = createMDX(); +// HTML pages: short edge cache + long stale-while-revalidate. Lets Vercel Edge +// serve repeat navigations from cache (~5 min fresh, 24 h stale-while-revalidate +// in the background) while keeping the browser revalidating on every nav. The +// negative lookahead leaves Next.js's own _next/static (immutable, hash-named) +// and _next/image cache headers untouched. +const HTML_CACHE_CONTROL = + 'public, max-age=0, s-maxage=300, stale-while-revalidate=86400'; + /** @type {import('next').NextConfig} */ const config = { reactStrictMode: true, + async headers() { + return [ + { + // Match every path except Next.js internals and API routes — those + // already have correct cache headers (immutable for hashed assets, + // app-controlled for /api). + source: '/((?!_next/static|_next/image|api/).*)', + headers: [ + { + key: 'Cache-Control', + value: HTML_CACHE_CONTROL, + }, + ], + }, + ]; + }, }; export default withMDX(config); -- 2.52.0