[{"data":1,"prerenderedAt":1717},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations":3,"all-docs-nav":1182},{"id":4,"title":5,"body":6,"breadcrumb":1157,"dateModified":1167,"datePublished":1167,"description":1168,"extension":1169,"faq":1170,"meta":1175,"navigation":1176,"path":1177,"seo":1178,"slug":12,"stem":1179,"type":1180,"__hash__":1181},"content\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations\u002Findex.md","Next.js App Router Static Export Limitations",{"type":7,"value":8,"toc":1135},"minimark",[9,13,21,35,40,55,59,87,211,215,402,407,419,581,592,596,603,691,698,702,716,845,849,888,892,911,915,923,927,933,993,997,1048,1052,1058,1062,1066,1069,1073,1076,1080,1083,1087,1090,1094,1131],[10,11,5],"h1",{"id":12},"nextjs-app-router-static-export-limitations",[14,15,16,20],"p",{},[17,18,19],"code",{},"output: 'export'"," turns a Next.js App Router project into a folder of HTML, CSS, JavaScript and RSC payload files that any static host can serve. For content sites that is often exactly right: React Server Components still run, at build time, and the result deploys to a CDN with no server. But the App Router was designed around a server, and a significant set of its features either do not work in an export or behave differently. Teams usually discover them one build error at a time.",[14,22,23,24,29,30,34],{},"This guide lists each limitation in one place, explains why it exists, and gives the static equivalent — from the host's configuration, an edge function, or a build-time pattern. It is part of ",[25,26,28],"a",{"href":27},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002F","Next.js Static Export for Content Sites",", complementing ",[25,31,33],{"href":32},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export\u002F","Handling Dynamic Routes in Next.js Static Export",".",[36,37,39],"h2",{"id":38},"prerequisites","Prerequisites",[41,42,43,49,52],"ul",{},[44,45,46,47,34],"li",{},"A Next.js 14 or 15 App Router project with ",[17,48,19],{},[44,50,51],{},"A static host with redirect, header and function support (Cloudflare Pages\u002FWorkers, Netlify, Vercel, or S3 with CloudFront).",[44,53,54],{},"The build log from a first export attempt — the errors list most limitations for you.",[36,56,58],{"id":57},"the-rule-behind-every-limitation","The Rule Behind Every Limitation",[14,60,61,62,66,67,70,71,74,75,78,79,82,83,86],{},"Everything that runs at ",[63,64,65],"strong",{},"build time"," works. Everything that must run ",[63,68,69],{},"per request"," does not, because a static export has no request-time runtime. Server Components, ",[17,72,73],{},"fetch"," in Server Components, ",[17,76,77],{},"generateStaticParams",", ",[17,80,81],{},"generateMetadata"," and static route handlers all run during ",[17,84,85],{},"next build"," and write their output to files. Cookies, headers, search params on the server, middleware, revalidation and on-demand image optimisation all need a request, and so fail or are disabled.",[88,89,90,207],"figure",{},[91,92,99,100,99,104,99,108,99,115],"svg",{"viewBox":93,"role":94,"ariaLabelledBy":95,"xmlns":98},"0 0 760 300","img",[96,97],"nxl-rule-title","nxl-rule-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[101,102,103],"title",{"id":96},"Build-time features work, request-time features do not",[105,106,107],"desc",{"id":97},"Two columns. Build time, supported: Server Components, fetch during build, generateStaticParams, generateMetadata, static GET route handlers, client components. Request time, unsupported in export: cookies and headers, server-side searchParams, middleware, ISR and revalidate, server actions, the default image optimiser, dynamic route handlers.",[109,110],"rect",{"x":111,"y":111,"width":112,"height":113,"fill":114},"0","760","300","#ffffff",[116,117,119,120,119,128,119,139,119,145,119,150,119,154,119,157,119,160,119,164,119,168,119,174,119,180,119,184,119,188,119,191,119,194,119,197,119,200,119,203,99],"g",{"style":118},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[121,122,127],"text",{"x":123,"y":124,"fill":125,"style":126},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","One question sorts every feature: when does it run?",[109,129],{"x":130,"y":131,"width":132,"height":133,"rx":134,"fill":135,"opacity":136,"stroke":137,"style":138},"40","50","320","226","12","#8ac926","0.1","#5a8a16","stroke-width:1.5px",[121,140,144],{"x":141,"y":142,"fill":125,"style":143},"200","76","font-size:14px;font-weight:700;text-anchor:middle","Build time — works",[121,146,149],{"x":147,"y":148,"fill":125},"62","108","Server Components",[121,151,153],{"x":147,"y":152,"fill":125},"132","fetch during build",[121,155,77],{"x":147,"y":156,"fill":125},"156",[121,158,81],{"x":147,"y":159,"fill":125},"180",[121,161,163],{"x":147,"y":162,"fill":125},"204","static GET route handlers",[121,165,167],{"x":147,"y":166,"fill":125},"228","client components",[121,169,173],{"x":147,"y":170,"fill":171,"style":172},"258","#3f6410","font-size:11px;font-weight:700","output written to files",[109,175],{"x":176,"y":131,"width":132,"height":133,"rx":134,"fill":177,"opacity":178,"stroke":179,"style":138},"400","#ff595e","0.08","#d83b41",[121,181,183],{"x":182,"y":142,"fill":125,"style":143},"560","Request time — not in export",[121,185,187],{"x":186,"y":148,"fill":125},"422","cookies(), headers()",[121,189,190],{"x":186,"y":152,"fill":125},"server searchParams",[121,192,193],{"x":186,"y":156,"fill":125},"middleware",[121,195,196],{"x":186,"y":159,"fill":125},"ISR \u002F revalidate",[121,198,199],{"x":186,"y":162,"fill":125},"server actions",[121,201,202],{"x":186,"y":166,"fill":125},"default image optimiser",[121,204,206],{"x":186,"y":170,"fill":205,"style":172},"#b32b30","move to host config or edge functions",[208,209,210],"figcaption",{},"Every limitation below is a request-time feature; every workaround moves the work to build time or to the edge.",[36,212,214],{"id":213},"limitation-by-limitation","Limitation by Limitation",[216,217,218,234],"table",{},[219,220,221],"thead",{},[222,223,224,228,231],"tr",{},[225,226,227],"th",{},"Feature",[225,229,230],{},"In export",[225,232,233],{},"Static equivalent",[235,236,237,253,287,300,316,333,351,361,371,384],"tbody",{},[222,238,239,247,250],{},[240,241,242,243,246],"td",{},"Middleware (",[17,244,245],{},"middleware.ts",")",[240,248,249],{},"not supported",[240,251,252],{},"host redirects\u002Fheaders files; edge function for logic",[222,254,255,271,274],{},[240,256,257,260,261,260,264,267,268],{},[17,258,259],{},"redirects()"," \u002F ",[17,262,263],{},"rewrites()",[17,265,266],{},"headers()"," in ",[17,269,270],{},"next.config.js",[240,272,273],{},"ignored",[240,275,276,260,279,282,283,286],{},[17,277,278],{},"_redirects",[17,280,281],{},"_headers"," (Cloudflare, Netlify), ",[17,284,285],{},"vercel.json",", CloudFront Functions",[222,288,289,295,297],{},[240,290,291,292,246],{},"ISR (",[17,293,294],{},"revalidate",[240,296,249],{},[240,298,299],{},"scheduled rebuilds or build hooks on content change",[222,301,302,307,310],{},[240,303,304,305],{},"Dynamic routes without ",[17,306,77],{},[240,308,309],{},"build error",[240,311,312,313],{},"enumerate every param; ",[17,314,315],{},"dynamicParams = false",[222,317,318,328,330],{},[240,319,320,78,323,78,325],{},[17,321,322],{},"cookies()",[17,324,266],{},[17,326,327],{},"draftMode()",[240,329,309],{},[240,331,332],{},"client-side reading; edge function for personalisation",[222,334,335,341,344],{},[240,336,337,340],{},[17,338,339],{},"searchParams"," in Server Components",[240,342,343],{},"empty at build",[240,345,346,347,350],{},"read ",[17,348,349],{},"useSearchParams"," in a client component",[222,352,353,356,358],{},[240,354,355],{},"Route handlers (non-GET or request-reading)",[240,357,249],{},[240,359,360],{},"serverless function on the host",[222,362,363,366,368],{},[240,364,365],{},"Server Actions",[240,367,249],{},[240,369,370],{},"form posting to a function endpoint",[222,372,373,379,381],{},[240,374,375,378],{},[17,376,377],{},"next\u002Fimage"," default loader",[240,380,309],{},[240,382,383],{},"custom loader or build-time variants",[222,385,386,393,395],{},[240,387,388,389,392],{},"Internationalised routing (",[17,390,391],{},"i18n"," config)",[240,394,249],{},[240,396,397,398,401],{},"explicit locale segments ",[17,399,400],{},"\u002F[lang]\u002F…"," with static params",[403,404,406],"h3",{"id":405},"redirects-and-headers","Redirects and Headers",[14,408,409,410,412,413,415,416,418],{},"The ",[17,411,259],{}," and ",[17,414,266],{}," functions in ",[17,417,270],{}," are applied by the Next.js server, which does not exist in an export. They are silently ignored — the most dangerous limitation because nothing fails. Generate the host's native file at build time from the same source so they stay in sync:",[420,421,426],"pre",{"className":422,"code":423,"language":424,"meta":425,"style":425},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F scripts\u002Femit-redirects.mjs — run after `next build`\nimport cfg from '..\u002Fredirects.config.mjs';\nimport { writeFileSync } from 'node:fs';\nwriteFileSync('out\u002F_redirects', cfg.map((r) => `${r.source} ${r.destination} ${r.permanent ? 301 : 302}`).join('\\n') + '\\n');\n","js","",[17,427,428,437,458,473],{"__ignoreMap":425},[429,430,433],"span",{"class":431,"line":432},"line",1,[429,434,436],{"class":435},"sJ8bj","\u002F\u002F scripts\u002Femit-redirects.mjs — run after `next build`\n",[429,438,440,444,448,451,455],{"class":431,"line":439},2,[429,441,443],{"class":442},"szBVR","import",[429,445,447],{"class":446},"sVt8B"," cfg ",[429,449,450],{"class":442},"from",[429,452,454],{"class":453},"sZZnC"," '..\u002Fredirects.config.mjs'",[429,456,457],{"class":446},";\n",[429,459,461,463,466,468,471],{"class":431,"line":460},3,[429,462,443],{"class":442},[429,464,465],{"class":446}," { writeFileSync } ",[429,467,450],{"class":442},[429,469,470],{"class":453}," 'node:fs'",[429,472,457],{"class":446},[429,474,476,480,483,486,489,492,495,499,502,505,508,510,512,515,518,520,522,525,527,529,531,534,537,541,544,547,550,553,556,558,561,564,566,568,571,574,576,578],{"class":431,"line":475},4,[429,477,479],{"class":478},"sScJk","writeFileSync",[429,481,482],{"class":446},"(",[429,484,485],{"class":453},"'out\u002F_redirects'",[429,487,488],{"class":446},", cfg.",[429,490,491],{"class":478},"map",[429,493,494],{"class":446},"((",[429,496,498],{"class":497},"s4XuR","r",[429,500,501],{"class":446},") ",[429,503,504],{"class":442},"=>",[429,506,507],{"class":453}," `${",[429,509,498],{"class":446},[429,511,34],{"class":453},[429,513,514],{"class":446},"source",[429,516,517],{"class":453},"} ${",[429,519,498],{"class":446},[429,521,34],{"class":453},[429,523,524],{"class":446},"destination",[429,526,517],{"class":453},[429,528,498],{"class":446},[429,530,34],{"class":453},[429,532,533],{"class":446},"permanent",[429,535,536],{"class":442}," ?",[429,538,540],{"class":539},"sj4cs"," 301",[429,542,543],{"class":442}," :",[429,545,546],{"class":539}," 302",[429,548,549],{"class":453},"}`",[429,551,552],{"class":446},").",[429,554,555],{"class":478},"join",[429,557,482],{"class":446},[429,559,560],{"class":453},"'",[429,562,563],{"class":539},"\\n",[429,565,560],{"class":453},[429,567,501],{"class":446},[429,569,570],{"class":442},"+",[429,572,573],{"class":453}," '",[429,575,563],{"class":539},[429,577,560],{"class":453},[429,579,580],{"class":446},");\n",[14,582,583,584,412,588,34],{},"Redirect semantics per host are covered in ",[25,585,587],{"href":586},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fconfiguring-redirects-on-cloudflare-pages\u002F","Configuring Redirects on Cloudflare Pages",[25,589,591],{"href":590},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-redirects-and-rewrites-for-static-sites\u002F","Netlify Redirects and Rewrites for Static Sites",[403,593,595],{"id":594},"isr-and-freshness","ISR and Freshness",[14,597,598,599,34],{},"Incremental Static Regeneration regenerates pages on a server after a time or on demand. Its static equivalent is a rebuild: triggered on a schedule for time-based freshness, or by a CMS webhook for on-demand updates. For a 1,200-page content site with an 80-second build, a webhook-triggered rebuild published a CMS change in about two minutes — slower than ISR's seconds, but without a server. The comparison is in ",[25,600,602],{"href":601},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-isr-vs-static-generation-for-ssgs\u002F","Vercel ISR vs Static Generation for SSGs",[88,604,605,688],{},[91,606,99,611,99,614,99,617,99,620],{"viewBox":607,"role":94,"ariaLabelledBy":608,"xmlns":98},"0 0 760 240",[609,610],"nxl-fresh-title","nxl-fresh-desc",[101,612,613],{"id":609},"Time from CMS publish to live page",[105,615,616],{"id":610},"Two timelines after an editor publishes. With on-demand ISR, the page is regenerated on the server and live in about 5 seconds. With a static export, a webhook triggers a build of about 80 seconds and a deploy of about 30, so the change is live in about 2 minutes, with a 60 second debounce window added for bursts of edits.",[109,618],{"x":111,"y":111,"width":112,"height":619,"fill":114},"240",[116,621,119,622,119,625,119,631,119,637,119,642,119,646,119,652,119,658,119,665,119,669,119,675,119,679,119,684,99],{"style":118},[121,623,624],{"x":123,"y":124,"fill":125,"style":126},"Publish to live: ISR vs rebuild",[121,626,630],{"x":627,"y":628,"fill":125,"style":629},"30","84","font-weight:700","On-demand ISR",[109,632],{"x":633,"y":634,"width":635,"height":124,"fill":135,"stroke":137,"style":636},"170","66","10","stroke-width:1px",[121,638,641],{"x":639,"y":640,"fill":171,"style":629},"190","85","~5 s",[121,643,645],{"x":627,"y":644,"fill":125,"style":629},"154","Export + hook",[109,647],{"x":633,"y":648,"width":649,"height":124,"fill":650,"stroke":651,"style":636},"136","120","#f8fafc","#556071",[121,653,657],{"x":654,"y":655,"fill":125,"style":656},"230","155","font-size:11px;text-anchor:middle","debounce 60 s",[109,659],{"x":660,"y":648,"width":661,"height":124,"fill":662,"opacity":663,"stroke":664,"style":636},"290","160","#ffca3a","0.35","#a97b00",[121,666,668],{"x":667,"y":655,"fill":125,"style":656},"370","build 80 s",[109,670],{"x":671,"y":648,"width":672,"height":124,"fill":673,"opacity":674,"stroke":673,"style":636},"450","60","#1982c4","0.25",[121,676,678],{"x":677,"y":655,"fill":125,"style":656},"480","deploy",[121,680,683],{"x":681,"y":655,"fill":682,"style":629},"520","#8a6d0f","~2–3 min",[121,685,687],{"x":123,"y":686,"fill":651,"style":656},"210","For a content site, minutes of freshness lag was an easy trade for no server",[208,689,690],{},"The debounce keeps a burst of edits to one build; without it, ten saves in a minute meant ten deploys.",[14,692,693,694,34],{},"For most content teams two minutes is invisible; editors publish and move on. Where it is not — a status page, a live event schedule — a hybrid works: keep the page static, and let a small client component fetch the time-sensitive fragment from an edge function on load, as described in ",[25,695,697],{"href":696},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fproxying-third-party-apis-from-an-edge-function\u002F","Proxying Third-Party APIs from an Edge Function",[403,699,701],{"id":700},"middleware-logic","Middleware Logic",[14,703,704,705,412,708,711,712,34],{},"Authentication gates, geolocation redirects and A\u002FB routing that lived in middleware move to an edge function on the host, which runs before the static file is served. The logic ports nearly unchanged because both use ",[17,706,707],{},"Request",[17,709,710],{},"Response","; see ",[25,713,715],{"href":714},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fprotecting-a-static-site-behind-authentication\u002F","Protecting a Static Site Behind Authentication",[88,717,718,842],{},[91,719,99,724,99,727,99,730,99,733,99,827],{"viewBox":720,"role":94,"ariaLabelledBy":721,"xmlns":98},"0 0 760 280",[722,723],"nxl-move-title","nxl-move-desc",[101,725,726],{"id":722},"Where each server feature goes after export",[105,728,729],{"id":723},"Arrows map server features to static-host equivalents. next.config redirects and headers go to _redirects and _headers files. Middleware goes to an edge function. ISR goes to build hooks and scheduled rebuilds. Server actions and dynamic route handlers go to serverless functions. The image optimiser goes to a custom loader.",[109,731],{"x":111,"y":111,"width":112,"height":732,"fill":114},"280",[116,734,119,735,119,738,119,745,119,749,119,752,119,754,119,757,119,760,119,763,119,767,119,769,119,773,119,778,119,782,119,786,119,789,119,792,119,795,119,797,119,800,119,802,119,805,99],{"style":118},[121,736,737],{"x":123,"y":124,"fill":125,"style":126},"Nothing is lost; it moves to the host",[109,739],{"x":627,"y":740,"width":741,"height":742,"rx":743,"fill":650,"stroke":744,"style":636},"54","250","34","6","#d9e2ef",[121,746,748],{"x":655,"y":142,"fill":125,"style":747},"text-anchor:middle","next.config redirects \u002F headers",[109,750],{"x":627,"y":751,"width":741,"height":742,"rx":743,"fill":650,"stroke":744,"style":636},"98",[121,753,193],{"x":655,"y":649,"fill":125,"style":747},[109,755],{"x":627,"y":756,"width":741,"height":742,"rx":743,"fill":650,"stroke":744,"style":636},"142",[121,758,196],{"x":655,"y":759,"fill":125,"style":747},"164",[109,761],{"x":627,"y":762,"width":741,"height":742,"rx":743,"fill":650,"stroke":744,"style":636},"186",[121,764,766],{"x":655,"y":765,"fill":125,"style":747},"208","server actions, POST handlers",[109,768],{"x":627,"y":654,"width":741,"height":742,"rx":743,"fill":650,"stroke":744,"style":636},[121,770,772],{"x":655,"y":771,"fill":125,"style":747},"252","image optimiser",[109,774],{"x":775,"y":740,"width":776,"height":742,"rx":743,"fill":135,"opacity":777,"stroke":137,"style":636},"460","270","0.18",[121,779,781],{"x":780,"y":142,"fill":125,"style":747},"595","_redirects, _headers (generated)",[109,783],{"x":775,"y":751,"width":776,"height":742,"rx":743,"fill":784,"opacity":785,"stroke":784,"style":636},"#6a4c93","0.14",[121,787,788],{"x":780,"y":649,"fill":125,"style":747},"edge function",[109,790],{"x":775,"y":756,"width":776,"height":742,"rx":743,"fill":662,"opacity":791,"stroke":664,"style":636},"0.24",[121,793,794],{"x":780,"y":759,"fill":125,"style":747},"build hook + scheduled rebuild",[109,796],{"x":775,"y":762,"width":776,"height":742,"rx":743,"fill":784,"opacity":785,"stroke":784,"style":636},[121,798,799],{"x":780,"y":765,"fill":125,"style":747},"serverless function",[109,801],{"x":775,"y":654,"width":776,"height":742,"rx":743,"fill":673,"opacity":785,"stroke":673,"style":636},[121,803,804],{"x":780,"y":771,"fill":125,"style":747},"custom loader \u002F build-time variants",[116,806,809,810,809,815,809,818,809,821,809,824,119],{"stroke":651,"fill":807,"style":808},"none","stroke-width:2px","\n      ",[811,812],"path",{"d":813,"style":814},"M282 71 L456 71","marker-end:url(#nxl-arrow)",[811,816],{"d":817,"style":814},"M282 115 L456 115",[811,819],{"d":820,"style":814},"M282 159 L456 159",[811,822],{"d":823,"style":814},"M282 203 L456 203",[811,825],{"d":826,"style":814},"M282 247 L456 247",[828,829,119,830,99],"defs",{},[831,832,809,839,119],"marker",{"id":833,"viewBox":834,"refX":835,"refY":836,"markerWidth":837,"markerHeight":837,"orient":838},"nxl-arrow","0 0 10 10","8","5","7","auto-start-reverse",[811,840],{"d":841,"fill":651},"M0 0 L10 5 L0 10 z",[208,843,844],{},"The first row is the dangerous one: it is ignored silently rather than failing the build.",[36,846,848],{"id":847},"trailing-slashes-and-client-navigation","Trailing Slashes and Client Navigation",[14,850,851,852,855,856,859,860,863,864,855,867,870,871,875,876,879,880,883,884,887],{},"Two quieter behaviours affect how the exported files are served. By default, Next.js writes ",[17,853,854],{},"about.html"," and links to ",[17,857,858],{},"\u002Fabout","; with ",[17,861,862],{},"trailingSlash: true"," it writes ",[17,865,866],{},"about\u002Findex.html",[17,868,869],{},"\u002Fabout\u002F",". Static hosts differ in how they map extensionless URLs to files, so choose the option that matches the host and assert it in smoke tests — the same issue that arises on S3, described in ",[25,872,874],{"href":873},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3\u002F","Clean URLs and Trailing Slashes on S3",". Client-side navigation with ",[17,877,878],{},"\u003CLink>"," fetches each route's RSC payload (",[17,881,882],{},"index.txt"," or ",[17,885,886],{},"about.txt",") rather than the HTML; the host must serve those files, with a sensible cache lifetime, or navigation silently falls back to full page loads. After a deploy, readers with an open tab request payloads from the previous build, so keep old files available briefly, which atomic hosts do by default.",[36,889,891],{"id":890},"catching-silent-failures","Catching Silent Failures",[14,893,894,895,412,897,899,900,902,903,907,908,910],{},"Most limitations fail the build loudly. The silent ones — ignored ",[17,896,259],{},[17,898,266],{},", and ",[17,901,339],{}," being empty at build time — need tests. After each export, a smoke test against the preview deploy should request a sample of redirect sources and assert the 301s, fetch a page and assert the security headers, and load a page that depends on query parameters in a headless browser to confirm the client component reads them. The pattern is the same as in ",[25,904,906],{"href":905},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url\u002F","Running Smoke Tests Against a Preview URL",". On the site that motivated this guide, 38 redirects defined in ",[17,909,270],{}," had been silently ignored for three months after switching to export; the smoke test would have caught them on the first preview.",[36,912,914],{"id":913},"when-export-is-the-wrong-choice","When Export Is the Wrong Choice",[14,916,917,918,922],{},"If the list of workarounds is long — per-request personalisation on most pages, minute-level freshness for thousands of pages, heavy use of Server Actions — a static export fights the framework. At that point either run Next.js on a server or edge runtime, or choose a generator designed for static output, as compared in ",[25,919,921],{"href":920},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-static-export-vs-astro-for-marketing-sites\u002F","Next.js Static Export vs Astro for Marketing Sites",". For a content site whose dynamic needs are a form, a few redirects and daily freshness, export is a good fit.",[36,924,926],{"id":925},"measured-impact","Measured Impact",[14,928,929,930,932],{},"A 1,200-page App Router content site moved from Vercel's server runtime to ",[17,931,19],{}," on Cloudflare Pages:",[216,934,935,948],{},[219,936,937],{},[222,938,939,942,945],{},[225,940,941],{},"Measure",[225,943,944],{},"Server runtime",[225,946,947],{},"Static export",[235,949,950,961,972,983],{},[222,951,952,955,958],{},[240,953,954],{},"TTFB p75 (RUM)",[240,956,957],{},"210 ms",[240,959,960],{},"44 ms",[222,962,963,966,969],{},[240,964,965],{},"Features needing a workaround",[240,967,968],{},"—",[240,970,971],{},"5 (redirects, headers, ISR, contact form action, images)",[222,973,974,977,980],{},[240,975,976],{},"Content freshness after CMS publish",[240,978,979],{},"~5 s (on-demand ISR)",[240,981,982],{},"~2 min (build hook)",[222,984,985,988,991],{},[240,986,987],{},"Monthly hosting",[240,989,990],{},"20 USD + usage",[240,992,111],{},[36,994,996],{"id":995},"pitfalls-rollback","Pitfalls & Rollback",[41,998,999,1008,1020,1029,1039],{},[44,1000,1001,1007],{},[63,1002,1003,1004,1006],{},"Trusting ",[17,1005,270],{}," redirects."," They are ignored in export; generate host files.",[44,1009,1010,1016,1017,34],{},[63,1011,1012,1015],{},[17,1013,1014],{},"dynamicParams"," left true."," Unlisted paths 404 in production while working in ",[17,1018,1019],{},"next dev",[44,1021,1022,1028],{},[63,1023,1024,1025,1027],{},"Reading ",[17,1026,339],{}," on the server."," It is empty at build time; move the logic into a client component.",[44,1030,1031,1034,1035,1038],{},[63,1032,1033],{},"Forgetting the RSC payload files."," Client navigation fetches ",[17,1036,1037],{},".txt"," payloads; the host must serve them with the right content type.",[44,1040,1041,1044,1045,1047],{},[63,1042,1043],{},"Rollback:"," removing ",[17,1046,19],{}," restores the server runtime; the host must then run Next.js again.",[36,1049,1051],{"id":1050},"conclusion","Conclusion",[14,1053,1054,1055,1057],{},"A Next.js App Router static export keeps everything that runs at build time and drops everything that runs per request. Middleware, ",[17,1056,270],{}," redirects and headers, ISR, server actions and on-demand image optimisation each have a static-host equivalent — generated config files, edge and serverless functions, build hooks and custom loaders. The silent ones need tests. For content sites whose dynamic needs are small, the trade is worth it: on a 1,200-page site, TTFB fell from 210 to 44 ms and hosting cost went to zero.",[36,1059,1061],{"id":1060},"faq","FAQ",[403,1063,1065],{"id":1064},"do-react-server-components-work-in-a-static-export","Do React Server Components work in a static export?",[14,1067,1068],{},"Yes. Server Components run at build time and their output is written into the static HTML and RSC payload files. What does not work is anything that needs to run on each request, such as reading cookies or headers.",[403,1070,1072],{"id":1071},"can-i-use-route-handlers-with-output-export","Can I use route handlers with output export?",[14,1074,1075],{},"Only GET route handlers that return static content, which are rendered to files at build time — useful for feeds, sitemaps and JSON. Handlers that read the request or handle POST need a serverless function on the host instead.",[403,1077,1079],{"id":1078},"what-happens-to-middleware-in-a-static-export","What happens to middleware in a static export?",[14,1081,1082],{},"It is not supported. Redirects, rewrites, headers and auth checks that middleware would perform must move to the host's configuration or edge functions, such as a _redirects file or a Cloudflare Worker.",[403,1084,1086],{"id":1085},"how-do-i-handle-dynamic-routes","How do I handle dynamic routes?",[14,1088,1089],{},"Every dynamic segment must be enumerated at build time with generateStaticParams, and dynamicParams must be false. Paths not returned at build time return 404, because there is no server to render them on demand.",[36,1091,1093],{"id":1092},"related","Related",[41,1095,1096,1105,1110,1117,1124],{},[44,1097,1098,1101,1102,1104],{},[63,1099,1100],{},"Parent:"," ",[25,1103,28],{"href":27}," — when export is the right model.",[44,1106,1107,1109],{},[25,1108,33],{"href":32}," — generateStaticParams in depth.",[44,1111,1112,1116],{},[25,1113,1115],{"href":1114},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Foptimizing-images-in-nextjs-static-export\u002F","Optimizing Images in Next.js Static Export"," — the image optimiser replacement.",[44,1118,1119,1123],{},[25,1120,1122],{"href":1121},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002F","Serverless Functions for Static Sites"," — where request-time logic goes.",[44,1125,1126,1130],{},[25,1127,1129],{"href":1128},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates\u002F","Netlify Build Hooks for Content Updates"," — replacing ISR with rebuilds.",[1132,1133,1134],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":425,"searchDepth":439,"depth":439,"links":1136},[1137,1138,1139,1144,1145,1146,1147,1148,1149,1150,1156],{"id":38,"depth":439,"text":39},{"id":57,"depth":439,"text":58},{"id":213,"depth":439,"text":214,"children":1140},[1141,1142,1143],{"id":405,"depth":460,"text":406},{"id":594,"depth":460,"text":595},{"id":700,"depth":460,"text":701},{"id":847,"depth":439,"text":848},{"id":890,"depth":439,"text":891},{"id":913,"depth":439,"text":914},{"id":925,"depth":439,"text":926},{"id":995,"depth":439,"text":996},{"id":1050,"depth":439,"text":1051},{"id":1060,"depth":439,"text":1061,"children":1151},[1152,1153,1154,1155],{"id":1064,"depth":460,"text":1065},{"id":1071,"depth":460,"text":1072},{"id":1078,"depth":460,"text":1079},{"id":1085,"depth":460,"text":1086},{"id":1092,"depth":439,"text":1093},[1158,1161,1164,1165],{"name":1159,"item":1160},"Home","\u002F",{"name":1162,"item":1163},"Choosing the Right Static Site Generator for Production","\u002Fchoosing-the-right-static-site-generator-for-production\u002F",{"name":28,"item":27},{"name":5,"item":1166},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations\u002F","2026-09-18","Which App Router features work with output export — route handlers, middleware, ISR, dynamic params, headers, images — and the static workaround for each.","md",[1171,1172,1173,1174],{"q":1065,"a":1068},{"q":1072,"a":1075},{"q":1079,"a":1082},{"q":1086,"a":1089},{},true,"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations",{"title":5,"description":1168},"choosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations\u002Findex","article","abO7sz3mDgPwkGquHH-l7I1mxcISnNPL1fzp1WVQJVA",[1183,1186,1189,1192,1195,1198,1201,1204,1207,1210,1213,1216,1219,1222,1225,1228,1231,1234,1237,1240,1242,1245,1248,1251,1254,1257,1260,1263,1266,1269,1272,1275,1278,1281,1284,1286,1288,1291,1292,1295,1297,1300,1303,1306,1309,1312,1315,1318,1321,1324,1327,1330,1333,1336,1339,1342,1345,1348,1351,1354,1357,1360,1363,1366,1369,1372,1375,1378,1381,1384,1387,1390,1393,1396,1399,1402,1405,1408,1411,1414,1417,1420,1423,1426,1429,1432,1435,1438,1441,1444,1447,1450,1453,1456,1459,1462,1465,1468,1471,1474,1477,1480,1483,1486,1489,1492,1495,1498,1501,1504,1507,1510,1513,1516,1518,1521,1524,1527,1530,1533,1536,1539,1542,1545,1548,1551,1554,1557,1560,1563,1566,1569,1572,1575,1578,1581,1584,1587,1590,1593,1596,1599,1602,1605,1608,1611,1614,1617,1619,1621,1624,1626,1629,1632,1635,1638,1641,1644,1647,1650,1653,1656,1659,1661,1664,1667,1670,1673,1676,1679,1682,1684,1687,1690,1693,1696,1699,1702,1705,1708,1710,1713,1715],{"path":1184,"title":1185},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fastro-vs-eleventy-build-times-at-10000-pages","Astro vs Eleventy Build Times at 10,000 Pages",{"path":1187,"title":1188},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fchoosing-between-astro-and-eleventy-for-large-docs","Astro vs Eleventy for Large Docs (1000+ Pages)",{"path":1190,"title":1191},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fcontent-collections-vs-eleventy-data-cascade","Content Collections vs the Eleventy Data Cascade",{"path":1193,"title":1194},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":1196,"title":1197},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fshortcodes-vs-components-for-docs-authors","Shortcodes vs Components for Docs Authors",{"path":1199,"title":1200},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fsidebar-navigation-in-astro-and-eleventy","Sidebar Navigation in Astro and Eleventy",{"path":1202,"title":1203},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcustomizing-starlight-without-forking-the-theme","Customizing Starlight Without Forking the Theme",{"path":1205,"title":1206},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fdocusaurus-vs-starlight-for-product-documentation","Docusaurus vs Starlight for Product Documentation",{"path":1208,"title":1209},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress","Docs Frameworks: Docusaurus, Starlight and VitePress",{"path":1211,"title":1212},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmdx-vs-markdoc-for-docs-content","MDX vs Markdoc for Docs Content",{"path":1214,"title":1215},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-from-mkdocs-to-starlight","Migrating from MkDocs to Starlight",{"path":1217,"title":1218},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioned-documentation-with-docusaurus","Versioned Documentation with Docusaurus",{"path":1220,"title":1221},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-for-library-documentation","VitePress for Library Documentation",{"path":1223,"title":1224},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhow-to-benchmark-hugo-vs-astro-build-speeds","How to Benchmark Hugo vs Astro Build Speeds",{"path":1226,"title":1227},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-partialcached-for-faster-builds","Hugo partialCached for Faster Builds",{"path":1229,"title":1230},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":1232,"title":1233},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics","Profiling Hugo Templates With Template Metrics",{"path":1235,"title":1236},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Freducing-hugo-memory-usage-on-ci-runners","Reducing Hugo Memory Usage on CI Runners",{"path":1238,"title":1239},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fspeeding-up-hugo-builds-with-render-hooks-and-caching","Speeding Up Hugo Builds with Render Hooks & Caching",{"path":1241,"title":1162},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":1243,"title":1244},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Feleventy-vs-jekyll-for-markdown-heavy-blogs","Eleventy vs Jekyll for Markdown-Heavy Blogs",{"path":1246,"title":1247},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":1249,"title":1250},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Freplacing-jekyll-plugins-when-migrating-to-eleventy","Replacing Jekyll Plugins When Migrating to Eleventy",{"path":1252,"title":1253},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Frunning-jekyll-on-github-pages-without-plugins","Running Jekyll on GitHub Pages Without Plugins",{"path":1255,"title":1256},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds","Speeding Up Slow Jekyll Builds",{"path":1258,"title":1259},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fupgrading-jekyll-and-ruby-versions-safely","Upgrading Jekyll and Ruby Versions Safely",{"path":1261,"title":1262},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fconverting-front-matter-at-scale-during-migration","Converting Front Matter at Scale During Migration",{"path":1264,"title":1265},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1267,"title":1268},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration","Keeping Redirects Working After an SSG Migration",{"path":1270,"title":1271},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo","Migrating a Docs Site From Jekyll to Hugo",{"path":1273,"title":1274},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-gatsby-to-astro","Migrating from Gatsby to Astro",{"path":1276,"title":1277},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-hugo-to-astro-without-breaking-urls","Migrating From Hugo to Astro Without Breaking URLs",{"path":1279,"title":1280},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-wordpress-to-a-static-site-generator","Migrating WordPress to a Static Site Generator",{"path":1282,"title":1283},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fporting-shortcodes-and-includes-between-generators","Porting Shortcodes and Includes Between Generators",{"path":1285,"title":33},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export",{"path":1287,"title":28},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites",{"path":1289,"title":1290},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fmigrating-from-gatsby-to-nextjs-static-export","Migrating from Gatsby to Next.js Static Export",{"path":1177,"title":5},{"path":1293,"title":1294},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-static-export-vs-astro-for-marketing-sites","Next.js Static Export vs Astro for Marketing",{"path":1296,"title":1115},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Foptimizing-images-in-nextjs-static-export",{"path":1298,"title":1299},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fadding-pagefind-to-an-astro-site","Adding Pagefind to an Astro Site",{"path":1301,"title":1302},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fbuilding-a-lunr-index-at-build-time-in-eleventy","Building a Lunr Index at Build Time in Eleventy",{"path":1304,"title":1305},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites","Search for Static Sites",{"path":1307,"title":1308},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Findexing-hugo-sites-with-pagefind","Indexing Hugo Sites with Pagefind",{"path":1310,"title":1311},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fmultilingual-search-on-static-sites","Multilingual Search on Static Sites",{"path":1313,"title":1314},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-algolia-docsearch","Pagefind vs Algolia DocSearch",{"path":1316,"title":1317},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fsearch-index-size-budgets-for-large-docs","Search Index Size Budgets for Large Docs",{"path":1319,"title":1320},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fbest-ssg-for-technical-writers-without-coding-experience","Best SSG for Non-Developer Technical Writers",{"path":1322,"title":1323},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation","Choosing an SSG for API Reference Documentation",{"path":1325,"title":1326},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fevaluating-ssg-accessibility-defaults","Evaluating SSG Accessibility Defaults",{"path":1328,"title":1329},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":1331,"title":1332},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fpicking-an-ssg-for-a-multi-language-documentation-site","Picking an SSG for a Multi-Language Docs Site",{"path":1334,"title":1335},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams","SSG Selection Checklist for Engineering Teams",{"path":1337,"title":1338},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Ftotal-cost-of-ownership-for-static-site-generators","Total Cost of Ownership for Static Site Generators",{"path":1340,"title":1341},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-busting-with-content-hashed-filenames","Cache Busting with Content-Hashed Filenames",{"path":1343,"title":1344},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":1346,"title":1347},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fpurging-the-cdn-cache-after-a-static-deploy","Purging the CDN Cache After a Static Deploy",{"path":1349,"title":1350},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-cache-control-headers-on-cloudflare-pages","Cache-Control Headers on Cloudflare Pages",{"path":1352,"title":1353},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-up-proper-cache-headers-on-netlify","Proper Cache Headers on Netlify for SSGs",{"path":1355,"title":1356},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fstale-while-revalidate-for-static-html","Stale-While-Revalidate for Static HTML",{"path":1358,"title":1359},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Feliminating-layout-shift-from-web-fonts","Eliminating Layout Shift From Web Fonts",{"path":1361,"title":1362},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-cookie-banners","Fixing CLS from Cookie Banners",{"path":1364,"title":1365},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-late-loading-embeds","Fixing CLS From Late-Loading Embeds",{"path":1367,"title":1368},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-sticky-headers-and-anchor-links","Fixing CLS from Sticky Headers and Anchor Links",{"path":1370,"title":1371},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1373,"title":1374},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Fmeasuring-cls-in-the-field-with-web-vitals-js","Measuring CLS in the Field With web-vitals.js",{"path":1376,"title":1377},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-images-and-embeds-to-stop-layout-shift","Reserving Space for Images and Embeds",{"path":1379,"title":1380},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Ffont-display-optional-vs-swap","font-display: optional vs swap",{"path":1382,"title":1383},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1385,"title":1386},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fmetric-matched-fallback-fonts-with-size-adjust","Metric-Matched Fallback Fonts with size-adjust",{"path":1388,"title":1389},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fpreloading-fonts-without-double-downloads","Preloading Fonts Without Double Downloads",{"path":1391,"title":1392},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fself-hosting-google-fonts-to-eliminate-layout-shift","Self-Host Google Fonts to Eliminate Layout Shift",{"path":1394,"title":1395},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fsubsetting-variable-fonts-for-faster-first-render","Subsetting Variable Fonts for Faster First Render",{"path":1397,"title":1398},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fbuilding-an-image-cdn-pipeline-for-static-sites","Building an Image CDN Pipeline for Static Sites",{"path":1400,"title":1401},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fgenerating-open-graph-images-at-build-time","Generating Open Graph Images at Build Time",{"path":1403,"title":1404},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1406,"title":1407},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Flazy-loading-images-without-hurting-lcp","Lazy-Loading Images Without Hurting LCP",{"path":1409,"title":1410},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Foptimizing-webp-images-in-hugo-without-plugins","Optimizing WebP Images in Hugo Without Plugins",{"path":1412,"title":1413},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fresponsive-images-with-srcset-in-eleventy","Responsive Images with srcset in Eleventy",{"path":1415,"title":1416},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fserving-avif-with-fallbacks-on-static-sites","Serving AVIF With Fallbacks on Static Sites",{"path":1418,"title":1419},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1421,"title":1422},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":1424,"title":1425},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fdeferring-hydration-with-client-visible-in-astro","Deferring Hydration with client:visible in Astro",{"path":1427,"title":1428},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fhow-to-reduce-bundle-size-in-eleventy-builds","How to Reduce Bundle Size in Eleventy Builds",{"path":1430,"title":1431},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1433,"title":1434},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fmeasuring-inp-on-static-sites-with-real-user-monitoring","Measuring INP on Static Sites with RUM",{"path":1436,"title":1437},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Freplacing-react-islands-with-web-components","Replacing React Islands with Web Components",{"path":1439,"title":1440},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Feliminating-render-blocking-css-on-static-sites","Eliminating Render-Blocking CSS on Static Sites",{"path":1442,"title":1443},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-lcp-on-text-heavy-documentation-pages","Fixing LCP on Text-Heavy Documentation Pages",{"path":1445,"title":1446},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1448,"title":1449},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Fmeasuring-lcp-subparts-with-devtools","Measuring LCP Subparts with DevTools",{"path":1451,"title":1452},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Foptimizing-lcp-on-astro-with-priority-hints","Optimizing LCP on Astro with Priority Hints",{"path":1454,"title":1455},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Freducing-lcp-from-hero-images-on-static-sites","Reducing LCP from Hero Images on Static Sites",{"path":1457,"title":1458},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fcomparing-lab-and-field-data-with-crux","Comparing Lab and Field Data with CrUX",{"path":1460,"title":1461},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci","Performance Budgets and Lighthouse CI",{"path":1463,"title":1464},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Freducing-lighthouse-score-variance-in-ci","Reducing Lighthouse Score Variance in CI",{"path":1466,"title":1467},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Frunning-webpagetest-scripts-against-preview-deploys","Running WebPageTest Scripts Against Preview Deploys",{"path":1469,"title":1470},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fsetting-up-lighthouse-ci-for-a-static-site","Setting Up Lighthouse CI for a Static Site",{"path":1472,"title":1473},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Ftracking-bundle-size-per-pull-request","Tracking Bundle Size per Pull Request",{"path":1475,"title":1476},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fwriting-a-performance-budget-that-fails-builds","Writing a Performance Budget That Fails Builds",{"path":1478,"title":1479},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fauditing-unused-preloads","Auditing Unused Preloads",{"path":1481,"title":1482},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed","Resource Hints and Navigation Speed",{"path":1484,"title":1485},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Finstant-navigation-with-speculation-rules","Instant Navigation with Speculation Rules",{"path":1487,"title":1488},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fpreconnect-vs-dns-prefetch-on-static-sites","Preconnect vs DNS-Prefetch on Static Sites",{"path":1490,"title":1491},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fprefetching-links-in-astro","Prefetching Links in Astro",{"path":1493,"title":1494},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fview-transitions-on-multi-page-static-sites","View Transitions on Multi-Page Static Sites",{"path":1496,"title":1497},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fauditing-third-party-scripts-with-lighthouse","Auditing Third-Party Scripts With Lighthouse",{"path":1499,"title":1500},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1502,"title":1503},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites","Lazy-Loading YouTube Embeds on Static Sites",{"path":1505,"title":1506},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Floading-google-tag-manager-without-hurting-inp","Loading Google Tag Manager Without Hurting INP",{"path":1508,"title":1509},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Frunning-third-party-scripts-in-a-web-worker-with-partytown","Running Third-Party Scripts in a Web Worker with Partytown",{"path":1511,"title":1512},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fself-hosting-analytics-to-cut-third-party-requests","Self-Hosting Analytics to Cut Third-Party Requests",{"path":1514,"title":1515},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":1517,"title":587},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fconfiguring-redirects-on-cloudflare-pages",{"path":1519,"title":1520},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fcustom-domains-and-tls-on-cloudflare-pages","Custom Domains and TLS on Cloudflare Pages",{"path":1522,"title":1523},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fdeploying-hugo-to-cloudflare-pages-and-workers","Deploying Hugo to Cloudflare Pages and Workers",{"path":1525,"title":1526},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":1528,"title":1529},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fmigrating-from-cloudflare-pages-to-workers-static-assets","Migrating from Cloudflare Pages to Workers Static Assets",{"path":1531,"title":1532},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fchecking-links-in-pull-requests","Checking Links in Pull Requests",{"path":1534,"title":1535},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers","Docs-as-Code Review Workflow for Writers",{"path":1537,"title":1538},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Feditorial-checks-with-vale-in-ci","Editorial Checks with Vale in CI",{"path":1540,"title":1541},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":1543,"title":1544},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fscheduling-content-publication-with-cron-triggered-builds","Scheduling Content Publication With Cron-Triggered Builds",{"path":1546,"title":1547},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fwiring-a-headless-cms-to-a-static-build","Wiring a Headless CMS to a Static Build",{"path":1549,"title":1550},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fbuilding-astro-sites-with-github-actions","Building Astro Sites with GitHub Actions",{"path":1552,"title":1553},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fcaching-node-modules-in-github-actions-for-faster-ssg-builds","Caching node_modules in GitHub Actions",{"path":1555,"title":1556},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-github-pages-with-actions","Deploying to GitHub Pages with Actions",{"path":1558,"title":1559},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-multiple-environments-from-one-workflow","Deploying to Multiple Environments From One Workflow",{"path":1561,"title":1562},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fhow-to-set-up-github-actions-for-hugo-deployments","GitHub Actions for Hugo Deployments",{"path":1564,"title":1565},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1567,"title":1568},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fmatrix-builds-for-multi-site-monorepos","Matrix Builds for Multi-Site Monorepos",{"path":1570,"title":1571},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions","Caching Hugo Builds in GitHub Actions",{"path":1573,"title":1574},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":1576,"title":1577},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fincremental-builds-in-astro-with-the-content-layer","Incremental Builds in Astro with the Content Layer",{"path":1579,"title":1580},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":1582,"title":1583},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fmeasuring-build-time-regressions-in-ci","Measuring Build-Time Regressions in CI",{"path":1585,"title":1586},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fremote-caching-with-turborepo-for-ssg-monorepos","Remote Caching with Turborepo for SSG Monorepos",{"path":1588,"title":1589},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fsharing-build-cache-across-ci-runners","Sharing Build Cache Across CI Runners",{"path":1591,"title":1592},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":1594,"title":1595},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Falerting-on-cache-hit-ratio-drops","Alerting on Cache Hit Ratio Drops",{"path":1597,"title":1598},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fbuilding-a-core-web-vitals-dashboard-from-rum-data","Building a Core Web Vitals Dashboard from RUM Data",{"path":1600,"title":1601},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fcrawling-for-broken-links-on-a-schedule","Crawling for Broken Links on a Schedule",{"path":1603,"title":1604},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production","Monitoring Static Sites in Production",{"path":1606,"title":1607},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Flogging-404s-at-the-edge","Logging 404s at the Edge",{"path":1609,"title":1610},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fuptime-and-synthetic-checks-for-static-sites","Uptime and Synthetic Checks for Static Sites",{"path":1612,"title":1613},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fconfiguring-vercel-for-hugo-and-eleventy","Configuring Vercel for Hugo and Eleventy",{"path":1615,"title":1616},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":1618,"title":1129},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates",{"path":1620,"title":591},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-redirects-and-rewrites-for-static-sites",{"path":1622,"title":1623},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fsetting-up-deploy-previews-on-netlify-for-every-pull-request","Netlify Deploy Previews for Every Pull Request",{"path":1625,"title":602},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-isr-vs-static-generation-for-ssgs",{"path":1627,"title":1628},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fautomating-preview-deploy-pipelines-with-github-actions","Automating Preview Deploy Pipelines with GitHub Actions",{"path":1630,"title":1631},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":1633,"title":1634},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":1636,"title":1637},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpassword-protecting-preview-deployments","Password-Protecting Preview Deployments",{"path":1639,"title":1640},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpreviewing-headless-cms-drafts","Previewing Headless CMS Drafts",{"path":1642,"title":1643},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fvisual-regression-testing-on-preview-deploys","Visual Regression Testing on Preview Deploys",{"path":1645,"title":1646},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":1648,"title":1649},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fcanary-releases-for-static-sites","Canary Releases for Static Sites",{"path":1651,"title":1652},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Ffeature-flags-on-static-sites","Feature Flags on Static Sites",{"path":1654,"title":1655},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":1657,"title":1658},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frolling-back-a-bad-static-deploy-in-under-a-minute","Rolling Back a Bad Static Deploy in Under a Minute",{"path":1660,"title":906},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url",{"path":1662,"title":1663},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fauditing-npm-dependencies-in-ssg-pipelines","Auditing npm Dependencies in SSG Pipelines",{"path":1665,"title":1666},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fenabling-hsts-and-preload-safely","Enabling HSTS and Preload Safely",{"path":1668,"title":1669},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fhash-based-csp-for-inline-scripts-in-astro","Hash-Based CSP for Inline Scripts in Astro",{"path":1671,"title":1672},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites","Security Headers and Hardening for Static Sites",{"path":1674,"title":1675},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecuring-deploy-credentials-with-github-oidc","Securing Deploy Credentials with GitHub OIDC",{"path":1677,"title":1678},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsubresource-integrity-for-third-party-assets","Subresource Integrity for Third-Party Assets",{"path":1680,"title":1681},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fwriting-a-content-security-policy-for-a-static-site","Writing a Content Security Policy for a Static Site",{"path":1683,"title":874},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3",{"path":1685,"title":1686},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fcloudfront-functions-for-redirects","CloudFront Functions for Redirects",{"path":1688,"title":1689},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fdeploying-a-static-site-to-s3-and-cloudfront","Deploying a Static Site to S3 and CloudFront",{"path":1691,"title":1692},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites","Self-Hosting Static Sites on S3, Nginx and Caddy",{"path":1694,"title":1695},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy","Serving a Static Site with Caddy",{"path":1697,"title":1698},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-nginx","Serving a Static Site with Nginx",{"path":1700,"title":1701},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fzero-downtime-deploys-with-symlink-swaps","Zero-Downtime Deploys with Symlink Swaps",{"path":1703,"title":1704},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fadding-a-contact-form-with-cloudflare-workers","Adding a Contact Form with Cloudflare Workers",{"path":1706,"title":1707},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fhandling-form-submissions-on-a-static-site","Handling Form Submissions on a Static Site",{"path":1709,"title":1122},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites",{"path":1711,"title":1712},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fnetlify-functions-vs-cloudflare-workers","Netlify Functions vs Cloudflare Workers",{"path":1714,"title":715},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fprotecting-a-static-site-behind-authentication",{"path":1716,"title":697},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fproxying-third-party-apis-from-an-edge-function",1789722848037]