[{"data":1,"prerenderedAt":2215},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress":3,"all-docs-nav":1684},{"id":4,"title":5,"body":6,"breadcrumb":1660,"dateModified":1667,"datePublished":1667,"description":1668,"extension":1669,"faq":1670,"meta":1676,"navigation":1677,"path":1678,"seo":1679,"slug":1680,"stem":1681,"type":1682,"__hash__":1683},"content\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Findex.md","Docs Frameworks: Docusaurus, Starlight and VitePress",{"type":7,"value":8,"toc":1641},"minimark",[9,13,35,54,66,220,225,228,292,393,515,535,539,542,628,640,734,741,745,748,771,781,796,924,928,931,1031,1054,1062,1157,1161,1164,1219,1226,1308,1312,1315,1357,1380,1402,1408,1418,1422,1425,1459,1467,1474,1477,1481,1520,1524,1541,1545,1550,1553,1557,1560,1564,1567,1571,1574,1578,1581,1585,1637],[10,11,5],"h1",{"id":12},"docs-frameworks-docusaurus-starlight-and-vitepress",[14,15,16,17,21,22,26,27,30,31,34],"p",{},"Most documentation teams never pick a bare static site generator. They pick a ",[18,19,20],"em",{},"docs framework"," — a generator with the sidebar, search, versioning, dark mode, edit-this-page links and callouts already decided. Three dominate new projects: ",[23,24,25],"strong",{},"Docusaurus"," (React, from Meta), ",[23,28,29],{},"Starlight"," (built on Astro) and ",[23,32,33],{},"VitePress"," (Vue, from the Vite team). Each gives you a working docs site in under ten minutes; they diverge sharply once the site passes a few hundred pages, needs a second version, or has to match a brand.",[14,36,37,38,43,44,48,49,53],{},"This topic sits inside ",[39,40,42],"a",{"href":41},"\u002Fchoosing-the-right-static-site-generator-for-production\u002F","Choosing the Right Static Site Generator for Production"," and narrows that decision to the docs case. It complements ",[39,45,47],{"href":46},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002F","Astro vs Eleventy for Documentation Sites",", which covers the do-it-yourself route, and the scored approach in the ",[39,50,52],{"href":51},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002F","SSG Framework Selection Matrix",".",[14,55,56,57,61,62,65],{},"Every number below comes from one test corpus: 1,200 Markdown pages (about 1.9 million words, 340 images, 85 pages with tabbed code samples) ported to each framework with default settings, built on a GitHub Actions ",[58,59,60],"code",{},"ubuntu-latest"," runner (4 vCPU, 16 GB), timed with ",[58,63,64],{},"hyperfine --warmup 1 --runs 5",", and measured for page weight with Lighthouse 12 on the mobile preset.",[67,68,69,216],"figure",{},[70,71,78,79,78,83,78,87,78,94],"svg",{"viewBox":72,"role":73,"ariaLabelledBy":74,"xmlns":77},"0 0 780 330","img",[75,76],"dfw-map-title","dfw-map-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[80,81,82],"title",{"id":75},"What each docs framework is built on",[84,85,86],"desc",{"id":76},"Three stacks side by side. Docusaurus sits on React and webpack or Rspack and renders a full single-page app. Starlight sits on Astro and Vite and ships static HTML with small islands. VitePress sits on Vue and Vite and ships static HTML that hydrates into a single-page app.",[88,89],"rect",{"x":90,"y":90,"width":91,"height":92,"fill":93},"0","780","330","#ffffff",[95,96,98,99,98,107,98,116,98,121,98,127,98,134,98,139,98,142,98,146,98,151,98,157,98,161,98,163,98,166,98,168,98,171,98,173,98,176,98,181,98,185,98,188,98,191,98,194,98,196,98,199,98,201,98,203,98,208,98,212,78],"g",{"style":97},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[100,101,106],"text",{"x":102,"y":103,"fill":104,"style":105},"390","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","Three frameworks, three runtime models",[88,108],{"x":109,"y":110,"width":111,"height":110,"rx":112,"fill":113,"opacity":114,"stroke":113,"style":115},"30","56","230","10","#1982c4","0.14","stroke-width:1.5px",[100,117,25],{"x":118,"y":119,"fill":104,"style":120},"145","80","font-size:14px;font-weight:700;text-anchor:middle",[100,122,126],{"x":118,"y":123,"fill":124,"style":125},"100","#556071","font-size:11px;text-anchor:middle","docs + blog + versions",[88,128],{"x":109,"y":129,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},"126","44","8","#f8fafc","#d9e2ef",[100,135,138],{"x":118,"y":136,"fill":104,"style":137},"153","text-anchor:middle","React 18\u002F19 + MDX 3",[88,140],{"x":109,"y":141,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},"182",[100,143,145],{"x":118,"y":144,"fill":104,"style":137},"209","webpack or Rspack",[88,147],{"x":109,"y":148,"width":111,"height":130,"rx":131,"fill":149,"opacity":114,"stroke":150,"style":115},"238","#ff595e","#d83b41",[100,152,156],{"x":118,"y":153,"fill":154,"style":155},"265","#b32b30","font-weight:700;text-anchor:middle","full SPA hydration",[88,158],{"x":159,"y":110,"width":111,"height":110,"rx":112,"fill":160,"opacity":114,"stroke":160,"style":115},"275","#6a4c93",[100,162,29],{"x":102,"y":119,"fill":104,"style":120},[100,164,165],{"x":102,"y":123,"fill":124,"style":125},"docs theme for Astro",[88,167],{"x":159,"y":129,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},[100,169,170],{"x":102,"y":136,"fill":104,"style":137},"Astro + MDX or Markdoc",[88,172],{"x":159,"y":141,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},[100,174,175],{"x":102,"y":144,"fill":104,"style":137},"Vite + Rollup",[88,177],{"x":159,"y":148,"width":111,"height":130,"rx":131,"fill":178,"opacity":179,"stroke":180,"style":115},"#8ac926","0.16","#5a8a16",[100,182,184],{"x":102,"y":153,"fill":183,"style":155},"#3f6410","static HTML + islands",[88,186],{"x":187,"y":110,"width":111,"height":110,"rx":112,"fill":178,"opacity":114,"stroke":180,"style":115},"520",[100,189,33],{"x":190,"y":119,"fill":104,"style":120},"635",[100,192,193],{"x":190,"y":123,"fill":124,"style":125},"Vue-powered docs",[88,195],{"x":187,"y":129,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},[100,197,198],{"x":190,"y":136,"fill":104,"style":137},"Vue 3 + markdown-it",[88,200],{"x":187,"y":141,"width":111,"height":130,"rx":131,"fill":132,"stroke":133,"style":115},[100,202,175],{"x":190,"y":144,"fill":104,"style":137},[88,204],{"x":187,"y":148,"width":111,"height":130,"rx":131,"fill":205,"opacity":206,"stroke":207,"style":115},"#ffca3a","0.28","#a97b00",[100,209,211],{"x":190,"y":153,"fill":210,"style":155},"#8a6d0f","HTML, then SPA router",[100,213,215],{"x":102,"y":214,"fill":124,"style":125},"312","The runtime model, not the Markdown dialect, decides page weight and interaction cost",[217,218,219],"figcaption",{},"All three produce static files; what differs is how much of the framework follows the HTML into the browser.",[221,222,224],"h2",{"id":223},"build-speed-on-a-real-corpus","Build Speed on a Real Corpus",[14,226,227],{},"Build time is the first cost a docs team feels, because it decides how long every preview deploy takes. The frameworks were built cold (no cache directory) and warm (cache from the previous run restored) on the 1,200-page corpus.",[229,230,235],"pre",{"className":231,"code":232,"language":233,"meta":234,"style":234},"language-bash shiki shiki-themes github-light github-dark","# Same runner, same corpus, five timed runs each after one warm-up\nhyperfine --warmup 1 --runs 5 \\\n  'npx docusaurus build' \\\n  'npx astro build' \\\n  'npx vitepress build docs'\n","bash","",[58,236,237,246,269,278,286],{"__ignoreMap":234},[238,239,242],"span",{"class":240,"line":241},"line",1,[238,243,245],{"class":244},"sJ8bj","# Same runner, same corpus, five timed runs each after one warm-up\n",[238,247,249,253,257,260,263,266],{"class":240,"line":248},2,[238,250,252],{"class":251},"sScJk","hyperfine",[238,254,256],{"class":255},"sj4cs"," --warmup",[238,258,259],{"class":255}," 1",[238,261,262],{"class":255}," --runs",[238,264,265],{"class":255}," 5",[238,267,268],{"class":255}," \\\n",[238,270,272,276],{"class":240,"line":271},3,[238,273,275],{"class":274},"sZZnC","  'npx docusaurus build'",[238,277,268],{"class":255},[238,279,281,284],{"class":240,"line":280},4,[238,282,283],{"class":274},"  'npx astro build'",[238,285,268],{"class":255},[238,287,289],{"class":240,"line":288},5,[238,290,291],{"class":274},"  'npx vitepress build docs'\n",[293,294,295,317],"table",{},[296,297,298],"thead",{},[299,300,301,305,308,311,314],"tr",{},[302,303,304],"th",{},"Framework",[302,306,307],{},"Cold build",[302,309,310],{},"Warm build",[302,312,313],{},"Peak RSS",[302,315,316],{},"Output size",[318,319,320,338,359,376],"tbody",{},[299,321,322,326,329,332,335],{},[323,324,325],"td",{},"Docusaurus 3.8 (webpack)",[323,327,328],{},"96 s",[323,330,331],{},"71 s",[323,333,334],{},"3.4 GB",[323,336,337],{},"148 MB",[299,339,340,347,350,353,356],{},[323,341,342,343,346],{},"Docusaurus 3.8 (Rspack, ",[58,344,345],{},"future.experimental_faster",")",[323,348,349],{},"44 s",[323,351,352],{},"31 s",[323,354,355],{},"2.6 GB",[323,357,358],{},"146 MB",[299,360,361,364,367,370,373],{},[323,362,363],{},"Starlight 0.34 on Astro 5",[323,365,366],{},"41 s",[323,368,369],{},"23 s",[323,371,372],{},"1.3 GB",[323,374,375],{},"61 MB",[299,377,378,381,384,387,390],{},[323,379,380],{},"VitePress 1.6",[323,382,383],{},"19 s",[323,385,386],{},"17 s",[323,388,389],{},"0.9 GB",[323,391,392],{},"74 MB",[67,394,395,512],{},[70,396,78,401,78,404,78,407,78,410],{"viewBox":397,"role":73,"ariaLabelledBy":398,"xmlns":77},"0 0 780 300",[399,400],"dfw-build-title","dfw-build-desc",[80,402,403],{"id":399},"Cold and warm build times for 1,200 pages",[84,405,406],{"id":400},"Horizontal bars. Docusaurus with webpack builds cold in 96 seconds and warm in 71. Docusaurus with Rspack builds in 44 and 31. Starlight builds in 41 and 23. VitePress builds in 19 and 17.",[88,408],{"x":90,"y":90,"width":91,"height":409,"fill":93},"300",[95,411,98,412,98,415,98,420,98,425,98,433,98,439,98,443,98,449,98,452,98,456,98,460,98,464,98,469,98,472,98,476,98,479,98,483,98,488,98,490,98,495,98,499,98,503,98,508,78],{"style":97},[100,413,414],{"x":102,"y":103,"fill":104,"style":105},"Seconds to build 1,200 pages (lower is better)",[240,416],{"x1":417,"y1":418,"x2":417,"y2":419,"stroke":133,"style":115},"220","46","256",[100,421,424],{"x":109,"y":422,"fill":104,"style":423},"74","font-weight:700","Docusaurus (webpack)",[88,426],{"x":417,"y":427,"width":428,"height":429,"rx":430,"fill":149,"opacity":431,"stroke":150,"style":432},"58","480","16","3","0.3","stroke-width:1px",[88,434],{"x":417,"y":435,"width":436,"height":437,"rx":430,"fill":149,"opacity":438,"stroke":150,"style":432},"78","355","12","0.12",[100,440,328],{"x":441,"y":442,"fill":154,"style":423},"708","71",[100,444,448],{"x":445,"y":446,"fill":124,"style":447},"583","89","font-size:11px","71 s warm",[100,450,451],{"x":109,"y":129,"fill":104,"style":423},"Docusaurus (Rspack)",[88,453],{"x":417,"y":454,"width":417,"height":429,"rx":430,"fill":205,"opacity":455,"stroke":207,"style":432},"110","0.4",[88,457],{"x":417,"y":458,"width":459,"height":437,"rx":430,"fill":205,"opacity":179,"stroke":207,"style":432},"130","155",[100,461,349],{"x":462,"y":463,"fill":210,"style":423},"448","123",[100,465,468],{"x":466,"y":467,"fill":124,"style":447},"383","141","31 s warm",[100,470,29],{"x":109,"y":471,"fill":104,"style":423},"178",[88,473],{"x":417,"y":474,"width":475,"height":429,"rx":430,"fill":160,"opacity":431,"stroke":160,"style":432},"162","205",[88,477],{"x":417,"y":141,"width":478,"height":437,"rx":430,"fill":160,"opacity":438,"stroke":160,"style":432},"115",[100,480,366],{"x":481,"y":482,"fill":160,"style":423},"433","175",[100,484,487],{"x":485,"y":486,"fill":124,"style":447},"343","193","23 s warm",[100,489,33],{"x":109,"y":111,"fill":104,"style":423},[88,491],{"x":417,"y":492,"width":493,"height":429,"rx":430,"fill":178,"opacity":494,"stroke":180,"style":432},"214","95","0.35",[88,496],{"x":417,"y":497,"width":498,"height":437,"rx":430,"fill":178,"opacity":114,"stroke":180,"style":432},"234","85",[100,500,383],{"x":501,"y":502,"fill":183,"style":423},"323","227",[100,504,507],{"x":505,"y":506,"fill":124,"style":447},"313","245","17 s warm",[100,509,511],{"x":109,"y":510,"fill":124,"style":447},"284","hyperfine, 5 runs, GitHub Actions ubuntu-latest (4 vCPU \u002F 16 GB); thick bar cold, thin bar warm",[217,513,514],{},"VitePress wins the raw race; Starlight gains most from a warm cache because Astro's content layer skips unchanged entries.",[14,516,517,518,521,522,525,526,529,530,534],{},"Two details matter more than the ranking. First, Docusaurus's webpack build is memory-bound: at 3.4 GB peak it will exceed the 2 GB limit of some hosted build containers and die with a heap error rather than slow down, so switch on the Rspack path (",[58,519,520],{},"future: { experimental_faster: true }"," in ",[58,523,524],{},"docusaurus.config.js",") before the corpus doubles. Second, Starlight's warm build is where its advantage lives — Astro's content layer stores a digest per entry in ",[58,527,528],{},"node_modules\u002F.astro\u002Fdata-store.json"," and only re-renders entries whose digest changed. Persist that directory between CI runs as described in ",[39,531,533],{"href":532},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions\u002F","Caching Hugo Builds in GitHub Actions"," (the pattern is identical) and a one-page edit rebuilds in about 23 seconds instead of 41.",[221,536,538],{"id":537},"page-weight-and-core-web-vitals","Page Weight and Core Web Vitals",[14,540,541],{},"The runtime model drawn above shows up directly in what a reader downloads. Each framework's default theme was measured on the same three page types: a short guide, a long API reference page and the homepage.",[293,543,544,557],{},[296,545,546],{},[299,547,548,551,553,555],{},[302,549,550],{},"Metric (median of 3 page types, mobile)",[302,552,25],{},[302,554,29],{},[302,556,33],{},[318,558,559,573,587,601,615],{},[299,560,561,564,567,570],{},[323,562,563],{},"Compressed JS",[323,565,566],{},"190 KB",[323,568,569],{},"12 KB",[323,571,572],{},"58 KB",[299,574,575,578,581,584],{},[323,576,577],{},"Total transfer",[323,579,580],{},"268 KB",[323,582,583],{},"71 KB",[323,585,586],{},"119 KB",[299,588,589,592,595,598],{},[323,590,591],{},"LCP (Lighthouse, simulated 4G)",[323,593,594],{},"2.1 s",[323,596,597],{},"1.1 s",[323,599,600],{},"1.4 s",[299,602,603,606,609,612],{},[323,604,605],{},"Total Blocking Time",[323,607,608],{},"240 ms",[323,610,611],{},"0 ms",[323,613,614],{},"60 ms",[299,616,617,620,623,625],{},[323,618,619],{},"Lighthouse Performance score",[323,621,622],{},"82",[323,624,123],{},[323,626,627],{},"96",[14,629,630,631,634,635,639],{},"Starlight's advantage is structural: Astro renders every page to HTML and ships no framework runtime unless a component opts in with a ",[58,632,633],{},"client:"," directive, which is the same mechanism explained in ",[39,636,638],{"href":637},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance\u002F","Astro Islands vs Full Hydration Performance",". VitePress ships prerendered HTML and then hydrates a Vue app so subsequent navigations are client-side; the first view pays a moderate cost and later clicks feel instant. Docusaurus hydrates the full React tree on every page, which is why its Total Blocking Time is the only one a real user on a mid-range phone will feel.",[67,641,642,731],{},[70,643,78,647,78,650,78,653,78,655],{"viewBox":397,"role":73,"ariaLabelledBy":644,"xmlns":77},[645,646],"dfw-weight-title","dfw-weight-desc",[80,648,649],{"id":645},"What each framework ships to the browser",[84,651,652],{"id":646},"Stacked bars of total transfer per page split into HTML and CSS, JavaScript and fonts. Docusaurus totals 268 kilobytes of which 190 is JavaScript. VitePress totals 119 of which 58 is JavaScript. Starlight totals 71 of which 12 is JavaScript.",[88,654],{"x":90,"y":90,"width":91,"height":409,"fill":93},[95,656,98,657,98,660,98,663,98,668,98,672,98,676,98,680,98,683,98,687,98,691,98,695,98,699,98,702,98,705,98,709,98,712,98,715,98,718,98,721,98,723,98,727,78],{"style":97},[100,658,659],{"x":102,"y":103,"fill":104,"style":105},"Median transfer per page, compressed",[100,661,25],{"x":109,"y":662,"fill":104,"style":423},"84",[88,664],{"x":665,"y":666,"width":662,"height":109,"fill":113,"opacity":667,"stroke":113,"style":432},"160","64","0.25",[88,669],{"x":670,"y":666,"width":671,"height":109,"fill":149,"opacity":667,"stroke":150,"style":432},"244","456",[100,673,675],{"x":674,"y":662,"fill":104,"style":137},"472","JavaScript 190 KB",[100,677,679],{"x":678,"y":662,"fill":104,"style":423},"710","268",[100,681,33],{"x":109,"y":682,"fill":104,"style":423},"144",[88,684],{"x":665,"y":685,"width":686,"height":109,"fill":113,"opacity":667,"stroke":113,"style":432},"124","98",[88,688],{"x":689,"y":685,"width":690,"height":109,"fill":149,"opacity":667,"stroke":150,"style":432},"258","139",[100,692,694],{"x":693,"y":682,"fill":104,"style":137},"328","JS 58 KB",[100,696,698],{"x":697,"y":682,"fill":104,"style":423},"407","119",[100,700,29],{"x":109,"y":701,"fill":104,"style":423},"204",[88,703],{"x":665,"y":704,"width":467,"height":109,"fill":113,"opacity":667,"stroke":113,"style":432},"184",[88,706],{"x":707,"y":704,"width":708,"height":109,"fill":149,"opacity":667,"stroke":150,"style":432},"301","29",[100,710,711],{"x":111,"y":701,"fill":104,"style":137},"HTML+CSS+fonts",[100,713,442],{"x":714,"y":701,"fill":104,"style":423},"340",[88,716],{"x":665,"y":670,"width":717,"height":717,"fill":113,"opacity":667,"stroke":113,"style":432},"14",[100,719,720],{"x":141,"y":419,"fill":124,"style":447},"HTML, CSS and fonts",[88,722],{"x":92,"y":670,"width":717,"height":717,"fill":149,"opacity":667,"stroke":150,"style":432},[100,724,726],{"x":725,"y":419,"fill":124,"style":447},"352","JavaScript",[100,728,730],{"x":109,"y":729,"fill":124,"style":447},"286","Lighthouse 12 mobile preset, median of guide, API reference and homepage templates, KB",[217,732,733],{},"Non-JavaScript bytes are similar across all three; the JavaScript column is the whole story.",[14,735,736,737,53],{},"If page weight is your deciding axis, the full comparison with a production content set is in ",[39,738,740],{"href":739},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fdocusaurus-vs-starlight-for-product-documentation\u002F","Docusaurus vs Starlight for Product Documentation",[221,742,744],{"id":743},"versioning-internationalisation-and-search","Versioning, Internationalisation and Search",[14,746,747],{},"These three features are why teams reach for a docs framework rather than a bare generator, and they are also where the frameworks differ most.",[14,749,750,753,754,757,758,761,762,765,766,770],{},[23,751,752],{},"Versioning."," Docusaurus treats it as a first-class feature: ",[58,755,756],{},"npx docusaurus docs:version 2.4"," copies ",[58,759,760],{},"docs\u002F"," into ",[58,763,764],{},"versioned_docs\u002Fversion-2.4\u002F",", snapshots the sidebar and adds the version to a dropdown. The cost is that every version multiplies build time and output size linearly — the 1,200-page corpus with four retained versions built in 5 minutes 40 seconds on webpack. ",[39,767,769],{"href":768},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioned-documentation-with-docusaurus\u002F","Versioned Documentation with Docusaurus"," covers how to keep that in check. Starlight and VitePress have no built-in versioning; the robust pattern is one branch per major version, each deployed to its own path, with a small header component linking them.",[14,772,773,776,777,53],{},[23,774,775],{},"Internationalisation."," All three support locale folders. Starlight's i18n is the most complete out of the box: it translates its own UI strings for over thirty languages, falls back to the default locale for untranslated pages and marks those pages with a notice. Docusaurus builds each locale as a separate full build, so ten locales mean ten builds. VitePress handles locales through config and leaves fallback behaviour to you. For the wider decision see ",[39,778,780],{"href":779},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fpicking-an-ssg-for-a-multi-language-documentation-site\u002F","Picking an SSG for a Multi-Language Documentation Site",[14,782,783,786,787,791,792,53],{},[23,784,785],{},"Search."," Starlight ships ",[39,788,790],{"href":789},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002F","Pagefind"," by default, which indexes the built HTML and loads index fragments on demand. VitePress ships a MiniSearch-based local search that bundles the index into JavaScript. Docusaurus defaults to Algolia DocSearch, which needs an application to the DocSearch programme or a paid Algolia plan. The trade-offs are covered in ",[39,793,795],{"href":794},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-algolia-docsearch\u002F","Pagefind vs Algolia DocSearch",[67,797,798,921],{},[70,799,78,804,78,807,78,810,78,813],{"viewBox":800,"role":73,"ariaLabelledBy":801,"xmlns":77},"0 0 780 320",[802,803],"dfw-feat-title","dfw-feat-desc",[80,805,806],{"id":802},"Feature support matrix",[84,808,809],{"id":803},"A matrix of four features against three frameworks. Versioning is built in for Docusaurus and do-it-yourself for Starlight and VitePress. Internationalisation is built in for all three, with Starlight translating its own interface. Search defaults to Algolia for Docusaurus, Pagefind for Starlight and MiniSearch for VitePress. Blog support is built in for Docusaurus, a plugin for Starlight and manual for VitePress.",[88,811],{"x":90,"y":90,"width":91,"height":812,"fill":93},"320",[95,814,98,815,98,818,98,821,98,823,98,826,98,829,98,834,98,839,98,843,98,847,98,850,98,853,98,855,98,859,98,862,98,866,98,868,98,871,98,873,98,876,98,880,98,883,98,887,98,889,98,892,98,894,98,897,98,900,98,903,98,907,98,909,98,912,98,914,98,917,78],{"style":97},[100,816,817],{"x":102,"y":103,"fill":104,"style":105},"What arrives configured, and what you assemble",[100,819,25],{"x":409,"y":820,"fill":104,"style":155},"66",[100,822,29],{"x":428,"y":820,"fill":104,"style":155},[100,824,33],{"x":825,"y":820,"fill":104,"style":155},"660",[240,827],{"x1":109,"y1":435,"x2":828,"y2":435,"stroke":133,"style":115},"750",[100,830,833],{"x":831,"y":832,"fill":104,"style":423},"40","112","Versioning",[88,835],{"x":417,"y":836,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},"94","6","0.18",[100,840,842],{"x":409,"y":841,"fill":104,"style":137},"113","built in (CLI)",[88,844],{"x":845,"y":836,"width":665,"height":103,"rx":837,"fill":205,"opacity":846,"stroke":207,"style":432},"400","0.26",[100,848,849],{"x":428,"y":841,"fill":104,"style":137},"branch per version",[88,851],{"x":852,"y":836,"width":665,"height":103,"rx":837,"fill":205,"opacity":846,"stroke":207,"style":432},"580",[100,854,849],{"x":825,"y":841,"fill":104,"style":137},[100,856,858],{"x":831,"y":857,"fill":104,"style":423},"164","i18n",[88,860],{"x":417,"y":861,"width":665,"height":103,"rx":837,"fill":205,"opacity":846,"stroke":207,"style":432},"146",[100,863,865],{"x":409,"y":864,"fill":104,"style":137},"165","one build per locale",[88,867],{"x":845,"y":861,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},[100,869,870],{"x":428,"y":864,"fill":104,"style":137},"UI strings + fallback",[88,872],{"x":852,"y":861,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},[100,874,875],{"x":825,"y":864,"fill":104,"style":137},"locale config",[100,877,879],{"x":831,"y":878,"fill":104,"style":423},"216","Search",[88,881],{"x":417,"y":882,"width":665,"height":103,"rx":837,"fill":205,"opacity":846,"stroke":207,"style":432},"198",[100,884,886],{"x":409,"y":885,"fill":104,"style":137},"217","Algolia (hosted)",[88,888],{"x":845,"y":882,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},[100,890,891],{"x":428,"y":885,"fill":104,"style":137},"Pagefind (static)",[88,893],{"x":852,"y":882,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},[100,895,896],{"x":825,"y":885,"fill":104,"style":137},"MiniSearch (bundled)",[100,898,899],{"x":831,"y":679,"fill":104,"style":423},"Blog",[88,901],{"x":417,"y":902,"width":665,"height":103,"rx":837,"fill":178,"opacity":838,"stroke":180,"style":432},"250",[100,904,906],{"x":409,"y":905,"fill":104,"style":137},"269","built in",[88,908],{"x":845,"y":902,"width":665,"height":103,"rx":837,"fill":205,"opacity":846,"stroke":207,"style":432},[100,910,911],{"x":428,"y":905,"fill":104,"style":137},"community plugin",[88,913],{"x":852,"y":902,"width":665,"height":103,"rx":837,"fill":149,"opacity":114,"stroke":150,"style":432},[100,915,916],{"x":825,"y":905,"fill":104,"style":137},"build it yourself",[100,918,920],{"x":831,"y":919,"fill":124,"style":447},"304","Green: configured by default · Yellow: supported with setup · Red: not provided",[217,922,923],{},"Versioning is the feature most likely to decide the choice outright — if you ship four supported versions, Docusaurus is the only one that does it for you.",[221,925,927],{"id":926},"customisation-without-forking","Customisation Without Forking",[14,929,930],{},"Every docs team eventually wants the theme to look like the product. How far each framework bends before you have to copy its source decides your upgrade cost for years.",[229,932,936],{"className":933,"code":934,"language":935,"meta":234,"style":234},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F astro.config.mjs — Starlight: replace one component, keep the rest\nimport starlight from '@astrojs\u002Fstarlight';\nexport default {\n  integrations: [starlight({\n    title: 'Acme Docs',\n    customCss: ['.\u002Fsrc\u002Fstyles\u002Fbrand.css'],\n    components: { Header: '.\u002Fsrc\u002Fcomponents\u002FHeader.astro' },\n  })],\n};\n","js",[58,937,938,943,962,973,984,995,1007,1019,1025],{"__ignoreMap":234},[238,939,940],{"class":240,"line":241},[238,941,942],{"class":244},"\u002F\u002F astro.config.mjs — Starlight: replace one component, keep the rest\n",[238,944,945,949,953,956,959],{"class":240,"line":248},[238,946,948],{"class":947},"szBVR","import",[238,950,952],{"class":951},"sVt8B"," starlight ",[238,954,955],{"class":947},"from",[238,957,958],{"class":274}," '@astrojs\u002Fstarlight'",[238,960,961],{"class":951},";\n",[238,963,964,967,970],{"class":240,"line":271},[238,965,966],{"class":947},"export",[238,968,969],{"class":947}," default",[238,971,972],{"class":951}," {\n",[238,974,975,978,981],{"class":240,"line":280},[238,976,977],{"class":951},"  integrations: [",[238,979,980],{"class":251},"starlight",[238,982,983],{"class":951},"({\n",[238,985,986,989,992],{"class":240,"line":288},[238,987,988],{"class":951},"    title: ",[238,990,991],{"class":274},"'Acme Docs'",[238,993,994],{"class":951},",\n",[238,996,998,1001,1004],{"class":240,"line":997},6,[238,999,1000],{"class":951},"    customCss: [",[238,1002,1003],{"class":274},"'.\u002Fsrc\u002Fstyles\u002Fbrand.css'",[238,1005,1006],{"class":951},"],\n",[238,1008,1010,1013,1016],{"class":240,"line":1009},7,[238,1011,1012],{"class":951},"    components: { Header: ",[238,1014,1015],{"class":274},"'.\u002Fsrc\u002Fcomponents\u002FHeader.astro'",[238,1017,1018],{"class":951}," },\n",[238,1020,1022],{"class":240,"line":1021},8,[238,1023,1024],{"class":951},"  })],\n",[238,1026,1028],{"class":240,"line":1027},9,[238,1029,1030],{"class":951},"};\n",[14,1032,1033,1034,1037,1038,1041,1042,1045,1046,1049,1050,1053],{},"Starlight exposes around forty named components that can be overridden individually, plus CSS custom properties for colours, fonts and spacing; the override receives the same props as the original, so a minor upgrade rarely breaks it. Docusaurus uses ",[18,1035,1036],{},"swizzling",": ",[58,1039,1040],{},"npx docusaurus swizzle @docusaurus\u002Ftheme-classic Footer --eject"," copies the component source into your project. Wrapping (",[58,1043,1044],{},"--wrap",") is safe across upgrades; ejecting is not, and the CLI marks many components as unsafe to eject. VitePress lets you extend the default theme with layout slots (",[58,1047,1048],{},"doc-before",", ",[58,1051,1052],{},"nav-bar-content-after"," and about twenty more) or replace components via Vite aliases.",[14,1055,1056,1057,1061],{},"In a year-long log of one team's upgrades, ejected Docusaurus components caused 7 of 9 upgrade breakages; Starlight overrides caused 1 of 6. The pattern is general: prefer slots and wrappers, eject only what you are willing to maintain as your own code. ",[39,1058,1060],{"href":1059},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcustomizing-starlight-without-forking-the-theme\u002F","Customizing Starlight Without Forking the Theme"," walks through the override set in detail.",[67,1063,1064,1154],{},[70,1065,78,1070,78,1073,78,1076,78,1079,78,1139],{"viewBox":1066,"role":73,"ariaLabelledBy":1067,"xmlns":77},"0 0 780 290",[1068,1069],"dfw-cust-title","dfw-cust-desc",[80,1071,1072],{"id":1068},"Customisation ladder from safe to costly",[84,1074,1075],{"id":1069},"A ladder of four rungs. CSS custom properties are the cheapest and safest. Slot or component overrides come next. Wrapping a component is third. Ejecting or forking the theme is the most expensive, because every upgrade must be merged by hand.",[88,1077],{"x":90,"y":90,"width":91,"height":1078,"fill":93},"290",[95,1080,98,1081,98,1084,98,1089,98,1094,98,1098,98,1101,98,1105,98,1109,98,1112,98,1117,98,1120,98,1122,98,1126,98,1129,98,1135,78],{"style":97},[100,1082,1083],{"x":102,"y":103,"fill":104,"style":105},"Climb only as high as the design needs",[88,1085],{"x":831,"y":1086,"width":1087,"height":1088,"rx":131,"fill":178,"opacity":838,"stroke":180,"style":115},"206","170","52",[100,1090,1093],{"x":1091,"y":1092,"fill":104,"style":155},"125","228","CSS variables",[100,1095,1097],{"x":1091,"y":1096,"fill":124,"style":125},"246","colours, fonts, spacing",[88,1099],{"x":417,"y":1100,"width":1087,"height":1088,"rx":131,"fill":178,"opacity":438,"stroke":180,"style":115},"156",[100,1102,1104],{"x":1103,"y":471,"fill":104,"style":155},"305","Slot \u002F override",[100,1106,1108],{"x":1103,"y":1107,"fill":124,"style":125},"196","same props, your markup",[88,1110],{"x":845,"y":1111,"width":1087,"height":1088,"rx":131,"fill":205,"opacity":846,"stroke":207,"style":115},"106",[100,1113,1116],{"x":1114,"y":1115,"fill":104,"style":155},"485","128","Wrap",[100,1118,1119],{"x":1114,"y":861,"fill":124,"style":125},"add around the original",[88,1121],{"x":852,"y":110,"width":1087,"height":1088,"rx":131,"fill":149,"opacity":179,"stroke":150,"style":115},[100,1123,1125],{"x":1124,"y":435,"fill":104,"style":155},"665","Eject \u002F fork",[100,1127,1128],{"x":1124,"y":627,"fill":124,"style":125},"you own the source now",[1130,1131],"path",{"d":1132,"stroke":124,"fill":1133,"style":1134},"M40 270 L750 270","none","stroke-width:1.5px;marker-end:url(#dfw-cust-arrow)",[100,1136,1138],{"x":1137,"y":729,"fill":124,"style":125},"395","upgrade cost per framework release rises to the right",[1140,1141,98,1142,78],"defs",{},[1143,1144,1150,1151,98],"marker",{"id":1145,"viewBox":1146,"refX":131,"refY":1147,"markerWidth":1148,"markerHeight":1148,"orient":1149},"dfw-cust-arrow","0 0 10 10","5","7","auto-start-reverse","\n      ",[1130,1152],{"d":1153,"fill":124},"M0 0 L10 5 L0 10 z",[217,1155,1156],{},"Most brand requirements are met on the first two rungs; teams that start on the fourth usually stop upgrading.",[221,1158,1160],{"id":1159},"content-format-and-authoring","Content Format and Authoring",[14,1162,1163],{},"All three read Markdown with YAML front matter, which is what keeps them portable. The differences are in how components get into prose:",[1165,1166,1167,1193,1207],"ul",{},[1168,1169,1170,1172,1173,1176,1177,1180,1181,1184,1185,1188,1189,1192],"li",{},[23,1171,25],{}," uses MDX 3 everywhere. Any ",[58,1174,1175],{},".md"," file is parsed as MDX by default, which means a stray ",[58,1178,1179],{},"\u003C"," or ",[58,1182,1183],{},"{"," in prose becomes a compile error — the most common failure when migrating plain Markdown in. Set ",[58,1186,1187],{},"markdown: { format: 'detect' }"," so only ",[58,1190,1191],{},".mdx"," files get MDX parsing.",[1168,1194,1195,1197,1198,1201,1202,1206],{},[23,1196,29],{}," accepts Markdown, MDX and Markdoc. Markdoc's tag syntax (",[58,1199,1200],{},"{% aside %}",") cannot execute arbitrary code, which some teams prefer for contributor-heavy repos. ",[39,1203,1205],{"href":1204},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmdx-vs-markdoc-for-docs-content\u002F","MDX vs Markdoc for Docs Content"," weighs that trade.",[1168,1208,1209,1211,1212,1215,1216,1218],{},[23,1210,33],{}," uses markdown-it with custom containers (",[58,1213,1214],{},"::: tip",") and allows Vue components inline in ",[58,1217,1175],{}," files, which is powerful and easy to overuse.",[14,1220,1221,1222,53],{},"For writers without a front-end background, the practical difference is error messages. In a timed exercise with four technical writers adding a tabbed code sample, the median time to a working page was 6 minutes on Starlight, 9 on VitePress and 14 on Docusaurus, almost entirely spent decoding MDX compile errors. That aligns with the findings in ",[39,1223,1225],{"href":1224},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fbest-ssg-for-technical-writers-without-coding-experience\u002F","Best SSG for Technical Writers Without Coding Experience",[67,1227,1228,1305],{},[70,1229,78,1234,78,1237,78,1240,78,1243],{"viewBox":1230,"role":73,"ariaLabelledBy":1231,"xmlns":77},"0 0 780 280",[1232,1233],"dfw-author-title","dfw-author-desc",[80,1235,1236],{"id":1232},"How a callout is written in each framework",[84,1238,1239],{"id":1233},"Three columns showing the syntax for a warning callout. Docusaurus uses an admonition with triple colons inside MDX. Starlight uses the same triple-colon aside syntax or a Markdoc tag. VitePress uses a triple-colon custom container. A footer notes that the syntax looks alike but the parsers fail differently.",[88,1241],{"x":90,"y":90,"width":91,"height":1242,"fill":93},"280",[95,1244,98,1245,98,1248,98,1250,98,1254,98,1259,98,1263,98,1266,98,1269,98,1271,98,1274,98,1278,98,1280,98,1283,98,1286,98,1288,98,1291,98,1295,98,1297,98,1299,98,1302,78],{"style":97},[100,1246,1247],{"x":102,"y":103,"fill":104,"style":105},"One warning callout, three dialects",[88,1249],{"x":109,"y":1088,"width":111,"height":1087,"rx":112,"fill":132,"stroke":133,"style":115},[100,1251,1253],{"x":118,"y":1252,"fill":104,"style":155},"76","Docusaurus (MDX)",[100,1255,1258],{"x":1256,"y":832,"fill":104,"style":1257},"48","font-family:ui-monospace, monospace",":::warning",[100,1260,1262],{"x":1256,"y":1261,"fill":104,"style":1257},"134","Rotate the key first.",[100,1264,1265],{"x":1256,"y":1100,"fill":104,"style":1257},":::",[100,1267,1268],{"x":1256,"y":1107,"fill":154,"style":447},"a bare { in prose breaks it",[88,1270],{"x":159,"y":1088,"width":111,"height":1087,"rx":112,"fill":132,"stroke":133,"style":115},[100,1272,1273],{"x":102,"y":1252,"fill":104,"style":155},"Starlight (Markdoc)",[100,1275,1277],{"x":1276,"y":832,"fill":104,"style":1257},"293","{% aside type=\"caution\" %}",[100,1279,1262],{"x":1276,"y":1261,"fill":104,"style":1257},[100,1281,1282],{"x":1276,"y":1100,"fill":104,"style":1257},"{% \u002Faside %}",[100,1284,1285],{"x":1276,"y":1107,"fill":183,"style":447},"validated tags, no code",[88,1287],{"x":187,"y":1088,"width":111,"height":1087,"rx":112,"fill":132,"stroke":133,"style":115},[100,1289,1290],{"x":190,"y":1252,"fill":104,"style":155},"VitePress (markdown-it)",[100,1292,1294],{"x":1293,"y":832,"fill":104,"style":1257},"538","::: warning",[100,1296,1262],{"x":1293,"y":1261,"fill":104,"style":1257},[100,1298,1265],{"x":1293,"y":1100,"fill":104,"style":1257},[100,1300,1301],{"x":1293,"y":1107,"fill":210,"style":447},"inline Vue also allowed",[100,1303,1304],{"x":102,"y":689,"fill":124,"style":125},"Near-identical syntax, very different failure modes when a contributor gets it wrong",[217,1306,1307],{},"Portability of prose is high; portability of components is where migrations spend their time.",[221,1309,1311],{"id":1310},"deploying-and-operating-each-framework","Deploying and Operating Each Framework",[14,1313,1314],{},"Once built, all three are folders of static files and deploy anywhere — but each has operational habits worth knowing before the first production incident.",[14,1316,1317,1320,1321,1324,1325,1328,1329,1332,1333,1336,1337,1340,1341,1344,1345,1348,1349,1351,1352,1356],{},[23,1318,1319],{},"Output layout and trailing slashes."," Docusaurus writes ",[58,1322,1323],{},"docs\u002Fintro\u002Findex.html"," by default and links with trailing slashes only if ",[58,1326,1327],{},"trailingSlash: true"," is set; leaving it undefined lets the host decide, which produces duplicate URLs on hosts that serve both forms. Starlight inherits Astro's ",[58,1330,1331],{},"trailingSlash"," and ",[58,1334,1335],{},"build.format"," options, and VitePress writes ",[58,1338,1339],{},"intro.html"," unless ",[58,1342,1343],{},"cleanUrls: true"," is set — which then requires the host to resolve ",[58,1346,1347],{},"\u002Fintro"," to ",[58,1350,1339],{},". Cloudflare and Netlify do that automatically; a bare S3 bucket does not, which is the problem solved in ",[39,1353,1355],{"href":1354},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3\u002F","Clean URLs and Trailing Slashes on S3",". Decide the canonical form on day one and assert it in a smoke test.",[14,1358,1359,1362,1363,1366,1367,1370,1371,1374,1375,1379],{},[23,1360,1361],{},"Hashed assets and caching."," All three fingerprint JavaScript and CSS into an assets directory (",[58,1364,1365],{},"\u002Fassets\u002F"," for Starlight and VitePress, ",[58,1368,1369],{},"\u002Fassets\u002Fjs\u002F"," for Docusaurus), so the long-lived ",[58,1372,1373],{},"immutable"," cache rule from ",[39,1376,1378],{"href":1377},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002F","CDN Caching Rules for SSGs"," applies unchanged. The one trap is VitePress's client-side router: after a deploy, an open tab still holds the old route manifest and requests chunk files that no longer exist. Keep the previous deploy's assets available for a day — atomic hosts do this for you — or readers see a blank page on their next click.",[14,1381,1382,1385,1386,1389,1390,1393,1394,1397,1398,53],{},[23,1383,1384],{},"Broken-link detection."," Docusaurus fails the build on broken internal links by default (",[58,1387,1388],{},"onBrokenLinks: 'throw'","), which is the single best default of the three. Starlight needs the ",[58,1391,1392],{},"starlight-links-validator"," plugin; VitePress reports dead links at build time and fails unless ",[58,1395,1396],{},"ignoreDeadLinks"," is set. Whichever you choose, wire a link check into pull requests as described in ",[39,1399,1401],{"href":1400},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fchecking-links-in-pull-requests\u002F","Checking Links in Pull Requests",[14,1403,1404,1407],{},[23,1405,1406],{},"Upgrade cadence."," Over the last twelve months Docusaurus shipped one major and eight minor releases, Starlight shipped seventeen minor releases (it is still pre-1.0, so minors can carry breaking changes, each listed in the changelog), and VitePress shipped a handful of patch releases on a stable 1.x line. A pre-1.0 dependency is not a reason to avoid Starlight, but it is a reason to pin exact versions and upgrade deliberately through a preview deploy rather than letting a bot merge updates unattended.",[14,1409,1410,1413,1414,1417],{},[23,1411,1412],{},"Memory in CI."," Peak memory, not wall time, is what breaks hosted builds. Record it with ",[58,1415,1416],{},"\u002Fusr\u002Fbin\u002Ftime -v npm run build"," and alert when it crosses 70% of the build container's limit; Docusaurus sites cross that line first, usually between 1,000 and 1,500 pages on webpack.",[221,1419,1421],{"id":1420},"choosing-between-them","Choosing Between Them",[14,1423,1424],{},"Reduce the decision to the constraint you cannot negotiate:",[1165,1426,1427,1433,1439,1449],{},[1168,1428,1429,1432],{},[23,1430,1431],{},"Several supported product versions, a blog and a React design system"," → Docusaurus, with Rspack enabled from day one.",[1168,1434,1435,1438],{},[23,1436,1437],{},"Page weight, Core Web Vitals and writer-friendly authoring matter most"," → Starlight. It is also the natural choice if other parts of your site are already on Astro.",[1168,1440,1441,1444,1445,53],{},[23,1442,1443],{},"Library or API docs for a Vue or Vite ecosystem project, where fast builds and instant client-side navigation matter"," → VitePress. See ",[39,1446,1448],{"href":1447},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-for-library-documentation\u002F","VitePress for Library Documentation",[1168,1450,1451,1454,1455,53],{},[23,1452,1453],{},"Already on MkDocs or Sphinx and feeling the limits"," → Starlight is the smoothest landing; the path is in ",[39,1456,1458],{"href":1457},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-from-mkdocs-to-starlight\u002F","Migrating from MkDocs to Starlight",[14,1460,1461,1462,1466],{},"If none of those is decisive, run the two-week pilot described in the ",[39,1463,1465],{"href":1464},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams\u002F","SSG Selection Checklist for Engineering Teams"," with twenty real pages, and let the build log and a Lighthouse run decide.",[14,1468,1469,1470,1473],{},"A useful tie-breaker is to ask who will own the site in two years. Docusaurus rewards teams with React engineers on hand: its plugin API is the richest of the three, and a custom plugin can generate pages from an OpenAPI file, inject analytics or add a changelog feed with a few dozen lines. Starlight rewards teams where writers own the repository and engineers visit occasionally, because most customisation stays in configuration and CSS. VitePress rewards maintainers of a single library who want docs to live next to the source code and build in the same ",[58,1471,1472],{},"npm"," workspace. Pick the framework that matches the people, not only the feature list; the feature gaps can be closed, but a framework nobody on the team can debug becomes a frozen site.",[14,1475,1476],{},"Finally, weigh the exit. Content stored as plain Markdown with front matter and a small, documented set of components can move between any of the three in a sprint. Content that leans on framework-specific imports inside MDX, custom remark plugins and ejected theme components can take a quarter. Keeping a written inventory of every component you add is the cheapest insurance against a future migration.",[221,1478,1480],{"id":1479},"common-pitfalls","Common Pitfalls",[1165,1482,1483,1496,1502,1508,1514],{},[1168,1484,1485,1488,1489,1491,1492,1495],{},[23,1486,1487],{},"Treating MDX as Markdown."," Docusaurus parses every ",[58,1490,1175],{}," file as MDX unless told otherwise; import a legacy corpus with ",[58,1493,1494],{},"format: 'detect'"," or expect hundreds of compile errors.",[1168,1497,1498,1501],{},[23,1499,1500],{},"Versioning everything forever."," Each retained Docusaurus version is a full copy of the docs. Archive versions older than your support window to a static snapshot.",[1168,1503,1504,1507],{},[23,1505,1506],{},"Ejecting for a colour change."," Brand colours belong in CSS custom properties on every framework; ejection is for structural changes only.",[1168,1509,1510,1513],{},[23,1511,1512],{},"Ignoring build memory."," Docusaurus on webpack can exceed a 2 GB build container past roughly 1,000 pages. Measure peak RSS in CI, not just wall time.",[1168,1515,1516,1519],{},[23,1517,1518],{},"Choosing on the demo site."," All three look excellent on twenty pages. Test with your real corpus size, your real code samples and your real image count.",[221,1521,1523],{"id":1522},"key-takeaways","Key Takeaways",[1165,1525,1526,1529,1532,1535,1538],{},[1168,1527,1528],{},"Docusaurus, Starlight and VitePress all emit static files; the runtime they ship afterwards is what separates their Core Web Vitals.",[1168,1530,1531],{},"On a 1,200-page corpus VitePress built in 19 s, Starlight in 41 s (23 s warm) and Docusaurus in 96 s (44 s with Rspack).",[1168,1533,1534],{},"Starlight shipped about 12 KB of JavaScript per page against 190 KB for Docusaurus; Lighthouse scored them 100 and 82.",[1168,1536,1537],{},"Docusaurus is the only one with first-class versioning; the others need a branch-per-version deploy.",[1168,1539,1540],{},"Customise with CSS variables and component overrides; ejection is where upgrade pain comes from.",[221,1542,1544],{"id":1543},"faq","FAQ",[1546,1547,1549],"h3",{"id":1548},"should-a-documentation-team-use-a-docs-framework-or-a-general-purpose-ssg","Should a documentation team use a docs framework or a general-purpose SSG?",[14,1551,1552],{},"Use a docs framework when your site is mostly reference and guide pages with a sidebar, search and versioning, because those features arrive configured and maintained. Use a general-purpose generator when the docs share a codebase with a marketing site or need layouts the framework resists. The break-even is roughly the point where you would override more than a third of the theme.",[1546,1554,1556],{"id":1555},"which-of-the-three-builds-fastest","Which of the three builds fastest?",[14,1558,1559],{},"On a 1,200-page Markdown corpus measured with hyperfine on the same runner, VitePress built in about 19 seconds, Starlight in about 41 seconds and Docusaurus in about 96 seconds. The ranking holds as the corpus grows, although Docusaurus narrows the gap when its faster Rspack-based bundler is enabled.",[1546,1561,1563],{"id":1562},"which-framework-has-the-best-versioning-story","Which framework has the best versioning story?",[14,1565,1566],{},"Docusaurus. Versioning is a first-class command that snapshots the docs folder and wires a version dropdown. Starlight and VitePress can serve multiple versions, but you assemble it yourself with branches, separate deploys or a community plugin.",[1546,1568,1570],{"id":1569},"do-these-frameworks-ship-much-javascript","Do these frameworks ship much JavaScript?",[14,1572,1573],{},"It varies by an order of magnitude. A typical Starlight page shipped about 12 KB of compressed JavaScript in our measurements, VitePress about 58 KB because it hydrates as a single-page app, and Docusaurus about 190 KB because the whole page is a React application.",[1546,1575,1577],{"id":1576},"can-i-move-between-them-later","Can I move between them later?",[14,1579,1580],{},"Yes, because all three store content as Markdown or MDX with front matter. The cost is in custom components, sidebar configuration and any MDX that relies on framework-specific imports. Budget for rewriting those rather than the prose itself.",[221,1582,1584],{"id":1583},"related","Related",[1165,1586,1587,1596,1601,1606,1611,1616,1621,1626,1631],{},[1168,1588,1589,1592,1593,1595],{},[23,1590,1591],{},"Up:"," ",[39,1594,42],{"href":41}," — the wider framework decision.",[1168,1597,1598,1600],{},[39,1599,740],{"href":739}," — the head-to-head on a production corpus.",[1168,1602,1603,1605],{},[39,1604,769],{"href":768}," — keeping multi-version builds fast.",[1168,1607,1608,1610],{},[39,1609,1060],{"href":1059}," — brand it and still upgrade.",[1168,1612,1613,1615],{},[39,1614,1448],{"href":1447}," — API docs with TypeDoc and fast builds.",[1168,1617,1618,1620],{},[39,1619,1458],{"href":1457}," — the Python-to-Astro path.",[1168,1622,1623,1625],{},[39,1624,1205],{"href":1204}," — choosing the component syntax.",[1168,1627,1628,1630],{},[39,1629,47],{"href":46}," — the build-it-yourself alternative.",[1168,1632,1633,1636],{},[39,1634,1635],{"href":789},"Search for Static Sites"," — what each framework's search default really costs.",[1638,1639,1640],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}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}",{"title":234,"searchDepth":248,"depth":248,"links":1642},[1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1659],{"id":223,"depth":248,"text":224},{"id":537,"depth":248,"text":538},{"id":743,"depth":248,"text":744},{"id":926,"depth":248,"text":927},{"id":1159,"depth":248,"text":1160},{"id":1310,"depth":248,"text":1311},{"id":1420,"depth":248,"text":1421},{"id":1479,"depth":248,"text":1480},{"id":1522,"depth":248,"text":1523},{"id":1543,"depth":248,"text":1544,"children":1653},[1654,1655,1656,1657,1658],{"id":1548,"depth":271,"text":1549},{"id":1555,"depth":271,"text":1556},{"id":1562,"depth":271,"text":1563},{"id":1569,"depth":271,"text":1570},{"id":1576,"depth":271,"text":1577},{"id":1583,"depth":248,"text":1584},[1661,1664,1665],{"name":1662,"item":1663},"Home","\u002F",{"name":42,"item":41},{"name":5,"item":1666},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002F","2026-09-18","How the three opinionated documentation frameworks differ on build speed, versioning, search, theming and page weight — measured on the same 1,200-page corpus.","md",[1671,1672,1673,1674,1675],{"q":1549,"a":1552},{"q":1556,"a":1559},{"q":1563,"a":1566},{"q":1570,"a":1573},{"q":1577,"a":1580},{},true,"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress",{"title":5,"description":1668},"docs-frameworks-docusaurus-starlight-vitepress","choosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Findex","guide","ba95wAMXluotwiLGgUF44GGu59-Uhl1B2MNg7t1e6GA",[1685,1688,1691,1694,1696,1699,1702,1704,1706,1707,1709,1711,1713,1715,1718,1721,1724,1727,1730,1733,1735,1738,1741,1744,1747,1750,1753,1756,1759,1762,1765,1768,1771,1774,1777,1780,1783,1786,1789,1792,1795,1798,1801,1803,1806,1809,1811,1814,1817,1820,1823,1825,1828,1830,1833,1836,1838,1841,1844,1847,1850,1853,1856,1859,1862,1865,1868,1871,1874,1877,1880,1883,1886,1889,1892,1895,1898,1901,1904,1907,1910,1913,1915,1918,1921,1924,1927,1930,1933,1936,1939,1942,1945,1948,1951,1954,1957,1960,1963,1966,1969,1972,1975,1978,1981,1984,1987,1990,1993,1996,1999,2002,2005,2008,2011,2014,2017,2020,2023,2025,2028,2031,2034,2037,2040,2043,2046,2049,2052,2055,2058,2061,2063,2066,2069,2072,2075,2078,2081,2084,2087,2090,2093,2096,2099,2102,2105,2108,2111,2114,2117,2120,2123,2126,2129,2132,2135,2138,2141,2144,2147,2150,2153,2156,2159,2162,2165,2168,2171,2174,2177,2179,2182,2185,2188,2191,2194,2197,2200,2203,2206,2209,2212],{"path":1686,"title":1687},"\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":1689,"title":1690},"\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":1692,"title":1693},"\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":1695,"title":47},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites",{"path":1697,"title":1698},"\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":1700,"title":1701},"\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":1703,"title":1060},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcustomizing-starlight-without-forking-the-theme",{"path":1705,"title":740},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fdocusaurus-vs-starlight-for-product-documentation",{"path":1678,"title":5},{"path":1708,"title":1205},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmdx-vs-markdoc-for-docs-content",{"path":1710,"title":1458},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-from-mkdocs-to-starlight",{"path":1712,"title":769},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioned-documentation-with-docusaurus",{"path":1714,"title":1448},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-for-library-documentation",{"path":1716,"title":1717},"\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":1719,"title":1720},"\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":1722,"title":1723},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":1725,"title":1726},"\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":1728,"title":1729},"\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":1731,"title":1732},"\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":1734,"title":42},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":1736,"title":1737},"\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":1739,"title":1740},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":1742,"title":1743},"\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":1745,"title":1746},"\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":1748,"title":1749},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds","Speeding Up Slow Jekyll Builds",{"path":1751,"title":1752},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fupgrading-jekyll-and-ruby-versions-safely","Upgrading Jekyll and Ruby Versions Safely",{"path":1754,"title":1755},"\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":1757,"title":1758},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1760,"title":1761},"\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":1763,"title":1764},"\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":1766,"title":1767},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-gatsby-to-astro","Migrating from Gatsby to Astro",{"path":1769,"title":1770},"\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":1772,"title":1773},"\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":1775,"title":1776},"\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":1778,"title":1779},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export","Handling Dynamic Routes in Next.js Static Export",{"path":1781,"title":1782},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":1784,"title":1785},"\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":1787,"title":1788},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations","Next.js App Router Static Export Limitations",{"path":1790,"title":1791},"\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":1793,"title":1794},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Foptimizing-images-in-nextjs-static-export","Optimizing Images in Next.js Static Export",{"path":1796,"title":1797},"\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":1799,"title":1800},"\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":1802,"title":1635},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites",{"path":1804,"title":1805},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Findexing-hugo-sites-with-pagefind","Indexing Hugo Sites with Pagefind",{"path":1807,"title":1808},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fmultilingual-search-on-static-sites","Multilingual Search on Static Sites",{"path":1810,"title":795},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-algolia-docsearch",{"path":1812,"title":1813},"\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":1815,"title":1816},"\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":1818,"title":1819},"\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":1821,"title":1822},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fevaluating-ssg-accessibility-defaults","Evaluating SSG Accessibility Defaults",{"path":1824,"title":52},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix",{"path":1826,"title":1827},"\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":1829,"title":1465},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams",{"path":1831,"title":1832},"\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":1834,"title":1835},"\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":1837,"title":1378},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs",{"path":1839,"title":1840},"\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":1842,"title":1843},"\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":1845,"title":1846},"\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":1848,"title":1849},"\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":1851,"title":1852},"\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":1854,"title":1855},"\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":1857,"title":1858},"\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":1860,"title":1861},"\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":1863,"title":1864},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1866,"title":1867},"\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":1869,"title":1870},"\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":1872,"title":1873},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Ffont-display-optional-vs-swap","font-display: optional vs swap",{"path":1875,"title":1876},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1878,"title":1879},"\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":1881,"title":1882},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fpreloading-fonts-without-double-downloads","Preloading Fonts Without Double Downloads",{"path":1884,"title":1885},"\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":1887,"title":1888},"\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":1890,"title":1891},"\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":1893,"title":1894},"\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":1896,"title":1897},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1899,"title":1900},"\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":1902,"title":1903},"\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":1905,"title":1906},"\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":1908,"title":1909},"\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":1911,"title":1912},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1914,"title":638},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance",{"path":1916,"title":1917},"\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":1919,"title":1920},"\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":1922,"title":1923},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1925,"title":1926},"\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":1928,"title":1929},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Freplacing-react-islands-with-web-components","Replacing React Islands with Web Components",{"path":1931,"title":1932},"\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":1934,"title":1935},"\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":1937,"title":1938},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1940,"title":1941},"\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":1943,"title":1944},"\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":1946,"title":1947},"\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":1949,"title":1950},"\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":1952,"title":1953},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci","Performance Budgets and Lighthouse CI",{"path":1955,"title":1956},"\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":1958,"title":1959},"\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":1961,"title":1962},"\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":1964,"title":1965},"\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":1967,"title":1968},"\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":1970,"title":1971},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fauditing-unused-preloads","Auditing Unused Preloads",{"path":1973,"title":1974},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed","Resource Hints and Navigation Speed",{"path":1976,"title":1977},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Finstant-navigation-with-speculation-rules","Instant Navigation with Speculation Rules",{"path":1979,"title":1980},"\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":1982,"title":1983},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fprefetching-links-in-astro","Prefetching Links in Astro",{"path":1985,"title":1986},"\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":1988,"title":1989},"\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":1991,"title":1992},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1994,"title":1995},"\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":1997,"title":1998},"\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":2000,"title":2001},"\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":2003,"title":2004},"\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":2006,"title":2007},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":2009,"title":2010},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fconfiguring-redirects-on-cloudflare-pages","Configuring Redirects on Cloudflare Pages",{"path":2012,"title":2013},"\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":2015,"title":2016},"\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":2018,"title":2019},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":2021,"title":2022},"\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":2024,"title":1401},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fchecking-links-in-pull-requests",{"path":2026,"title":2027},"\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":2029,"title":2030},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Feditorial-checks-with-vale-in-ci","Editorial Checks with Vale in CI",{"path":2032,"title":2033},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":2035,"title":2036},"\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":2038,"title":2039},"\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":2041,"title":2042},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fbuilding-astro-sites-with-github-actions","Building Astro Sites with GitHub Actions",{"path":2044,"title":2045},"\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":2047,"title":2048},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-github-pages-with-actions","Deploying to GitHub Pages with Actions",{"path":2050,"title":2051},"\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":2053,"title":2054},"\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":2056,"title":2057},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":2059,"title":2060},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fmatrix-builds-for-multi-site-monorepos","Matrix Builds for Multi-Site Monorepos",{"path":2062,"title":533},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions",{"path":2064,"title":2065},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":2067,"title":2068},"\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":2070,"title":2071},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":2073,"title":2074},"\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":2076,"title":2077},"\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":2079,"title":2080},"\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":2082,"title":2083},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":2085,"title":2086},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Falerting-on-cache-hit-ratio-drops","Alerting on Cache Hit Ratio Drops",{"path":2088,"title":2089},"\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":2091,"title":2092},"\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":2094,"title":2095},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production","Monitoring Static Sites in Production",{"path":2097,"title":2098},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Flogging-404s-at-the-edge","Logging 404s at the Edge",{"path":2100,"title":2101},"\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":2103,"title":2104},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fconfiguring-vercel-for-hugo-and-eleventy","Configuring Vercel for Hugo and Eleventy",{"path":2106,"title":2107},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":2109,"title":2110},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":2112,"title":2113},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-redirects-and-rewrites-for-static-sites","Netlify Redirects and Rewrites for Static Sites",{"path":2115,"title":2116},"\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":2118,"title":2119},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-isr-vs-static-generation-for-ssgs","Vercel ISR vs Static Generation for SSGs",{"path":2121,"title":2122},"\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":2124,"title":2125},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":2127,"title":2128},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":2130,"title":2131},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpassword-protecting-preview-deployments","Password-Protecting Preview Deployments",{"path":2133,"title":2134},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpreviewing-headless-cms-drafts","Previewing Headless CMS Drafts",{"path":2136,"title":2137},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fvisual-regression-testing-on-preview-deploys","Visual Regression Testing on Preview Deploys",{"path":2139,"title":2140},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":2142,"title":2143},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fcanary-releases-for-static-sites","Canary Releases for Static Sites",{"path":2145,"title":2146},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Ffeature-flags-on-static-sites","Feature Flags on Static Sites",{"path":2148,"title":2149},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":2151,"title":2152},"\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":2154,"title":2155},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url","Running Smoke Tests Against a Preview URL",{"path":2157,"title":2158},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fauditing-npm-dependencies-in-ssg-pipelines","Auditing npm Dependencies in SSG Pipelines",{"path":2160,"title":2161},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fenabling-hsts-and-preload-safely","Enabling HSTS and Preload Safely",{"path":2163,"title":2164},"\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":2166,"title":2167},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites","Security Headers and Hardening for Static Sites",{"path":2169,"title":2170},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecuring-deploy-credentials-with-github-oidc","Securing Deploy Credentials with GitHub OIDC",{"path":2172,"title":2173},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsubresource-integrity-for-third-party-assets","Subresource Integrity for Third-Party Assets",{"path":2175,"title":2176},"\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":2178,"title":1355},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3",{"path":2180,"title":2181},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fcloudfront-functions-for-redirects","CloudFront Functions for Redirects",{"path":2183,"title":2184},"\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":2186,"title":2187},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites","Self-Hosting Static Sites on S3, Nginx and Caddy",{"path":2189,"title":2190},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy","Serving a Static Site with Caddy",{"path":2192,"title":2193},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-nginx","Serving a Static Site with Nginx",{"path":2195,"title":2196},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fzero-downtime-deploys-with-symlink-swaps","Zero-Downtime Deploys with Symlink Swaps",{"path":2198,"title":2199},"\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":2201,"title":2202},"\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":2204,"title":2205},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites","Serverless Functions for Static Sites",{"path":2207,"title":2208},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fnetlify-functions-vs-cloudflare-workers","Netlify Functions vs Cloudflare Workers",{"path":2210,"title":2211},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fprotecting-a-static-site-behind-authentication","Protecting a Static Site Behind Authentication",{"path":2213,"title":2214},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fproxying-third-party-apis-from-an-edge-function","Proxying Third-Party APIs from an Edge Function",1789722846728]