[{"data":1,"prerenderedAt":1422},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation":3,"all-docs-nav":1182},{"id":4,"title":5,"body":6,"breadcrumb":1154,"dateModified":1164,"datePublished":1164,"description":1165,"extension":1166,"faq":1167,"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\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation\u002Findex.md","Choosing an SSG for API Reference Documentation",{"type":7,"value":8,"toc":1135},"minimark",[9,13,17,26,31,44,48,170,174,177,258,270,274,277,468,547,584,587,591,594,601,609,757,761,764,767,855,859,976,993,996,999,1003,1041,1045,1050,1054,1059,1062,1066,1069,1073,1076,1080,1083,1087,1090,1094,1131],[10,11,5],"h1",{"id":12},"choosing-an-ssg-for-api-reference-documentation",[14,15,16],"p",{},"API reference is documentation with unusual constraints. Most of its pages are generated from an OpenAPI or GraphQL schema rather than written by a person. Several versions are published at once. And the page count is large enough that build time becomes a scheduling problem rather than an annoyance — a 200-endpoint API across four supported versions is easily five thousand pages.",[14,18,19,20,25],{},"Those constraints change which generator is right, and the answer is often different from the one that suits the hand-written guides on the same site. This guide works through the criteria and the trade-offs. It sits under the ",[21,22,24],"a",{"href":23},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002F","SSG Framework Selection Matrix",".",[27,28,30],"h2",{"id":29},"prerequisites","Prerequisites",[32,33,34,38,41],"ul",{},[35,36,37],"li",{},"A machine-readable schema: OpenAPI, GraphQL SDL, Protobuf, or a typed source you can introspect.",[35,39,40],{},"A rough page count: endpoints plus schema objects, multiplied by supported versions.",[35,42,43],{},"A decision about whether reference and guides share one site or two.",[27,45,47],{"id":46},"the-four-constraints-that-decide-it","The Four Constraints That Decide It",[49,50,51,166],"figure",{},[52,53,60,61,60,65,60,69,60,76],"svg",{"viewBox":54,"role":55,"ariaLabelledBy":56,"xmlns":59},"0 0 760 300","img",[57,58],"api-cons-title","api-cons-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[62,63,64],"title",{"id":57},"What makes API reference different",[66,67,68],"desc",{"id":58},"Four constraints. Scale: thousands of pages per version. Generation: most pages come from a schema, not an author. Versioning: several versions published simultaneously. Search: the index outgrows what a client can download. Each constraint maps to a generator capability.",[70,71],"rect",{"x":72,"y":72,"width":73,"height":74,"fill":75},"0","760","300","#ffffff",[77,78,80,81,80,89,80,100,80,106,80,112,80,118,80,123,80,127,80,131,80,134,80,140,80,144,80,148,80,152,80,157,80,160,80,163,60],"g",{"style":79},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[82,83,88],"text",{"x":84,"y":85,"fill":86,"style":87},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","Four constraints, four capabilities to compare",[70,90],{"x":91,"y":92,"width":93,"height":94,"rx":95,"fill":96,"opacity":97,"stroke":98,"style":99},"40","56","330","96","12","#ff595e","0.12","#d83b41","stroke-width:1.5px",[82,101,105],{"x":102,"y":103,"fill":86,"style":104},"205","82","font-size:13px;font-weight:700;text-anchor:middle","Scale",[82,107,111],{"x":108,"y":109,"fill":86,"style":110},"62","110","font-size:12px","1,200 pages per version × 4 versions",[82,113,117],{"x":108,"y":114,"fill":115,"style":116},"134","#556071","font-size:11px","→ raw build throughput matters most",[70,119],{"x":120,"y":92,"width":121,"height":94,"rx":95,"fill":122,"opacity":97,"stroke":122,"style":99},"400","320","#1982c4",[82,124,126],{"x":125,"y":103,"fill":86,"style":104},"560","Generation",[82,128,130],{"x":129,"y":109,"fill":86,"style":110},"424","pages come from a schema",[82,132,133],{"x":129,"y":114,"fill":115,"style":116},"→ programmatic routing, typed data",[70,135],{"x":91,"y":136,"width":93,"height":94,"rx":95,"fill":137,"opacity":138,"stroke":139,"style":99},"168","#ffca3a","0.26","#a97b00",[82,141,143],{"x":102,"y":142,"fill":86,"style":104},"194","Versioning",[82,145,147],{"x":108,"y":146,"fill":86,"style":110},"222","v1 … v4 live at once",[82,149,151],{"x":108,"y":150,"fill":115,"style":116},"246","→ per-version builds, stable URLs",[70,153],{"x":120,"y":136,"width":121,"height":94,"rx":95,"fill":154,"opacity":155,"stroke":156,"style":99},"#8ac926","0.16","#5a8a16",[82,158,159],{"x":125,"y":142,"fill":86,"style":104},"Search",[82,161,162],{"x":129,"y":146,"fill":86,"style":110},"index over 5,000 pages",[82,164,165],{"x":129,"y":150,"fill":115,"style":116},"→ split, trim, or host it",[167,168,169],"figcaption",{},"None of these constraints applies to a fifty-page guide site, which is why the generator that suits your handbook may be the wrong one for your reference.",[27,171,173],{"id":172},"scale-build-throughput-is-the-first-filter","Scale: Build Throughput Is the First Filter",[14,175,176],{},"At five thousand pages, the difference between generators stops being aesthetic. A build that takes four seconds can run on every commit; one that takes eleven minutes cannot, and the workflow around it changes accordingly — fewer deploys, batched changes, and a slower feedback loop for the people writing the surrounding prose.",[178,179,180,199],"table",{},[181,182,183],"thead",{},[184,185,186,190,193,196],"tr",{},[187,188,189],"th",{},"Generator",[187,191,192],{},"5,000 generated pages",[187,194,195],{},"Rebuild after one spec change",[187,197,198],{},"Practical ceiling",[200,201,202,217,231,245],"tbody",{},[184,203,204,208,211,214],{},[205,206,207],"td",{},"Hugo",[205,209,210],{},"9 s",[205,212,213],{},"9 s (full)",[205,215,216],{},"Very high",[184,218,219,222,225,228],{},[205,220,221],{},"Eleventy",[205,223,224],{},"74 s",[205,226,227],{},"3 s (incremental)",[205,229,230],{},"High",[184,232,233,236,239,242],{},[205,234,235],{},"Astro",[205,237,238],{},"260 s",[205,240,241],{},"6 s (dev server)",[205,243,244],{},"Medium",[184,246,247,250,253,256],{},[205,248,249],{},"Next.js export",[205,251,252],{},"340 s",[205,254,255],{},"8 s (dev server)",[205,257,244],{},[14,259,260,261,265,266,25],{},"Two readings of that table matter. Hugo's number is the reason it dominates large reference sites: it is fast enough that no caching or incrementality is needed at all. And Eleventy's second column is the reason it competes: the full build is slower, but ",[262,263,264],"code",{},"--incremental"," makes the edit loop comparable, as covered in ",[21,267,269],{"href":268},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy\u002F","Enabling Incremental Builds in Eleventy",[27,271,273],{"id":272},"generation-how-pages-come-from-the-schema","Generation: How Pages Come From the Schema",[14,275,276],{},"Every generator can produce pages from data; they differ in how much ceremony it takes and how much the build helps you when the schema changes shape.",[278,279,284],"pre",{"className":280,"code":281,"language":282,"meta":283,"style":283},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Eleventy — pagination over an OpenAPI spec produces one page per operation\nmodule.exports = () => {\n  const spec = require('.\u002Fapi\u002Fopenapi.v4.json');\n  const ops = [];\n  for (const [path, methods] of Object.entries(spec.paths)) {\n    for (const [method, op] of Object.entries(methods)) {\n      ops.push({ path, method, id: op.operationId, summary: op.summary, op });\n    }\n  }\n  return ops;\n};\n","javascript","",[262,285,286,295,321,346,359,398,429,441,447,453,462],{"__ignoreMap":283},[287,288,291],"span",{"class":289,"line":290},"line",1,[287,292,294],{"class":293},"sJ8bj","\u002F\u002F Eleventy — pagination over an OpenAPI spec produces one page per operation\n",[287,296,298,302,305,308,312,315,318],{"class":289,"line":297},2,[287,299,301],{"class":300},"sj4cs","module",[287,303,25],{"class":304},"sVt8B",[287,306,307],{"class":300},"exports",[287,309,311],{"class":310},"szBVR"," =",[287,313,314],{"class":304}," () ",[287,316,317],{"class":310},"=>",[287,319,320],{"class":304}," {\n",[287,322,324,327,330,332,336,339,343],{"class":289,"line":323},3,[287,325,326],{"class":310},"  const",[287,328,329],{"class":300}," spec",[287,331,311],{"class":310},[287,333,335],{"class":334},"sScJk"," require",[287,337,338],{"class":304},"(",[287,340,342],{"class":341},"sZZnC","'.\u002Fapi\u002Fopenapi.v4.json'",[287,344,345],{"class":304},");\n",[287,347,349,351,354,356],{"class":289,"line":348},4,[287,350,326],{"class":310},[287,352,353],{"class":300}," ops",[287,355,311],{"class":310},[287,357,358],{"class":304}," [];\n",[287,360,362,365,368,371,374,377,380,383,386,389,392,395],{"class":289,"line":361},5,[287,363,364],{"class":310},"  for",[287,366,367],{"class":304}," (",[287,369,370],{"class":310},"const",[287,372,373],{"class":304}," [",[287,375,376],{"class":300},"path",[287,378,379],{"class":304},", ",[287,381,382],{"class":300},"methods",[287,384,385],{"class":304},"] ",[287,387,388],{"class":310},"of",[287,390,391],{"class":304}," Object.",[287,393,394],{"class":334},"entries",[287,396,397],{"class":304},"(spec.paths)) {\n",[287,399,401,404,406,408,410,413,415,418,420,422,424,426],{"class":289,"line":400},6,[287,402,403],{"class":310},"    for",[287,405,367],{"class":304},[287,407,370],{"class":310},[287,409,373],{"class":304},[287,411,412],{"class":300},"method",[287,414,379],{"class":304},[287,416,417],{"class":300},"op",[287,419,385],{"class":304},[287,421,388],{"class":310},[287,423,391],{"class":304},[287,425,394],{"class":334},[287,427,428],{"class":304},"(methods)) {\n",[287,430,432,435,438],{"class":289,"line":431},7,[287,433,434],{"class":304},"      ops.",[287,436,437],{"class":334},"push",[287,439,440],{"class":304},"({ path, method, id: op.operationId, summary: op.summary, op });\n",[287,442,444],{"class":289,"line":443},8,[287,445,446],{"class":304},"    }\n",[287,448,450],{"class":289,"line":449},9,[287,451,452],{"class":304},"  }\n",[287,454,456,459],{"class":289,"line":455},10,[287,457,458],{"class":310},"  return",[287,460,461],{"class":304}," ops;\n",[287,463,465],{"class":289,"line":464},11,[287,466,467],{"class":304},"};\n",[278,469,473],{"className":470,"code":471,"language":472,"meta":283,"style":283},"language-astro shiki shiki-themes github-light github-dark","---\n\u002F\u002F Astro — getStaticPaths with typed spec data\nimport spec from '..\u002F..\u002Fapi\u002Fopenapi.v4.json';\nexport function getStaticPaths() {\n  return Object.entries(spec.paths).flatMap(([path, methods]) =>\n    Object.entries(methods).map(([method, op]) => ({\n      params: { slug: op.operationId },\n      props: { path, method, op },\n    })));\n}\nconst { path, method, op } = Astro.props;\n---\n\u003Ch1>{method.toUpperCase()} {path}\u003C\u002Fh1>\n\u003Cp>{op.summary}\u003C\u002Fp>\n","astro",[262,474,475,480,485,490,495,500,505,510,515,520,525,530,535,541],{"__ignoreMap":283},[287,476,477],{"class":289,"line":290},[287,478,479],{},"---\n",[287,481,482],{"class":289,"line":297},[287,483,484],{},"\u002F\u002F Astro — getStaticPaths with typed spec data\n",[287,486,487],{"class":289,"line":323},[287,488,489],{},"import spec from '..\u002F..\u002Fapi\u002Fopenapi.v4.json';\n",[287,491,492],{"class":289,"line":348},[287,493,494],{},"export function getStaticPaths() {\n",[287,496,497],{"class":289,"line":361},[287,498,499],{},"  return Object.entries(spec.paths).flatMap(([path, methods]) =>\n",[287,501,502],{"class":289,"line":400},[287,503,504],{},"    Object.entries(methods).map(([method, op]) => ({\n",[287,506,507],{"class":289,"line":431},[287,508,509],{},"      params: { slug: op.operationId },\n",[287,511,512],{"class":289,"line":443},[287,513,514],{},"      props: { path, method, op },\n",[287,516,517],{"class":289,"line":449},[287,518,519],{},"    })));\n",[287,521,522],{"class":289,"line":455},[287,523,524],{},"}\n",[287,526,527],{"class":289,"line":464},[287,528,529],{},"const { path, method, op } = Astro.props;\n",[287,531,533],{"class":289,"line":532},12,[287,534,479],{},[287,536,538],{"class":289,"line":537},13,[287,539,540],{},"\u003Ch1>{method.toUpperCase()} {path}\u003C\u002Fh1>\n",[287,542,544],{"class":289,"line":543},14,[287,545,546],{},"\u003Cp>{op.summary}\u003C\u002Fp>\n",[278,548,552],{"className":549,"code":550,"language":551,"meta":283,"style":283},"language-go-html-template shiki shiki-themes github-light github-dark","{{\u002F* Hugo — one page per operation from a data file, via a headless section *\u002F}}\n{{ range $path, $methods := .Site.Data.openapi_v4.paths }}\n  {{ range $method, $op := $methods }}\n    {{ $.Scratch.Add \"ops\" (dict \"path\" $path \"method\" $method \"op\" $op) }}\n  {{ end }}\n{{ end }}\n","go-html-template",[262,553,554,559,564,569,574,579],{"__ignoreMap":283},[287,555,556],{"class":289,"line":290},[287,557,558],{},"{{\u002F* Hugo — one page per operation from a data file, via a headless section *\u002F}}\n",[287,560,561],{"class":289,"line":297},[287,562,563],{},"{{ range $path, $methods := .Site.Data.openapi_v4.paths }}\n",[287,565,566],{"class":289,"line":323},[287,567,568],{},"  {{ range $method, $op := $methods }}\n",[287,570,571],{"class":289,"line":348},[287,572,573],{},"    {{ $.Scratch.Add \"ops\" (dict \"path\" $path \"method\" $method \"op\" $op) }}\n",[287,575,576],{"class":289,"line":361},[287,577,578],{},"  {{ end }}\n",[287,580,581],{"class":289,"line":400},[287,582,583],{},"{{ end }}\n",[14,585,586],{},"The important difference is not syntax. Astro's typed props mean a spec that changes shape produces a build error at the component boundary; Hugo and Eleventy produce empty output for the missing field and carry on. On a reference site where the spec is generated by another team, that difference decides whether a breaking change is caught at build time or reported by a reader.",[27,588,590],{"id":589},"versioning-the-constraint-people-underestimate","Versioning: The Constraint People Underestimate",[14,592,593],{},"Publishing several versions at once is where reference sites accumulate accidental complexity. The clean model is: version is a path segment, each version is generated from its own frozen spec, and old versions are rebuilt only when their spec changes.",[278,595,599],{"className":596,"code":598,"language":82,"meta":283},[597],"language-text","\u002Fapi\u002Fv4\u002Foperations\u002Fcreate-invoice\u002F     ← current, regenerated on every spec change\n\u002Fapi\u002Fv3\u002Foperations\u002Fcreate-invoice\u002F     ← frozen, rebuilt only if v3 spec changes\n\u002Fapi\u002Fv2\u002F…                              ← frozen\n",[262,600,598],{"__ignoreMap":283},[14,602,603,604,608],{},"Generate each version independently and deploy the union. That way a v4 spec change cannot break v3 pages, and a v2 deprecation is a matter of deleting one directory and adding redirects — the mechanics in ",[21,605,607],{"href":606},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration\u002F","Keeping Redirects Working After an SSG Migration"," apply exactly to version sunsets.",[49,610,611,754],{},[52,612,60,616,60,619,60,622,60,624,60,739],{"viewBox":54,"role":55,"ariaLabelledBy":613,"xmlns":59},[614,615],"api-ver-title","api-ver-desc",[62,617,618],{"id":614},"Per-version generation and deployment",[66,620,621],{"id":615},"Four spec files, one per API version, each generating its own set of pages. Only the current version regenerates on a spec change; older versions are cached artifacts. All four sets deploy together as one site, with a version switcher linking equivalent pages.",[70,623],{"x":72,"y":72,"width":73,"height":74,"fill":75},[77,625,80,626,80,629,80,634,80,639,80,644,80,648,80,651,80,655,80,658,80,662,80,667,80,670,80,672,80,675,80,678,80,680,80,682,80,684,80,691,80,696,80,701,80,705,80,735,60],{"style":79},[82,627,628],{"x":84,"y":85,"fill":86,"style":87},"Independent builds, one deployment",[70,630],{"x":91,"y":92,"width":631,"height":91,"rx":632,"fill":154,"opacity":633,"stroke":156,"style":99},"140","6","0.2",[82,635,638],{"x":109,"y":636,"fill":86,"style":637},"81","font-size:12px;text-anchor:middle","openapi.v4.json",[70,640],{"x":91,"y":641,"width":631,"height":91,"rx":632,"fill":642,"opacity":643,"stroke":115,"style":99},"104","#d9e2ef","0.5",[82,645,647],{"x":109,"y":646,"fill":86,"style":637},"129","openapi.v3.json",[70,649],{"x":91,"y":650,"width":631,"height":91,"rx":632,"fill":642,"opacity":643,"stroke":115,"style":99},"152",[82,652,654],{"x":109,"y":653,"fill":86,"style":637},"177","openapi.v2.json",[70,656],{"x":91,"y":657,"width":631,"height":91,"rx":632,"fill":642,"opacity":643,"stroke":115,"style":99},"200",[82,659,661],{"x":109,"y":660,"fill":86,"style":637},"225","openapi.v1.json",[70,663],{"x":664,"y":92,"width":665,"height":91,"rx":632,"fill":154,"opacity":666,"stroke":156,"style":99},"230","180","0.18",[82,668,669],{"x":121,"y":636,"fill":86,"style":637},"build v4 · 1,240 pages",[70,671],{"x":664,"y":641,"width":665,"height":91,"rx":632,"fill":137,"opacity":138,"stroke":139,"style":99},[82,673,674],{"x":121,"y":646,"fill":86,"style":637},"cached artifact",[70,676],{"x":664,"y":650,"width":665,"height":91,"rx":632,"fill":137,"opacity":677,"stroke":139,"style":99},"0.22",[82,679,674],{"x":121,"y":653,"fill":86,"style":637},[70,681],{"x":664,"y":657,"width":665,"height":91,"rx":632,"fill":137,"opacity":666,"stroke":139,"style":99},[82,683,674],{"x":121,"y":660,"fill":86,"style":637},[70,685],{"x":686,"y":641,"width":687,"height":688,"rx":95,"fill":689,"opacity":690,"stroke":689,"style":99},"460","260","92","#6a4c93","0.14",[82,692,695],{"x":693,"y":694,"fill":86,"style":104},"590","136","one deployment",[82,697,700],{"x":693,"y":698,"fill":115,"style":699},"158","font-size:11px;text-anchor:middle","\u002Fapi\u002Fv1 … \u002Fapi\u002Fv4",[82,702,704],{"x":693,"y":703,"fill":115,"style":699},"176","version switcher links equivalents",[77,706,709,710,709,714,709,717,709,720,709,723,709,726,709,729,709,732,80],{"stroke":115,"fill":707,"style":708},"none","stroke-width:2px","\n      ",[376,711],{"d":712,"style":713},"M182 76 L228 76","marker-end:url(#api-arrow)",[376,715],{"d":716,"style":713},"M182 124 L228 124",[376,718],{"d":719,"style":713},"M182 172 L228 172",[376,721],{"d":722,"style":713},"M182 220 L228 220",[376,724],{"d":725,"style":713},"M412 76 L458 120",[376,727],{"d":728,"style":713},"M412 124 L458 138",[376,730],{"d":731,"style":713},"M412 172 L458 160",[376,733],{"d":734,"style":713},"M412 220 L458 180",[82,736,738],{"x":91,"y":737,"fill":115,"style":116},"276","A v4 spec change rebuilds 1,240 pages, not 5,000 — and cannot affect a frozen version at all",[740,741,80,742,60],"defs",{},[743,744,709,751,80],"marker",{"id":745,"viewBox":746,"refX":747,"refY":748,"markerWidth":749,"markerHeight":749,"orient":750},"api-arrow","0 0 10 10","8","5","7","auto-start-reverse",[376,752],{"d":753,"fill":115},"M0 0 L10 5 L0 10 z",[167,755,756],{},"Caching the frozen versions is what keeps the build proportional to what changed. It also means an old version's pages are byte-identical to what was reviewed when that version shipped.",[27,758,760],{"id":759},"search-the-constraint-that-arrives-late","Search: The Constraint That Arrives Late",[14,762,763],{},"Client-side search is delightful at 200 pages and impossible at 5,000. A prebuilt index over a full reference is several megabytes, which nobody should download to search for one endpoint.",[14,765,766],{},"Three workable answers, in increasing order of effort: index only titles, operation IDs and one-line summaries, which keeps a 5,000-page index around 400 KB; split the index per version and load only the active one; or move search to a hosted service and keep the client payload at zero. Most reference sites end up at the second option and then the third.",[49,768,769,852],{},[52,770,60,775,60,778,60,781,60,784],{"viewBox":771,"role":55,"ariaLabelledBy":772,"xmlns":59},"0 0 760 290",[773,774],"api-search-title","api-search-desc",[62,776,777],{"id":773},"Search index size as a reference site grows",[66,779,780],{"id":774},"Index size against page count for three strategies. A full-text index reaches 5.8 megabytes at 5,000 pages. A titles-and-summaries index stays around 400 kilobytes. A per-version split index stays around 120 kilobytes for the active version. A dashed line marks a 500 kilobyte practical download budget.",[70,782],{"x":72,"y":72,"width":73,"height":783,"fill":75},"290",[77,785,80,786,80,790,80,795,80,798,80,802,80,807,80,812,80,815,80,819,80,823,80,828,80,833,80,836,80,840,80,844,80,848,60],{"style":79},[82,787,789],{"x":84,"y":788,"fill":86,"style":87},"26","The index outgrows the client before the site feels large",[289,791],{"x1":792,"y1":793,"x2":792,"y2":794,"stroke":115,"style":99},"100","52","204",[289,796],{"x1":792,"y1":794,"x2":797,"y2":794,"stroke":115,"style":99},"700",[289,799],{"x1":792,"y1":800,"x2":797,"y2":800,"stroke":154,"style":801},"186","stroke-width:2px;stroke-dasharray:6 5",[82,803,806],{"x":804,"y":665,"fill":156,"style":805},"580","font-size:11px;font-weight:700","500 KB budget",[808,809],"polyline",{"points":810,"fill":707,"stroke":98,"style":811},"150,200 300,168 450,116 640,58","stroke-width:2.5px",[808,813],{"points":814,"fill":707,"stroke":139,"style":811},"150,202 300,197 450,192 640,188",[808,816],{"points":817,"fill":707,"stroke":156,"style":818},"150,203 300,201 450,200 640,199","stroke-width:2.5px;stroke-dasharray:7 5",[82,820,822],{"x":821,"y":793,"fill":98,"style":805},"540","full text · 5.8 MB",[82,824,827],{"x":825,"y":826,"fill":139,"style":805},"520","212","titles + summaries · 400 KB",[82,829,832],{"x":830,"y":831,"fill":115,"style":699},"150","228","500",[82,834,835],{"x":74,"y":831,"fill":115,"style":699},"1,500",[82,837,839],{"x":838,"y":831,"fill":115,"style":699},"450","3,000",[82,841,843],{"x":842,"y":831,"fill":115,"style":699},"640","5,000 pages",[82,845,847],{"x":792,"y":846,"fill":115,"style":116},"258","Green dashed: per-version split index, ~120 KB for the active version only",[82,849,851],{"x":792,"y":850,"fill":115,"style":116},"278","Measured on generated OpenAPI reference output with a standard client-side index",[167,853,854],{},"Full-text indexing crosses a reasonable download budget somewhere around 1,500 pages, which on a reference site is one version of a medium API.",[27,856,858],{"id":857},"putting-it-together","Putting It Together",[178,860,861,877],{},[181,862,863],{},[184,864,865,868,870,872,874],{},[187,866,867],{},"Criterion",[187,869,207],{},[187,871,221],{},[187,873,235],{},[187,875,876],{},"Next export",[200,878,879,895,917,932,946,962],{},[184,880,881,884,887,890,893],{},[205,882,883],{},"Build at 5,000 pages",[205,885,886],{},"Excellent",[205,888,889],{},"Good",[205,891,892],{},"Fair",[205,894,892],{},[184,896,897,900,903,906,912],{},[205,898,899],{},"Schema-driven pages",[205,901,902],{},"Data files",[205,904,905],{},"Pagination",[205,907,908,911],{},[262,909,910],{},"getStaticPaths"," + types",[205,913,914],{},[262,915,916],{},"generateStaticParams",[184,918,919,922,925,927,930],{},[205,920,921],{},"Type-checked spec changes",[205,923,924],{},"No",[205,926,924],{},[205,928,929],{},"Yes",[205,931,929],{},[184,933,934,937,940,942,944],{},[205,935,936],{},"Per-version isolation",[205,938,939],{},"Easy",[205,941,939],{},[205,943,939],{},[205,945,939],{},[184,947,948,951,954,956,959],{},[205,949,950],{},"Interactive try-it components",[205,952,953],{},"Limited",[205,955,953],{},[205,957,958],{},"Native islands",[205,960,961],{},"Native",[184,963,964,967,970,972,974],{},[205,965,966],{},"Shared design system with the app",[205,968,969],{},"Hard",[205,971,969],{},[205,973,929],{},[205,975,929],{},[14,977,978,979,982,983,985,986,988,989,25],{},"The practical split: ",[980,981,207],"strong",{}," when the reference is large and mostly static, ",[980,984,235],{}," when it is smaller and needs interactive request builders sharing components with the product, and ",[980,987,221],{}," when you want a middle ground with an excellent edit loop. Next.js export makes sense mainly when the documentation is part of a Next application already — the constraints of that target are in ",[21,990,992],{"href":991},"\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",[14,994,995],{},"One more consideration decides more of these choices than the table suggests: who owns the reference. When the schema and the generator both belong to the API team, a fast build with plain templates is usually right, because the people maintaining it are not front-end specialists and will not enjoy a component framework. When the reference is owned by the same team that builds the product's interface, sharing components is worth real build time — a try-it panel that behaves exactly like the product's console is a genuinely better document than a code sample.",[14,997,998],{},"A perfectly reasonable answer is two generators: Hugo for the reference, something component-friendly for the guides, joined at the edge by path. It costs a routing rule and removes the compromise entirely.",[27,1000,1002],{"id":1001},"pitfalls-rollback","Pitfalls & Rollback",[32,1004,1005,1011,1017,1023,1029,1035],{},[35,1006,1007,1010],{},[980,1008,1009],{},"Choosing on the guides and inheriting it for the reference."," The constraints are different by an order of magnitude.",[35,1012,1013,1016],{},[980,1014,1015],{},"Committing generated pages."," Diffs become unreviewable and hand edits silently diverge from the spec.",[35,1018,1019,1022],{},[980,1020,1021],{},"Rebuilding every version on every change."," Freeze old versions as artifacts; only the current one needs regenerating.",[35,1024,1025,1028],{},[980,1026,1027],{},"Deferring the search decision."," The index outgrows the client somewhere around a thousand pages, usually without warning.",[35,1030,1031,1034],{},[980,1032,1033],{},"Ignoring spec-shape changes."," Without type checking, a renamed field produces empty sections rather than an error.",[35,1036,1037,1040],{},[980,1038,1039],{},"Rollback:"," because reference output is generated, switching generators is a matter of rewriting templates rather than migrating content. That is the one genuine advantage of a corpus nobody hand-edits.",[27,1042,1044],{"id":1043},"conclusion","Conclusion",[14,1046,1047,1048,25],{},"Pick for the reference's constraints, not the guides': raw build throughput first, then how much the build helps when the schema changes, then per-version isolation, then search. Hugo wins on scale, Astro wins on interactivity and type safety, Eleventy sits comfortably between them, and running two generators joined at the edge is a legitimate answer rather than an admission of defeat. The general comparison is in the ",[21,1049,24],{"href":23},[27,1051,1053],{"id":1052},"faq","FAQ",[1055,1056,1058],"h3",{"id":1057},"what-makes-api-reference-different-from-other-documentation","What makes API reference different from other documentation?",[14,1060,1061],{},"Three things: most pages are generated from a schema rather than written, several versions are published simultaneously, and the page count is an order of magnitude larger than the hand-written guides around it. Every selection criterion follows from those.",[1055,1063,1065],{"id":1064},"how-many-pages-does-a-typical-api-reference-produce","How many pages does a typical API reference produce?",[14,1067,1068],{},"A medium REST API with 200 endpoints and 400 schema objects produces roughly 600 to 1,200 pages per version once you emit a page per operation and per model. Multiply by the number of supported versions and a two-year-old product is comfortably past 5,000 pages.",[1055,1070,1072],{"id":1071},"should-generated-pages-live-in-the-repository","Should generated pages live in the repository?",[14,1074,1075],{},"Generate them into a build directory rather than committing them. Committed generated pages create enormous diffs, hide real content changes in review, and drift from the spec whenever someone edits the output by hand.",[1055,1077,1079],{"id":1078},"how-do-i-handle-multiple-api-versions","How do I handle multiple API versions?",[14,1081,1082],{},"Treat the version as a path segment and the spec as an input, then generate each version from its own spec file. Keep old versions as static output that is regenerated only when their spec changes, so publishing a new version does not risk the old ones.",[1055,1084,1086],{"id":1085},"does-client-side-search-work-at-this-scale","Does client-side search work at this scale?",[14,1088,1089],{},"Up to a point. A prebuilt index over 5,000 pages is several megabytes, which is too much to ship. Either index only titles and summaries, split the index by version, or move search to a hosted service — the decision usually arrives sooner than teams expect.",[27,1091,1093],{"id":1092},"related","Related",[32,1095,1096,1105,1112,1119,1124],{},[35,1097,1098,1101,1102,1104],{},[980,1099,1100],{},"Parent:"," ",[21,1103,24],{"href":23}," — the general comparison this specialises.",[35,1106,1107,1111],{},[21,1108,1110],{"href":1109},"\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"," — the process around the decision.",[35,1113,1114,1118],{},[21,1115,1117],{"href":1116},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002F","Hugo Build Times for Large Repositories"," — why Hugo dominates at this scale.",[35,1120,1121,1123],{},[21,1122,992],{"href":991}," — the export target's constraints.",[35,1125,1126,1130],{},[21,1127,1129],{"href":1128},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fcontent-collections-vs-eleventy-data-cascade\u002F","Content Collections vs the Eleventy Data Cascade"," — type checking for schema-driven content.",[1132,1133,1134],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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);}",{"title":283,"searchDepth":297,"depth":297,"links":1136},[1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1153],{"id":29,"depth":297,"text":30},{"id":46,"depth":297,"text":47},{"id":172,"depth":297,"text":173},{"id":272,"depth":297,"text":273},{"id":589,"depth":297,"text":590},{"id":759,"depth":297,"text":760},{"id":857,"depth":297,"text":858},{"id":1001,"depth":297,"text":1002},{"id":1043,"depth":297,"text":1044},{"id":1052,"depth":297,"text":1053,"children":1147},[1148,1149,1150,1151,1152],{"id":1057,"depth":323,"text":1058},{"id":1064,"depth":323,"text":1065},{"id":1071,"depth":323,"text":1072},{"id":1078,"depth":323,"text":1079},{"id":1085,"depth":323,"text":1086},{"id":1092,"depth":297,"text":1093},[1155,1158,1161,1162],{"name":1156,"item":1157},"Home","\u002F",{"name":1159,"item":1160},"Choosing the Right Static Site Generator for Production","\u002Fchoosing-the-right-static-site-generator-for-production\u002F",{"name":24,"item":23},{"name":5,"item":1163},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation\u002F","2026-08-01","API docs are generated, versioned and enormous. Compare Hugo, Astro, Eleventy and Next export on build scale, schema-driven pages, versioning and search.","md",[1168,1171,1172,1173,1174],{"q":1058,"a":1169},{"Three things":1170},"most pages are generated from a schema rather than written, several versions are published simultaneously, and the page count is an order of magnitude larger than the hand-written guides around it. Every selection criterion follows from those.",{"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\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation",{"title":5,"description":1165},"choosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation\u002Findex","article","_cEgXpK8Nif-8n4yjo7USj6djV1aoSKKo0KnnEg7B4o",[1183,1186,1188,1191,1194,1196,1199,1202,1204,1207,1210,1213,1216,1219,1221,1224,1227,1230,1232,1235,1238,1241,1244,1245,1247,1250,1252,1255,1258,1261,1264,1267,1270,1273,1276,1279,1282,1285,1288,1291,1294,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,1377,1380,1383,1386,1389,1392,1395,1398,1401,1404,1407,1410,1413,1416,1419],{"path":1184,"title":1185},"\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":1187,"title":1129},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fcontent-collections-vs-eleventy-data-cascade",{"path":1189,"title":1190},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":1192,"title":1193},"\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":1195,"title":1117},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories",{"path":1197,"title":1198},"\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":1200,"title":1201},"\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":1203,"title":1159},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":1205,"title":1206},"\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":1208,"title":1209},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":1211,"title":1212},"\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":1214,"title":1215},"\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":1217,"title":1218},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1220,"title":607},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration",{"path":1222,"title":1223},"\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":1225,"title":1226},"\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":1228,"title":1229},"\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":1231,"title":992},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export",{"path":1233,"title":1234},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":1236,"title":1237},"\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":1239,"title":1240},"\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":1242,"title":1243},"\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":1177,"title":5},{"path":1246,"title":24},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix",{"path":1248,"title":1249},"\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":1251,"title":1110},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams",{"path":1253,"title":1254},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":1256,"title":1257},"\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":1259,"title":1260},"\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":1262,"title":1263},"\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":1265,"title":1266},"\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":1268,"title":1269},"\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":1271,"title":1272},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1274,"title":1275},"\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":1277,"title":1278},"\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":1280,"title":1281},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1283,"title":1284},"\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":1286,"title":1287},"\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":1289,"title":1290},"\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":1292,"title":1293},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1295,"title":1296},"\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":1298,"title":1299},"\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":1301,"title":1302},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1304,"title":1305},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":1307,"title":1308},"\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":1310,"title":1311},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1313,"title":1314},"\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":1316,"title":1317},"\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":1319,"title":1320},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1322,"title":1323},"\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":1325,"title":1326},"\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":1328,"title":1329},"\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":1331,"title":1332},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1334,"title":1335},"\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":1337,"title":1338},"\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":1340,"title":1341},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":1343,"title":1344},"\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":1346,"title":1347},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":1349,"title":1350},"\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":1352,"title":1353},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":1355,"title":1356},"\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":1358,"title":1359},"\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":1361,"title":1362},"\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":1364,"title":1365},"\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":1367,"title":1368},"\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":1370,"title":1371},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1373,"title":1374},"\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":1376,"title":269},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy",{"path":1378,"title":1379},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":1381,"title":1382},"\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":1384,"title":1385},"\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":1387,"title":1388},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":1390,"title":1391},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":1393,"title":1394},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":1396,"title":1397},"\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":1399,"title":1400},"\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":1402,"title":1403},"\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":1405,"title":1406},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":1408,"title":1409},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":1411,"title":1412},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":1414,"title":1415},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":1417,"title":1418},"\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":1420,"title":1421},"\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",1785611671115]