diff --git a/next.config.ts b/next.config.ts index e9ffa30..72f70b9 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,65 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + /** + * Cache-Control policy. + * + * Why this exists: + * Hostinger's CDN was applying `s-maxage=31536000` (1 year) to + * prerendered HTML pages by default. When a new deploy shipped + * fresh Turbopack chunk hashes, the edge kept serving year-old + * HTML referencing chunk filenames that no longer existed on + * disk — result: HTML 200, every /_next/static/*.js and .css + * came back 404, the page rendered unstyled. Private/incognito + * did nothing because the cache is server-side. + * + * Strategy: + * - /_next/static/* — immutable for a year. Filenames are + * content-hashed, so a new build produces new filenames; the + * old ones are safe to keep indefinitely in caches. + * - /api/* — no-store. API responses are per-user and + * must never be shared across requests at the edge. + * - Everything else — public, brief s-maxage + generous + * stale-while-revalidate. The edge serves instantly from cache + * for the first 5 min, then returns cached content while + * refreshing in the background for up to 24 h. A deploy's + * chunk-hash drift self-heals within ~5 min with no user- + * visible latency. + * + * Note: dynamic dashboard routes (/inbox, /contacts, /pipelines, + * /broadcasts, etc.) are server-rendered per request — Next.js + * and Supabase auth already prevent them from being served + * from a shared cache. The s-maxage here is a ceiling; Next.js + * and auth middleware still set `private` / `no-store` for + * per-user responses. + */ + async headers() { + return [ + { + source: "/_next/static/:path*", + headers: [ + { + key: "Cache-Control", + value: "public, max-age=31536000, immutable", + }, + ], + }, + { + source: "/api/:path*", + headers: [{ key: "Cache-Control", value: "no-store" }], + }, + { + source: "/:path*", + headers: [ + { + key: "Cache-Control", + value: + "public, max-age=0, s-maxage=300, stale-while-revalidate=86400", + }, + ], + }, + ]; + }, }; export default nextConfig;