[{"data":1,"prerenderedAt":1073},["ShallowReactive",2],{"page:\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers":3,"all-docs-nav":829},{"id":4,"title":5,"body":6,"breadcrumb":802,"dateModified":812,"datePublished":812,"description":813,"extension":814,"faq":815,"meta":823,"navigation":274,"path":824,"seo":825,"slug":12,"stem":826,"type":827,"__hash__":828},"content\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers\u002Findex.md","Docs-as-Code Review Workflow for Writers",{"type":7,"value":8,"toc":782},"minimark",[9,13,17,26,31,44,48,175,183,186,196,200,203,206,209,230,234,237,243,249,328,333,422,426,429,435,441,447,451,454,468,476,480,483,486,489,493,496,574,646,650,688,692,697,701,706,709,713,716,720,723,727,730,734,737,741,778],[10,11,5],"h1",{"id":12},"docs-as-code-review-workflow-for-writers",[14,15,16],"p",{},"Docs-as-code gets documentation the things code has had for years: versioning, review, previews and automated checks. It also imports code review's failure modes — pull requests that sit for a week, comments about commas, and a process that quietly excludes anyone who is not comfortable with branches.",[14,18,19,20,25],{},"This guide is the workflow that avoids those: how to size a change, what to name a branch, how to make the preview the review, and a checklist short enough that reviewers actually use it. It is the day-to-day practice inside ",[21,22,24],"a",{"href":23},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002F","Content Workflows for Documentation Teams",".",[27,28,30],"h2",{"id":29},"prerequisites","Prerequisites",[32,33,34,38,41],"ul",{},[35,36,37],"li",{},"Preview deploys on every pull request, arriving in a couple of minutes.",[35,39,40],{},"Content build gates already running: links, front matter, spelling, terminology.",[35,42,43],{},"A written style guide, even a short one, so wording debates have somewhere to resolve.",[27,45,47],{"id":46},"size-the-change-first","Size the Change First",[49,50,51,171],"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],"dac-size-title","dac-size-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[62,63,64],"title",{"id":57},"Review latency by pull request size",[66,67,68],"desc",{"id":58},"A chart relating pull request size to median review time. A single-page change is reviewed in about three hours. A change touching two to four pages takes about eight hours. A change touching five to ten pages takes two days, and anything larger takes over four days and often receives only a cursory review.",[70,71],"rect",{"x":72,"y":72,"width":73,"height":74,"fill":75},"0","760","300","#ffffff",[77,78,80,81,80,89,80,97,80,103,80,112,80,117,80,121,80,126,80,131,80,135,80,142,80,147,80,151,80,158,80,164,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","Small changes are not just faster to write",[90,91],"line",{"x1":92,"y1":93,"x2":92,"y2":94,"stroke":95,"style":96},"250","48","222","#d9e2ef","stroke-width:1.5px",[82,98,102],{"x":99,"y":100,"fill":86,"style":101},"60","80","font-size:12px;font-weight:700","1 page",[70,104],{"x":92,"y":105,"width":106,"height":107,"rx":108,"fill":109,"opacity":110,"stroke":111,"style":96},"62","52","30","5","#8ac926","0.28","#5a8a16",[82,113,116],{"x":114,"y":115,"fill":111,"style":101},"322","82","3 hours",[82,118,120],{"x":99,"y":119,"fill":86,"style":101},"132","2–4 pages",[70,122],{"x":92,"y":123,"width":124,"height":107,"rx":108,"fill":109,"opacity":125,"stroke":111,"style":96},"114","138","0.2",[82,127,130],{"x":128,"y":129,"fill":111,"style":101},"408","134","8 hours",[82,132,134],{"x":99,"y":133,"fill":86,"style":101},"184","5–10 pages",[70,136],{"x":92,"y":137,"width":138,"height":107,"rx":108,"fill":139,"opacity":140,"stroke":141,"style":96},"166","290","#ffca3a","0.34","#a97b00",[82,143,146],{"x":144,"y":145,"fill":141,"style":101},"560","186","2 days",[82,148,150],{"x":99,"y":149,"fill":86,"style":101},"236","10+ pages",[70,152],{"x":92,"y":153,"width":154,"height":107,"rx":108,"fill":155,"opacity":156,"stroke":157,"style":96},"218","420","#ff595e","0.16","#d83b41",[82,159,163],{"x":160,"y":161,"fill":157,"style":162},"460","238","font-size:12px;font-weight:700;text-anchor:middle","4+ days, often reviewed superficially",[82,165,170],{"x":166,"y":167,"fill":168,"style":169},"207","278","#556071","font-size:11px","Median time to first review · one documentation team, 240 pull requests over two quarters",[172,173,174],"figcaption",{},"The relationship is worse than linear: past about five pages, reviewers defer the change rather than start it, and the ones that do get reviewed get less scrutiny per page.",[14,176,177,178,182],{},"The practical rule: ",[179,180,181],"strong",{},"one page per pull request, or one coherent change across a few."," When a task is genuinely large — restructuring a section, renaming a group of pages — split it into a structural pull request (moves and redirects, no prose changes) and one or more content pull requests. The structural one is reviewed by looking at the URL diff; the content ones are reviewed by reading.",[14,184,185],{},"Branch names are worth a convention because they show up in every preview URL and every notification:",[187,188,193],"pre",{"className":189,"code":191,"language":82,"meta":192},[190],"language-text","docs\u002Fdeploying-hugo-to-workers        # new or substantially rewritten page\nfix\u002Fbroken-links-in-caching-guide     # correction\nstruct\u002Fsplit-deployment-section       # moves, renames, redirects — no prose\n","",[194,195,191],"code",{"__ignoreMap":192},[27,197,199],{"id":198},"make-the-preview-the-review","Make the Preview the Review",[14,201,202],{},"Reviewing a documentation diff is reviewing the source code of a page nobody has read. The rendered preview shows what the reader gets: heading hierarchy, code block formatting, table rendering, whether the diagram still matches the text.",[14,204,205],{},"Put the preview link in the pull request automatically, and make the review request point at it rather than at the diff. On a well-configured pipeline the sequence is: push, gates run in about ninety seconds, preview appears in about two minutes, reviewer opens the page. Anything slower and reviewers fall back to reading the diff, which is where the mechanical comments come from.",[14,207,208],{},"For substantial changes, ask the author to include three things in the pull request description:",[210,211,212,218,224],"ol",{},[35,213,214,217],{},[179,215,216],{},"What question this page answers",", in one sentence.",[35,219,220,223],{},[179,221,222],{},"What changed and why",", if it is an edit rather than a new page.",[35,225,226,229],{},[179,227,228],{},"Anything they are unsure about"," — the single highest-value line, because it directs review attention where it is actually needed.",[27,231,233],{"id":232},"two-passes-not-one-argument","Two Passes, Not One Argument",[14,235,236],{},"Reading for accuracy and reading for clarity are different activities, and mixing them produces reviews that wander. Do them as explicit passes, even when one person does both.",[14,238,239,242],{},[179,240,241],{},"Pass one — is it true?"," Do the commands run? Do the numbers match a real measurement, and is the tool that produced them named? Is the version current? Does the page contradict another page? A subject-matter reviewer answers these, and nothing else.",[14,244,245,248],{},[179,246,247],{},"Pass two — is it clear and consistent?"," Does the title match what the page delivers? Is the structure scannable? Does it use the site's terminology? Does the introduction tell a reader whether they are in the right place? An editorial reviewer answers these.",[187,250,254],{"className":251,"code":252,"language":253,"meta":192,"style":192},"language-markdown shiki shiki-themes github-light github-dark","\u003C!-- .github\u002Fpull_request_template.md -->\n## What question does this page answer?\n\n## What changed and why?\n\n## Anything you want a second opinion on?\n\n---\n- [ ] Preview checked (link appears below once the build finishes)\n- [ ] Commands and config in this page were run, not paraphrased\n- [ ] Numbers name the tool that produced them\n- [ ] Links point at the most specific page available\n","markdown",[194,255,256,263,269,276,282,287,293,298,304,310,316,322],{"__ignoreMap":192},[257,258,260],"span",{"class":90,"line":259},1,[257,261,262],{},"\u003C!-- .github\u002Fpull_request_template.md -->\n",[257,264,266],{"class":90,"line":265},2,[257,267,268],{},"## What question does this page answer?\n",[257,270,272],{"class":90,"line":271},3,[257,273,275],{"emptyLinePlaceholder":274},true,"\n",[257,277,279],{"class":90,"line":278},4,[257,280,281],{},"## What changed and why?\n",[257,283,285],{"class":90,"line":284},5,[257,286,275],{"emptyLinePlaceholder":274},[257,288,290],{"class":90,"line":289},6,[257,291,292],{},"## Anything you want a second opinion on?\n",[257,294,296],{"class":90,"line":295},7,[257,297,275],{"emptyLinePlaceholder":274},[257,299,301],{"class":90,"line":300},8,[257,302,303],{},"---\n",[257,305,307],{"class":90,"line":306},9,[257,308,309],{},"- [ ] Preview checked (link appears below once the build finishes)\n",[257,311,313],{"class":90,"line":312},10,[257,314,315],{},"- [ ] Commands and config in this page were run, not paraphrased\n",[257,317,319],{"class":90,"line":318},11,[257,320,321],{},"- [ ] Numbers name the tool that produced them\n",[257,323,325],{"class":90,"line":324},12,[257,326,327],{},"- [ ] Links point at the most specific page available\n",[14,329,330,331,25],{},"Everything mechanical stays out of that template. If a reviewer finds themselves commenting on spelling or a broken link, that is a missing build gate, not a review finding — the gates are in ",[21,332,24],{"href":23},[49,334,335,419],{},[52,336,60,341,60,344,60,347,60,349],{"viewBox":337,"role":55,"ariaLabelledBy":338,"xmlns":59},"0 0 760 290",[339,340],"dac-pass-title","dac-pass-desc",[62,342,343],{"id":339},"Two review passes and what each owns",[66,345,346],{"id":340},"Two columns. The accuracy pass owns whether commands run, whether numbers are measured and attributed, whether versions are current and whether the page contradicts another. The clarity pass owns title fit, structure, terminology and whether a reader arriving from search can orient themselves. A third box below shows the build gates that own everything mechanical.",[70,348],{"x":72,"y":72,"width":73,"height":138,"fill":75},[77,350,80,351,80,354,80,362,80,368,80,373,80,377,80,381,80,385,80,390,80,393,80,397,80,400,80,403,80,406,80,411,80,415,60],{"style":79},[82,352,353],{"x":84,"y":85,"fill":86,"style":87},"Separate the two kinds of attention",[70,355],{"x":356,"y":106,"width":357,"height":358,"rx":359,"fill":360,"opacity":361,"stroke":360,"style":96},"40","330","140","12","#1982c4","0.12",[82,363,367],{"x":364,"y":365,"fill":86,"style":366},"205","78","font-size:13px;font-weight:700;text-anchor:middle","Pass 1 · Is it true?",[82,369,372],{"x":105,"y":370,"fill":86,"style":371},"106","font-size:12px","commands actually run",[82,374,376],{"x":105,"y":375,"fill":86,"style":371},"130","numbers name their tool",[82,378,380],{"x":105,"y":379,"fill":86,"style":371},"154","versions are current",[82,382,384],{"x":105,"y":383,"fill":86,"style":371},"178","no contradiction elsewhere",[70,386],{"x":387,"y":106,"width":388,"height":358,"rx":359,"fill":389,"opacity":361,"stroke":389,"style":96},"400","320","#6a4c93",[82,391,392],{"x":144,"y":365,"fill":86,"style":366},"Pass 2 · Is it clear?",[82,394,396],{"x":395,"y":370,"fill":86,"style":371},"424","title matches delivery",[82,398,399],{"x":395,"y":375,"fill":86,"style":371},"structure is scannable",[82,401,402],{"x":395,"y":379,"fill":86,"style":371},"terminology is consistent",[82,404,405],{"x":395,"y":383,"fill":86,"style":371},"a search arrival can orient",[70,407],{"x":356,"y":408,"width":409,"height":106,"rx":410,"fill":109,"opacity":156,"stroke":111,"style":96},"210","680","10",[82,412,414],{"x":84,"y":413,"fill":86,"style":162},"232","Build gates · links, front matter, spelling, terminology, image size",[82,416,418],{"x":84,"y":92,"fill":168,"style":417},"font-size:11px;text-anchor:middle","never a review comment — the author sees these before a reviewer does",[172,420,421],{},"When a comment lands in the green band, the fix is to add a check, not to remind the author. That is the mechanism by which review quality improves over time instead of decaying.",[27,423,425],{"id":424},"keep-reviews-moving","Keep Reviews Moving",[14,427,428],{},"Latency, not effort, is what kills documentation review. Three practices keep it short.",[14,430,431,434],{},[179,432,433],{},"A named reviewer."," A rotating reviewer of the week removes the \"someone will pick it up\" queue, which is where most of the waiting happens.",[14,436,437,440],{},[179,438,439],{},"A response-time expectation."," One working day to a first response — not to approval. A comment saying \"reading this tomorrow morning\" is a valid first response and stops the author from context-switching away entirely.",[14,442,443,446],{},[179,444,445],{},"Approve with suggestions."," For anything that is not factually wrong, approve and leave suggestions rather than blocking. Documentation improves continuously; a page that is 90% right and published beats a page that is 100% right and unmerged.",[27,448,450],{"id":449},"handle-structural-changes-separately","Handle Structural Changes Separately",[14,452,453],{},"Renames and moves are the changes most likely to break things and least likely to be read carefully, because the diff is enormous and mostly mechanical. Give them their own pull request with a specific checklist:",[32,455,456,459,462,465],{},[35,457,458],{},"Every moved URL has a redirect, generated rather than hand-written.",[35,460,461],{},"Internal links to the moved pages were updated (the link check proves it).",[35,463,464],{},"The navigation and any manual index pages were updated.",[35,466,467],{},"No prose changed in this pull request — so the diff is verifiable by inspection.",[14,469,470,471,475],{},"The redirect mechanics are in ",[21,472,474],{"href":473},"\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","; they apply to a routine reorganisation exactly as they do to a migration.",[27,477,479],{"id":478},"onboarding-someone-in-an-afternoon","Onboarding Someone in an Afternoon",[14,481,482],{},"The test of a docs-as-code workflow is how long it takes a new contributor to publish their first change. If the answer is more than an afternoon, the process has accumulated steps that exist for the team's convenience rather than the reader's benefit.",[14,484,485],{},"Write the onboarding path as a single page with exactly the steps required, and have a new contributor follow it to publish something real — a typo fix, a clarified sentence — rather than a sandbox change. Whatever they get stuck on is a defect in the workflow, not in them. The three most common blockers are an unexplained branch naming convention, a required local build that is not actually required, and a review queue with no named owner.",[14,487,488],{},"Keep the first contribution deliberately small. Someone who has merged one pull request understands the shape of the process and will happily attempt a larger change next week; someone whose first attempt was a section rewrite that sat unreviewed for a fortnight usually does not come back.",[27,490,492],{"id":491},"measured-impact","Measured Impact",[14,494,495],{},"One documentation team of nine, comparing the quarter before adopting these practices with the quarter after:",[497,498,499,515],"table",{},[500,501,502],"thead",{},[503,504,505,509,512],"tr",{},[506,507,508],"th",{},"Measure",[506,510,511],{},"Before",[506,513,514],{},"After",[516,517,518,530,541,552,563],"tbody",{},[503,519,520,524,527],{},[521,522,523],"td",{},"Median pages per pull request",[521,525,526],{},"4.6",[521,528,529],{},"1.2",[503,531,532,535,538],{},[521,533,534],{},"Median time to first review",[521,536,537],{},"2.1 days",[521,539,540],{},"4 hours",[503,542,543,546,549],{},[521,544,545],{},"Median time to merge",[521,547,548],{},"6.2 days",[521,550,551],{},"0.6 days",[503,553,554,557,560],{},[521,555,556],{},"Mechanical review comments per PR",[521,558,559],{},"7.9",[521,561,562],{},"0.7",[503,564,565,568,571],{},[521,566,567],{},"Pull requests abandoned unmerged",[521,569,570],{},"17%",[521,572,573],{},"4%",[49,575,576,643],{},[52,577,60,582,60,585,60,588,60,591],{"viewBox":578,"role":55,"ariaLabelledBy":579,"xmlns":59},"0 0 760 280",[580,581],"dac-impact-title","dac-impact-desc",[62,583,584],{"id":580},"Time to merge before and after the workflow changes",[66,586,587],{"id":581},"A horizontal bar comparison. Median time to merge fell from 6.2 days to 0.6 days, and the abandonment rate fell from 17 percent to 4 percent, after pull requests were made smaller and previews became the review artifact.",[70,589],{"x":72,"y":72,"width":73,"height":590,"fill":75},"280",[77,592,80,593,80,597,80,602,80,605,80,609,80,613,80,616,80,619,80,622,80,625,80,629,80,633,80,636,80,639,60],{"style":79},[82,594,596],{"x":84,"y":595,"fill":86,"style":87},"26","Smaller changes, faster reviews, fewer abandoned",[90,598],{"x1":599,"y1":600,"x2":599,"y2":601,"stroke":95,"style":96},"260","44","212",[82,603,604],{"x":99,"y":115,"fill":86,"style":101},"Time to merge · before",[70,606],{"x":599,"y":607,"width":608,"height":107,"rx":108,"fill":155,"opacity":156,"stroke":157,"style":96},"64","410",[82,610,548],{"x":611,"y":612,"fill":157,"style":162},"465","84",[82,614,615],{"x":99,"y":129,"fill":86,"style":101},"Time to merge · after",[70,617],{"x":599,"y":618,"width":356,"height":107,"rx":108,"fill":109,"opacity":110,"stroke":111,"style":96},"116",[82,620,551],{"x":114,"y":621,"fill":111,"style":101},"136",[82,623,624],{"x":99,"y":145,"fill":86,"style":101},"Abandoned PRs",[70,626],{"x":599,"y":627,"width":628,"height":107,"rx":108,"fill":139,"opacity":140,"stroke":141,"style":96},"168","170",[82,630,570],{"x":631,"y":632,"fill":86,"style":162},"345","188",[70,634],{"x":635,"y":627,"width":356,"height":107,"rx":108,"fill":109,"opacity":110,"stroke":111,"style":96},"450",[82,637,573],{"x":638,"y":632,"fill":111,"style":101},"512",[82,640,642],{"x":599,"y":641,"fill":168,"style":169},"252","240 pull requests, two quarters, same team and same reviewers throughout",[172,644,645],{},"The abandonment number is the one worth watching. A pull request that is never merged represents work someone did and readers never received.",[27,647,649],{"id":648},"pitfalls-rollback","Pitfalls & Rollback",[32,651,652,658,664,670,676,682],{},[35,653,654,657],{},[179,655,656],{},"Large pull requests."," They are deferred, then rubber-stamped. Split structural changes from content changes.",[35,659,660,663],{},[179,661,662],{},"Blocking on style preferences."," Approve with suggestions unless the page is wrong; write the convention down instead of arguing it twice.",[35,665,666,669],{},[179,667,668],{},"Reviewing the diff."," Structure and rendering problems only appear on the page.",[35,671,672,675],{},[179,673,674],{},"No named reviewer."," Unassigned queues are where documentation goes to wait.",[35,677,678,681],{},[179,679,680],{},"Mechanical comments."," Every one is a missing build gate; treat it as a bug in the pipeline rather than as feedback.",[35,683,684,687],{},[179,685,686],{},"Rollback:"," every practice here is a convention, a template file or a rotation. Removing the pull request template restores the previous process instantly; nothing is coupled to the build.",[27,689,691],{"id":690},"conclusion","Conclusion",[14,693,694,695,25],{},"A docs-as-code process succeeds when it is small enough to sustain: one page per pull request, a preview link that arrives before the reviewer loses interest, two short passes with distinct purposes, and every mechanical check pushed into the build. Watch time-to-merge and abandonment rather than comment counts — those are the numbers that tell you whether the workflow is helping readers or just producing process. The wider setup is in ",[21,696,24],{"href":23},[27,698,700],{"id":699},"faq","FAQ",[702,703,705],"h3",{"id":704},"how-large-should-a-documentation-pull-request-be","How large should a documentation pull request be?",[14,707,708],{},"One page, or one coherent change across a few pages. A pull request that rewrites a section and renames six files is effectively unreviewable, and the review will either be rubber-stamped or sit for a week. If a change is genuinely large, split it into a structural change and a content change.",[702,710,712],{"id":711},"who-should-review-documentation-changes","Who should review documentation changes?",[14,714,715],{},"Someone who can verify the content is true, and someone who can verify it is clear. On a small team that is one person doing two passes rather than one, because reading for accuracy and reading for clarity use different attention.",[702,717,719],{"id":718},"do-writers-need-to-run-the-site-locally","Do writers need to run the site locally?",[14,721,722],{},"No, if previews are fast. A preview URL on every pull request means the rendered page is always available without a local toolchain, which is what lets occasional contributors participate at all.",[702,724,726],{"id":725},"what-belongs-in-a-review-checklist-versus-a-build-check","What belongs in a review checklist versus a build check?",[14,728,729],{},"Anything deterministic belongs in the build: links, front matter, spelling, terminology, image sizes. The checklist should only contain judgement calls, which in practice means accuracy, structure and whether the page answers the question its title asks.",[702,731,733],{"id":732},"how-do-we-handle-disagreements-about-wording","How do we handle disagreements about wording?",[14,735,736],{},"Write the style decision down once, in a style guide the linter can partially enforce, and refer to it instead of re-litigating. Wording debates in pull requests are usually a symptom of an undocumented convention rather than of a real disagreement.",[27,738,740],{"id":739},"related","Related",[32,742,743,752,759,766,773],{},[35,744,745,748,749,751],{},[179,746,747],{},"Parent:"," ",[21,750,24],{"href":23}," — entry points, gates and scheduling.",[35,753,754,758],{},[21,755,757],{"href":756},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fwiring-a-headless-cms-to-a-static-build\u002F","Wiring a Headless CMS to a Static Build"," — the editorial workflow that produces these pull requests.",[35,760,761,765],{},[21,762,764],{"href":763},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002F","Preview Environments for Pull Requests"," — the preview this workflow depends on.",[35,767,768,772],{},[21,769,771],{"href":770},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fsetting-up-deploy-previews-on-netlify-for-every-pull-request\u002F","Setting Up Deploy Previews on Netlify for Every Pull Request"," — host-specific wiring.",[35,774,775,777],{},[21,776,474],{"href":473}," — for the structural pull requests.",[779,780,781],"style",{},"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":192,"searchDepth":265,"depth":265,"links":783},[784,785,786,787,788,789,790,791,792,793,794,801],{"id":29,"depth":265,"text":30},{"id":46,"depth":265,"text":47},{"id":198,"depth":265,"text":199},{"id":232,"depth":265,"text":233},{"id":424,"depth":265,"text":425},{"id":449,"depth":265,"text":450},{"id":478,"depth":265,"text":479},{"id":491,"depth":265,"text":492},{"id":648,"depth":265,"text":649},{"id":690,"depth":265,"text":691},{"id":699,"depth":265,"text":700,"children":795},[796,797,798,799,800],{"id":704,"depth":271,"text":705},{"id":711,"depth":271,"text":712},{"id":718,"depth":271,"text":719},{"id":725,"depth":271,"text":726},{"id":732,"depth":271,"text":733},{"id":739,"depth":265,"text":740},[803,806,809,810],{"name":804,"item":805},"Home","\u002F",{"name":807,"item":808},"Production-Ready Deployment & CI\u002FCD Workflows","\u002Fproduction-ready-deployment-cicd-workflows\u002F",{"name":24,"item":23},{"name":5,"item":811},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers\u002F","2026-08-01","Branch naming, small pull requests, preview-first review and a two-pass checklist — a docs-as-code process that non-engineers can follow and reviewers can sustain.","md",[816,817,818,819,822],{"q":705,"a":708},{"q":712,"a":715},{"q":719,"a":722},{"q":726,"a":820},{"Anything deterministic belongs in the build":821},"links, front matter, spelling, terminology, image sizes. The checklist should only contain judgement calls, which in practice means accuracy, structure and whether the page answers the question its title asks.",{"q":733,"a":736},{},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers",{"title":5,"description":813},"production-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers\u002Findex","article","FVQ-rV9ZLwrUbv8ZianGEwbwkWKDC86SNZHW3kYmpOw",[830,833,836,839,842,845,848,851,854,857,860,863,866,869,871,874,877,880,883,886,889,892,895,898,901,904,907,910,913,916,919,922,925,928,931,934,937,940,943,946,949,952,955,958,961,964,967,970,973,976,979,982,985,988,991,994,997,1000,1003,1004,1006,1009,1011,1014,1017,1020,1023,1026,1029,1032,1035,1038,1041,1044,1047,1050,1053,1056,1059,1061,1064,1067,1070],{"path":831,"title":832},"\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":834,"title":835},"\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":837,"title":838},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":840,"title":841},"\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":843,"title":844},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":846,"title":847},"\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":849,"title":850},"\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":852,"title":853},"\u002Fchoosing-the-right-static-site-generator-for-production","Choosing the Right Static Site Generator for Production",{"path":855,"title":856},"\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":858,"title":859},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":861,"title":862},"\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":864,"title":865},"\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":867,"title":868},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":870,"title":474},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration",{"path":872,"title":873},"\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":875,"title":876},"\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":878,"title":879},"\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":881,"title":882},"\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":884,"title":885},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":887,"title":888},"\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":890,"title":891},"\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":893,"title":894},"\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":896,"title":897},"\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":899,"title":900},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":902,"title":903},"\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":905,"title":906},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams","SSG Selection Checklist for Engineering Teams",{"path":908,"title":909},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":911,"title":912},"\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":914,"title":915},"\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":917,"title":918},"\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":920,"title":921},"\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":923,"title":924},"\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":926,"title":927},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":929,"title":930},"\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":932,"title":933},"\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":935,"title":936},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":938,"title":939},"\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":941,"title":942},"\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":944,"title":945},"\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":947,"title":948},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":950,"title":951},"\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":953,"title":954},"\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":956,"title":957},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":959,"title":960},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":962,"title":963},"\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":965,"title":966},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":968,"title":969},"\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":971,"title":972},"\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":974,"title":975},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":977,"title":978},"\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":980,"title":981},"\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":983,"title":984},"\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":986,"title":987},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":989,"title":990},"\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":992,"title":993},"\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":995,"title":996},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":998,"title":999},"\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":1001,"title":1002},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":824,"title":5},{"path":1005,"title":24},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams",{"path":1007,"title":1008},"\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":1010,"title":757},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fwiring-a-headless-cms-to-a-static-build",{"path":1012,"title":1013},"\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":1015,"title":1016},"\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":1018,"title":1019},"\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":1021,"title":1022},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1024,"title":1025},"\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":1027,"title":1028},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":1030,"title":1031},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":1033,"title":1034},"\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":1036,"title":1037},"\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":1039,"title":1040},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":1042,"title":1043},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":1045,"title":1046},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":1048,"title":1049},"\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":1051,"title":1052},"\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":1054,"title":1055},"\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":1057,"title":1058},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":1060,"title":764},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests",{"path":1062,"title":1063},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":1065,"title":1066},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":1068,"title":1069},"\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":1071,"title":1072},"\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",1785611671058]