[{"data":1,"prerenderedAt":2399},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo":3,"all-docs-nav":2159},{"id":4,"title":5,"body":6,"breadcrumb":2130,"dateModified":2139,"datePublished":2139,"description":2140,"extension":554,"faq":2141,"meta":2153,"navigation":343,"path":2154,"seo":2155,"slug":12,"stem":2156,"type":2157,"__hash__":2158},"content\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo\u002Findex.md","Migrating a Docs Site From Jekyll to Hugo",{"type":7,"value":8,"toc":2111},"minimark",[9,13,17,26,31,52,56,71,236,250,254,1221,1241,1245,1248,1372,1378,1381,1496,1507,1511,1525,1552,1577,1584,1588,1591,1706,1726,1738,1742,1753,1849,1937,1944,1948,1999,2003,2008,2012,2017,2028,2032,2041,2045,2054,2058,2061,2065,2068,2072,2107],[10,11,5],"h1",{"id":12},"migrating-a-docs-site-from-jekyll-to-hugo",[14,15,16],"p",{},"Jekyll is where a great many documentation sites started, and it stops being comfortable in a predictable way: builds that take minutes, a plugin list that only one person understands, and a hosting default that limits what you can run. Hugo is the usual destination because the content model is close enough that most Markdown converts mechanically, and the build-speed difference on a large corpus is not subtle.",[14,18,19,20,25],{},"This guide is the concrete path: mapping collections to sections, converting Liquid to Go templates and shortcodes, reproducing permalinks exactly, and the measured before and after on a 1,200-page site. It is one route through the general process in ",[21,22,24],"a",{"href":23},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002F","Migrating Between Static Site Generators",".",[27,28,30],"h2",{"id":29},"prerequisites","Prerequisites",[32,33,34,43,46,49],"ul",{},[35,36,37,38,42],"li",{},"Hugo extended 0.128 or newer (",[39,40,41],"code",{},"hugo version"," — the extended build is required for SCSS and image processing).",[35,44,45],{},"The Jekyll site building locally, so you can diff old output against new.",[35,47,48],{},"The production URL list from your sitemap, saved before you start.",[35,50,51],{},"Node available for the conversion script, or Ruby if you prefer to write it against Jekyll's own front-matter parser.",[27,53,55],{"id":54},"map-the-content-model-first","Map the Content Model First",[14,57,58,59,62,63,66,67,70],{},"Jekyll's collections and Hugo's sections describe the same idea with different mechanics. Jekyll declares collections in ",[39,60,61],{},"_config.yml"," and stores them in underscore-prefixed directories; Hugo infers a section from any directory under ",[39,64,65],{},"content\u002F",", and a directory containing an ",[39,68,69],{},"_index.md"," becomes a list page.",[72,73,74,232],"figure",{},[75,76,83,84,83,88,83,92,83,99,83,218],"svg",{"viewBox":77,"role":78,"ariaLabelledBy":79,"xmlns":82},"0 0 760 320","img",[80,81],"jh-model-title","jh-model-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[85,86,87],"title",{"id":80},"Jekyll collections mapped to Hugo sections",[89,90,91],"desc",{"id":81},"A mapping diagram. Jekyll's underscore posts directory maps to Hugo's content slash posts directory. Jekyll's underscore docs collection maps to content slash docs with an underscore index file for the list page. Jekyll's underscore includes maps to Hugo layouts partials, and underscore layouts maps to Hugo layouts default.",[93,94],"rect",{"x":95,"y":95,"width":96,"height":97,"fill":98},"0","760","320","#ffffff",[100,101,103,104,103,112,103,119,103,124,103,134,103,139,103,144,103,147,103,150,103,154,103,156,103,160,103,166,103,169,103,173,103,175,103,179,103,182,103,185,103,189,103,191,103,194,103,213,83],"g",{"style":102},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[105,106,111],"text",{"x":107,"y":108,"fill":109,"style":110},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","Same concepts, different directory contract",[105,113,118],{"x":114,"y":115,"fill":116,"style":117},"150","58","#d83b41","font-size:13px;font-weight:700;text-anchor:middle","Jekyll",[105,120,123],{"x":121,"y":115,"fill":122,"style":117},"610","#5a8a16","Hugo",[93,125],{"x":126,"y":127,"width":128,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"40","72","220","42","8","#ff595e","0.12","stroke-width:1.5px",[105,135,138],{"x":114,"y":136,"fill":109,"style":137},"98","font-size:12px;text-anchor:middle","_posts\u002F2024-01-01-x.md",[93,140],{"x":141,"y":127,"width":128,"height":129,"rx":130,"fill":142,"opacity":143,"stroke":122,"style":133},"500","#8ac926","0.16",[105,145,146],{"x":121,"y":136,"fill":109,"style":137},"content\u002Fposts\u002Fx.md",[93,148],{"x":126,"y":149,"width":128,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"128",[105,151,153],{"x":114,"y":152,"fill":109,"style":137},"154","_docs\u002F collection",[93,155],{"x":141,"y":149,"width":128,"height":129,"rx":130,"fill":142,"opacity":143,"stroke":122,"style":133},[105,157,159],{"x":121,"y":158,"fill":109,"style":137},"148","content\u002Fdocs\u002F + _index.md",[105,161,165],{"x":121,"y":162,"fill":163,"style":164},"164","#556071","font-size:11px;text-anchor:middle","the list page",[93,167],{"x":126,"y":168,"width":128,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"184",[105,170,172],{"x":114,"y":171,"fill":109,"style":137},"210","_includes\u002Fnote.html",[93,174],{"x":141,"y":168,"width":128,"height":129,"rx":130,"fill":142,"opacity":143,"stroke":122,"style":133},[105,176,178],{"x":121,"y":177,"fill":109,"style":137},"204","layouts\u002Fpartials\u002Fnote.html",[105,180,181],{"x":121,"y":128,"fill":163,"style":164},"or shortcodes\u002F if used in content",[93,183],{"x":126,"y":184,"width":128,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"240",[105,186,188],{"x":114,"y":187,"fill":109,"style":137},"266","_layouts\u002Fdefault.html",[93,190],{"x":141,"y":184,"width":128,"height":129,"rx":130,"fill":142,"opacity":143,"stroke":122,"style":133},[105,192,193],{"x":121,"y":187,"fill":109,"style":137},"layouts\u002F_default\u002Fbaseof.html",[100,195,198,199,198,204,198,207,198,210,103],{"stroke":163,"fill":196,"style":197},"none","stroke-width:2px","\n      ",[200,201],"path",{"d":202,"style":203},"M262 93 L498 93","marker-end:url(#jh-arrow)",[200,205],{"d":206,"style":203},"M262 149 L498 149",[200,208],{"d":209,"style":203},"M262 205 L498 205",[200,211],{"d":212,"style":203},"M262 261 L498 261",[105,214,217],{"x":126,"y":215,"fill":163,"style":216},"306","font-size:11px","The date prefix moves out of the filename and into front matter — Hugo derives URLs from config, not from names",[219,220,103,221,83],"defs",{},[222,223,198,229,103],"marker",{"id":224,"viewBox":225,"refX":130,"refY":226,"markerWidth":227,"markerHeight":227,"orient":228},"jh-arrow","0 0 10 10","5","7","auto-start-reverse",[200,230],{"d":231,"fill":163},"M0 0 L10 5 L0 10 z",[233,234,235],"figcaption",{},"Most of the migration is this table applied file by file. The interesting decisions are what happens to page order and to anything that was implicit in a Jekyll filename.",[14,237,238,239,242,243,246,247,249],{},"The important behavioural difference is where ordering comes from. Jekyll orders posts by the date in the filename; Hugo orders by a ",[39,240,241],{},"date"," or ",[39,244,245],{},"weight"," field. Docs sites almost always want ",[39,248,245],{},", since chapter order is not chronological — so decide the ordering field during conversion and write it into the front matter rather than discovering it later.",[27,251,253],{"id":252},"the-conversion-script","The Conversion Script",[255,256,261],"pre",{"className":257,"code":258,"language":259,"meta":260,"style":260},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F scripts\u002Fjekyll-to-hugo.mjs — run into a clean directory, never hand-edit the output\nimport { readFile, writeFile, mkdir, rm } from 'node:fs\u002Fpromises';\nimport { globSync } from 'node:fs';\nimport path from 'node:path';\nimport matter from 'gray-matter';\n\nawait rm('content', { recursive: true, force: true });\nlet converted = 0, unhandled = [];\n\nfor (const src of globSync('_docs\u002F**\u002F*.md')) {\n  const { data, content } = matter(await readFile(src, 'utf8'));\n  const base = path.basename(src).replace(\u002F^(\\d{4}-\\d{2}-\\d{2})-\u002F, '').replace(\u002F\\.md$\u002F, '');\n\n  const body = content\n    .replace(\u002F\\{%\\s*highlight\\s+(\\w+)[^%]*%\\}\u002Fg, '```$1')\n    .replace(\u002F\\{%\\s*endhighlight\\s*%\\}\u002Fg, '```')\n    .replace(\u002F\\{\\{\\s*site\\.baseurl\\s*\\}\\}\u002Fg, '')\n    .replace(\u002F\\{%\\s*include\\s+note\\.html\\s+content=[\"'](.+?)[\"']\\s*%\\}\u002Fg, '{{\u003C note >}}$1{{\u003C \u002Fnote >}}')\n    .replace(\u002F\\{%\\s*link\\s+(\\S+)\\s*%\\}\u002Fg, (_, p) => '\u002F' + p.replace(\u002F\\.md$\u002F, '\u002F'));\n\n  for (const [tag] of body.matchAll(\u002F\\{[%{][^}]*[%}]\\}\u002Fg)) unhandled.push(`${src}: ${tag}`);\n\n  await mkdir('content\u002Fdocs', { recursive: true });\n  await writeFile(path.join('content\u002Fdocs', `${base}.md`), matter.stringify(body, {\n    title: data.title,\n    description: data.description ?? data.excerpt,\n    weight: data.nav_order ?? data.weight ?? 100,\n    date: data.date,\n    draft: data.published === false,\n    aliases: data.permalink ? [data.permalink] : undefined,\n  }));\n  converted++;\n}\n\nconsole.log(`converted ${converted} file(s)`);\nif (unhandled.length) console.log('unhandled template tags:\\n' + unhandled.join('\\n'));\n","javascript","",[39,262,263,272,293,308,323,338,345,376,399,404,433,475,567,572,585,654,695,738,811,905,910,987,992,1012,1049,1055,1067,1086,1092,1106,1126,1132,1143,1149,1154,1176],{"__ignoreMap":260},[264,265,268],"span",{"class":266,"line":267},"line",1,[264,269,271],{"class":270},"sJ8bj","\u002F\u002F scripts\u002Fjekyll-to-hugo.mjs — run into a clean directory, never hand-edit the output\n",[264,273,275,279,283,286,290],{"class":266,"line":274},2,[264,276,278],{"class":277},"szBVR","import",[264,280,282],{"class":281},"sVt8B"," { readFile, writeFile, mkdir, rm } ",[264,284,285],{"class":277},"from",[264,287,289],{"class":288},"sZZnC"," 'node:fs\u002Fpromises'",[264,291,292],{"class":281},";\n",[264,294,296,298,301,303,306],{"class":266,"line":295},3,[264,297,278],{"class":277},[264,299,300],{"class":281}," { globSync } ",[264,302,285],{"class":277},[264,304,305],{"class":288}," 'node:fs'",[264,307,292],{"class":281},[264,309,311,313,316,318,321],{"class":266,"line":310},4,[264,312,278],{"class":277},[264,314,315],{"class":281}," path ",[264,317,285],{"class":277},[264,319,320],{"class":288}," 'node:path'",[264,322,292],{"class":281},[264,324,326,328,331,333,336],{"class":266,"line":325},5,[264,327,278],{"class":277},[264,329,330],{"class":281}," matter ",[264,332,285],{"class":277},[264,334,335],{"class":288}," 'gray-matter'",[264,337,292],{"class":281},[264,339,341],{"class":266,"line":340},6,[264,342,344],{"emptyLinePlaceholder":343},true,"\n",[264,346,348,351,355,358,361,364,368,371,373],{"class":266,"line":347},7,[264,349,350],{"class":277},"await",[264,352,354],{"class":353},"sScJk"," rm",[264,356,357],{"class":281},"(",[264,359,360],{"class":288},"'content'",[264,362,363],{"class":281},", { recursive: ",[264,365,367],{"class":366},"sj4cs","true",[264,369,370],{"class":281},", force: ",[264,372,367],{"class":366},[264,374,375],{"class":281}," });\n",[264,377,379,382,385,388,391,394,396],{"class":266,"line":378},8,[264,380,381],{"class":277},"let",[264,383,384],{"class":281}," converted ",[264,386,387],{"class":277},"=",[264,389,390],{"class":366}," 0",[264,392,393],{"class":281},", unhandled ",[264,395,387],{"class":277},[264,397,398],{"class":281}," [];\n",[264,400,402],{"class":266,"line":401},9,[264,403,344],{"emptyLinePlaceholder":343},[264,405,407,410,413,416,419,422,425,427,430],{"class":266,"line":406},10,[264,408,409],{"class":277},"for",[264,411,412],{"class":281}," (",[264,414,415],{"class":277},"const",[264,417,418],{"class":366}," src",[264,420,421],{"class":277}," of",[264,423,424],{"class":353}," globSync",[264,426,357],{"class":281},[264,428,429],{"class":288},"'_docs\u002F**\u002F*.md'",[264,431,432],{"class":281},")) {\n",[264,434,436,439,442,445,448,451,454,456,459,461,463,466,469,472],{"class":266,"line":435},11,[264,437,438],{"class":277},"  const",[264,440,441],{"class":281}," { ",[264,443,444],{"class":366},"data",[264,446,447],{"class":281},", ",[264,449,450],{"class":366},"content",[264,452,453],{"class":281}," } ",[264,455,387],{"class":277},[264,457,458],{"class":353}," matter",[264,460,357],{"class":281},[264,462,350],{"class":277},[264,464,465],{"class":353}," readFile",[264,467,468],{"class":281},"(src, ",[264,470,471],{"class":288},"'utf8'",[264,473,474],{"class":281},"));\n",[264,476,478,480,483,486,489,492,495,498,500,503,506,509,512,515,518,520,523,525,527,529,532,534,536,539,542,544,546,548,552,555,558,560,562,564],{"class":266,"line":477},12,[264,479,438],{"class":277},[264,481,482],{"class":366}," base",[264,484,485],{"class":277}," =",[264,487,488],{"class":281}," path.",[264,490,491],{"class":353},"basename",[264,493,494],{"class":281},"(src).",[264,496,497],{"class":353},"replace",[264,499,357],{"class":281},[264,501,502],{"class":288},"\u002F",[264,504,505],{"class":277},"^",[264,507,357],{"class":508},"sA_wV",[264,510,511],{"class":366},"\\d",[264,513,514],{"class":277},"{4}",[264,516,517],{"class":508},"-",[264,519,511],{"class":366},[264,521,522],{"class":277},"{2}",[264,524,517],{"class":508},[264,526,511],{"class":366},[264,528,522],{"class":277},[264,530,531],{"class":508},")-",[264,533,502],{"class":288},[264,535,447],{"class":281},[264,537,538],{"class":288},"''",[264,540,541],{"class":281},").",[264,543,497],{"class":353},[264,545,357],{"class":281},[264,547,502],{"class":288},[264,549,551],{"class":550},"snhLl","\\.",[264,553,554],{"class":508},"md",[264,556,557],{"class":277},"$",[264,559,502],{"class":288},[264,561,447],{"class":281},[264,563,538],{"class":288},[264,565,566],{"class":281},");\n",[264,568,570],{"class":266,"line":569},13,[264,571,344],{"emptyLinePlaceholder":343},[264,573,575,577,580,582],{"class":266,"line":574},14,[264,576,438],{"class":277},[264,578,579],{"class":366}," body",[264,581,485],{"class":277},[264,583,584],{"class":281}," content\n",[264,586,588,591,593,595,597,600,603,606,609,612,614,617,619,622,624,627,630,632,635,637,639,642,644,646,648,651],{"class":266,"line":587},15,[264,589,590],{"class":281},"    .",[264,592,497],{"class":353},[264,594,357],{"class":281},[264,596,502],{"class":288},[264,598,599],{"class":550},"\\{",[264,601,602],{"class":508},"%",[264,604,605],{"class":366},"\\s",[264,607,608],{"class":277},"*",[264,610,611],{"class":508},"highlight",[264,613,605],{"class":366},[264,615,616],{"class":277},"+",[264,618,357],{"class":508},[264,620,621],{"class":366},"\\w",[264,623,616],{"class":277},[264,625,626],{"class":508},")",[264,628,629],{"class":366},"[",[264,631,505],{"class":277},[264,633,634],{"class":366},"%]",[264,636,608],{"class":277},[264,638,602],{"class":508},[264,640,641],{"class":550},"\\}",[264,643,502],{"class":288},[264,645,100],{"class":277},[264,647,447],{"class":281},[264,649,650],{"class":288},"'```$1'",[264,652,653],{"class":281},")\n",[264,655,657,659,661,663,665,667,669,671,673,676,678,680,682,684,686,688,690,693],{"class":266,"line":656},16,[264,658,590],{"class":281},[264,660,497],{"class":353},[264,662,357],{"class":281},[264,664,502],{"class":288},[264,666,599],{"class":550},[264,668,602],{"class":508},[264,670,605],{"class":366},[264,672,608],{"class":277},[264,674,675],{"class":508},"endhighlight",[264,677,605],{"class":366},[264,679,608],{"class":277},[264,681,602],{"class":508},[264,683,641],{"class":550},[264,685,502],{"class":288},[264,687,100],{"class":277},[264,689,447],{"class":281},[264,691,692],{"class":288},"'```'",[264,694,653],{"class":281},[264,696,698,700,702,704,706,709,711,713,716,718,721,723,725,728,730,732,734,736],{"class":266,"line":697},17,[264,699,590],{"class":281},[264,701,497],{"class":353},[264,703,357],{"class":281},[264,705,502],{"class":288},[264,707,708],{"class":550},"\\{\\{",[264,710,605],{"class":366},[264,712,608],{"class":277},[264,714,715],{"class":508},"site",[264,717,551],{"class":550},[264,719,720],{"class":508},"baseurl",[264,722,605],{"class":366},[264,724,608],{"class":277},[264,726,727],{"class":550},"\\}\\}",[264,729,502],{"class":288},[264,731,100],{"class":277},[264,733,447],{"class":281},[264,735,538],{"class":288},[264,737,653],{"class":281},[264,739,741,743,745,747,749,751,753,755,757,760,762,764,767,769,772,774,776,779,782,784,786,789,791,794,796,798,800,802,804,806,809],{"class":266,"line":740},18,[264,742,590],{"class":281},[264,744,497],{"class":353},[264,746,357],{"class":281},[264,748,502],{"class":288},[264,750,599],{"class":550},[264,752,602],{"class":508},[264,754,605],{"class":366},[264,756,608],{"class":277},[264,758,759],{"class":508},"include",[264,761,605],{"class":366},[264,763,616],{"class":277},[264,765,766],{"class":508},"note",[264,768,551],{"class":550},[264,770,771],{"class":508},"html",[264,773,605],{"class":366},[264,775,616],{"class":277},[264,777,778],{"class":508},"content=",[264,780,781],{"class":366},"[\"']",[264,783,357],{"class":508},[264,785,25],{"class":366},[264,787,788],{"class":277},"+?",[264,790,626],{"class":508},[264,792,793],{"class":366},"[\"']\\s",[264,795,608],{"class":277},[264,797,602],{"class":508},[264,799,641],{"class":550},[264,801,502],{"class":288},[264,803,100],{"class":277},[264,805,447],{"class":281},[264,807,808],{"class":288},"'{{\u003C note >}}$1{{\u003C \u002Fnote >}}'",[264,810,653],{"class":281},[264,812,814,816,818,820,822,824,826,828,830,833,835,837,839,842,844,846,848,850,852,854,856,858,861,865,867,869,872,875,878,881,884,886,888,890,892,894,896,898,900,903],{"class":266,"line":813},19,[264,815,590],{"class":281},[264,817,497],{"class":353},[264,819,357],{"class":281},[264,821,502],{"class":288},[264,823,599],{"class":550},[264,825,602],{"class":508},[264,827,605],{"class":366},[264,829,608],{"class":277},[264,831,832],{"class":508},"link",[264,834,605],{"class":366},[264,836,616],{"class":277},[264,838,357],{"class":508},[264,840,841],{"class":366},"\\S",[264,843,616],{"class":277},[264,845,626],{"class":508},[264,847,605],{"class":366},[264,849,608],{"class":277},[264,851,602],{"class":508},[264,853,641],{"class":550},[264,855,502],{"class":288},[264,857,100],{"class":277},[264,859,860],{"class":281},", (",[264,862,864],{"class":863},"s4XuR","_",[264,866,447],{"class":281},[264,868,14],{"class":863},[264,870,871],{"class":281},") ",[264,873,874],{"class":277},"=>",[264,876,877],{"class":288}," '\u002F'",[264,879,880],{"class":277}," +",[264,882,883],{"class":281}," p.",[264,885,497],{"class":353},[264,887,357],{"class":281},[264,889,502],{"class":288},[264,891,551],{"class":550},[264,893,554],{"class":508},[264,895,557],{"class":277},[264,897,502],{"class":288},[264,899,447],{"class":281},[264,901,902],{"class":288},"'\u002F'",[264,904,474],{"class":281},[264,906,908],{"class":266,"line":907},20,[264,909,344],{"emptyLinePlaceholder":343},[264,911,913,916,918,920,923,926,929,932,935,938,940,942,944,947,949,952,954,957,959,961,963,966,969,971,974,977,980,982,985],{"class":266,"line":912},21,[264,914,915],{"class":277},"  for",[264,917,412],{"class":281},[264,919,415],{"class":277},[264,921,922],{"class":281}," [",[264,924,925],{"class":366},"tag",[264,927,928],{"class":281},"] ",[264,930,931],{"class":277},"of",[264,933,934],{"class":281}," body.",[264,936,937],{"class":353},"matchAll",[264,939,357],{"class":281},[264,941,502],{"class":288},[264,943,599],{"class":550},[264,945,946],{"class":366},"[%{][",[264,948,505],{"class":277},[264,950,951],{"class":366},"}]",[264,953,608],{"class":277},[264,955,956],{"class":366},"[%}]",[264,958,641],{"class":550},[264,960,502],{"class":288},[264,962,100],{"class":277},[264,964,965],{"class":281},")) unhandled.",[264,967,968],{"class":353},"push",[264,970,357],{"class":281},[264,972,973],{"class":288},"`${",[264,975,976],{"class":281},"src",[264,978,979],{"class":288},"}: ${",[264,981,925],{"class":281},[264,983,984],{"class":288},"}`",[264,986,566],{"class":281},[264,988,990],{"class":266,"line":989},22,[264,991,344],{"emptyLinePlaceholder":343},[264,993,995,998,1001,1003,1006,1008,1010],{"class":266,"line":994},23,[264,996,997],{"class":277},"  await",[264,999,1000],{"class":353}," mkdir",[264,1002,357],{"class":281},[264,1004,1005],{"class":288},"'content\u002Fdocs'",[264,1007,363],{"class":281},[264,1009,367],{"class":366},[264,1011,375],{"class":281},[264,1013,1015,1017,1020,1023,1026,1028,1030,1032,1034,1037,1040,1043,1046],{"class":266,"line":1014},24,[264,1016,997],{"class":277},[264,1018,1019],{"class":353}," writeFile",[264,1021,1022],{"class":281},"(path.",[264,1024,1025],{"class":353},"join",[264,1027,357],{"class":281},[264,1029,1005],{"class":288},[264,1031,447],{"class":281},[264,1033,973],{"class":288},[264,1035,1036],{"class":281},"base",[264,1038,1039],{"class":288},"}.md`",[264,1041,1042],{"class":281},"), matter.",[264,1044,1045],{"class":353},"stringify",[264,1047,1048],{"class":281},"(body, {\n",[264,1050,1052],{"class":266,"line":1051},25,[264,1053,1054],{"class":281},"    title: data.title,\n",[264,1056,1058,1061,1064],{"class":266,"line":1057},26,[264,1059,1060],{"class":281},"    description: data.description ",[264,1062,1063],{"class":277},"??",[264,1065,1066],{"class":281}," data.excerpt,\n",[264,1068,1070,1073,1075,1078,1080,1083],{"class":266,"line":1069},27,[264,1071,1072],{"class":281},"    weight: data.nav_order ",[264,1074,1063],{"class":277},[264,1076,1077],{"class":281}," data.weight ",[264,1079,1063],{"class":277},[264,1081,1082],{"class":366}," 100",[264,1084,1085],{"class":281},",\n",[264,1087,1089],{"class":266,"line":1088},28,[264,1090,1091],{"class":281},"    date: data.date,\n",[264,1093,1095,1098,1101,1104],{"class":266,"line":1094},29,[264,1096,1097],{"class":281},"    draft: data.published ",[264,1099,1100],{"class":277},"===",[264,1102,1103],{"class":366}," false",[264,1105,1085],{"class":281},[264,1107,1109,1112,1115,1118,1121,1124],{"class":266,"line":1108},30,[264,1110,1111],{"class":281},"    aliases: data.permalink ",[264,1113,1114],{"class":277},"?",[264,1116,1117],{"class":281}," [data.permalink] ",[264,1119,1120],{"class":277},":",[264,1122,1123],{"class":366}," undefined",[264,1125,1085],{"class":281},[264,1127,1129],{"class":266,"line":1128},31,[264,1130,1131],{"class":281},"  }));\n",[264,1133,1135,1138,1141],{"class":266,"line":1134},32,[264,1136,1137],{"class":281},"  converted",[264,1139,1140],{"class":277},"++",[264,1142,292],{"class":281},[264,1144,1146],{"class":266,"line":1145},33,[264,1147,1148],{"class":281},"}\n",[264,1150,1152],{"class":266,"line":1151},34,[264,1153,344],{"emptyLinePlaceholder":343},[264,1155,1157,1160,1163,1165,1168,1171,1174],{"class":266,"line":1156},35,[264,1158,1159],{"class":281},"console.",[264,1161,1162],{"class":353},"log",[264,1164,357],{"class":281},[264,1166,1167],{"class":288},"`converted ${",[264,1169,1170],{"class":281},"converted",[264,1172,1173],{"class":288},"} file(s)`",[264,1175,566],{"class":281},[264,1177,1179,1182,1185,1188,1191,1193,1195,1198,1201,1204,1206,1209,1211,1213,1215,1217,1219],{"class":266,"line":1178},36,[264,1180,1181],{"class":277},"if",[264,1183,1184],{"class":281}," (unhandled.",[264,1186,1187],{"class":366},"length",[264,1189,1190],{"class":281},") console.",[264,1192,1162],{"class":353},[264,1194,357],{"class":281},[264,1196,1197],{"class":288},"'unhandled template tags:",[264,1199,1200],{"class":366},"\\n",[264,1202,1203],{"class":288},"'",[264,1205,880],{"class":277},[264,1207,1208],{"class":281}," unhandled.",[264,1210,1025],{"class":353},[264,1212,357],{"class":281},[264,1214,1203],{"class":288},[264,1216,1200],{"class":366},[264,1218,1203],{"class":288},[264,1220,474],{"class":281},[14,1222,1223,1224,1227,1228,1232,1233,1236,1237,1240],{},"The ",[39,1225,1226],{},"unhandled"," report is the progress bar for the whole migration — every line is a Liquid construct that still needs a rule or a manual decision in the ",[1229,1230,1231],"em",{},"source",". Note the ",[39,1234,1235],{},"aliases"," entry: Hugo emits a redirect stub for each alias, which is the cheapest way to honour a Jekyll ",[39,1238,1239],{},"permalink"," that does not match the new structure.",[27,1242,1244],{"id":1243},"reproduce-the-urls-exactly","Reproduce the URLs Exactly",[14,1246,1247],{},"Hugo derives URLs from configuration, so a Jekyll permalink pattern becomes a permalink setting per section:",[255,1249,1253],{"className":1250,"code":1251,"language":1252,"meta":260,"style":260},"language-yaml shiki shiki-themes github-light github-dark","# hugo.yaml\nbaseURL: https:\u002F\u002Fexample.com\u002F\nlanguageCode: en-us\npermalinks:\n  posts: \u002Fblog\u002F:year\u002F:month\u002F:slug\u002F    # matches Jekyll's \u002Fblog\u002F:categories\u002F:year\u002F:month\u002F:day\u002F:title\u002F\n  docs: \u002Fdocs\u002F:slug\u002F\nmarkup:\n  goldmark:\n    renderer:\n      unsafe: true                    # allow raw HTML that Jekyll permitted\n  highlight:\n    noClasses: false\n    lineNos: false\n","yaml",[39,1254,1255,1260,1272,1282,1290,1303,1313,1320,1327,1334,1346,1353,1363],{"__ignoreMap":260},[264,1256,1257],{"class":266,"line":267},[264,1258,1259],{"class":270},"# hugo.yaml\n",[264,1261,1262,1266,1269],{"class":266,"line":274},[264,1263,1265],{"class":1264},"s9eBZ","baseURL",[264,1267,1268],{"class":281},": ",[264,1270,1271],{"class":288},"https:\u002F\u002Fexample.com\u002F\n",[264,1273,1274,1277,1279],{"class":266,"line":295},[264,1275,1276],{"class":1264},"languageCode",[264,1278,1268],{"class":281},[264,1280,1281],{"class":288},"en-us\n",[264,1283,1284,1287],{"class":266,"line":310},[264,1285,1286],{"class":1264},"permalinks",[264,1288,1289],{"class":281},":\n",[264,1291,1292,1295,1297,1300],{"class":266,"line":325},[264,1293,1294],{"class":1264},"  posts",[264,1296,1268],{"class":281},[264,1298,1299],{"class":288},"\u002Fblog\u002F:year\u002F:month\u002F:slug\u002F",[264,1301,1302],{"class":270},"    # matches Jekyll's \u002Fblog\u002F:categories\u002F:year\u002F:month\u002F:day\u002F:title\u002F\n",[264,1304,1305,1308,1310],{"class":266,"line":340},[264,1306,1307],{"class":1264},"  docs",[264,1309,1268],{"class":281},[264,1311,1312],{"class":288},"\u002Fdocs\u002F:slug\u002F\n",[264,1314,1315,1318],{"class":266,"line":347},[264,1316,1317],{"class":1264},"markup",[264,1319,1289],{"class":281},[264,1321,1322,1325],{"class":266,"line":378},[264,1323,1324],{"class":1264},"  goldmark",[264,1326,1289],{"class":281},[264,1328,1329,1332],{"class":266,"line":401},[264,1330,1331],{"class":1264},"    renderer",[264,1333,1289],{"class":281},[264,1335,1336,1339,1341,1343],{"class":266,"line":406},[264,1337,1338],{"class":1264},"      unsafe",[264,1340,1268],{"class":281},[264,1342,367],{"class":366},[264,1344,1345],{"class":270},"                    # allow raw HTML that Jekyll permitted\n",[264,1347,1348,1351],{"class":266,"line":435},[264,1349,1350],{"class":1264},"  highlight",[264,1352,1289],{"class":281},[264,1354,1355,1358,1360],{"class":266,"line":477},[264,1356,1357],{"class":1264},"    noClasses",[264,1359,1268],{"class":281},[264,1361,1362],{"class":366},"false\n",[264,1364,1365,1368,1370],{"class":266,"line":569},[264,1366,1367],{"class":1264},"    lineNos",[264,1369,1268],{"class":281},[264,1371,1362],{"class":366},[14,1373,1374,1377],{},[39,1375,1376],{},"unsafe: true"," deserves a note: Jekyll's Kramdown passes raw HTML through by default, so any content with inline HTML silently renders empty in Hugo without it. It is the single most common \"the page is missing half its content\" cause after a Jekyll migration.",[14,1379,1380],{},"Then gate on parity in CI, comparing the built tree against the sitemap you saved:",[255,1382,1386],{"className":1383,"code":1384,"language":1385,"meta":260,"style":260},"language-bash shiki shiki-themes github-light github-dark","hugo --minify --gc\nfind public -name '*.html' | sed 's|public||; s|\u002Findex.html|\u002F|' | sort > urls-after.txt\ncomm -23 urls-before.txt urls-after.txt > missing.txt\n[ -s missing.txt ] && { echo \"MISSING URLS:\"; cat missing.txt; exit 1; }\necho \"URL parity: OK\"\n","bash",[39,1387,1388,1399,1433,1452,1489],{"__ignoreMap":260},[264,1389,1390,1393,1396],{"class":266,"line":267},[264,1391,1392],{"class":353},"hugo",[264,1394,1395],{"class":366}," --minify",[264,1397,1398],{"class":366}," --gc\n",[264,1400,1401,1404,1407,1410,1413,1416,1419,1422,1424,1427,1430],{"class":266,"line":274},[264,1402,1403],{"class":353},"find",[264,1405,1406],{"class":288}," public",[264,1408,1409],{"class":366}," -name",[264,1411,1412],{"class":288}," '*.html'",[264,1414,1415],{"class":277}," |",[264,1417,1418],{"class":353}," sed",[264,1420,1421],{"class":288}," 's|public||; s|\u002Findex.html|\u002F|'",[264,1423,1415],{"class":277},[264,1425,1426],{"class":353}," sort",[264,1428,1429],{"class":277}," >",[264,1431,1432],{"class":288}," urls-after.txt\n",[264,1434,1435,1438,1441,1444,1447,1449],{"class":266,"line":295},[264,1436,1437],{"class":353},"comm",[264,1439,1440],{"class":366}," -23",[264,1442,1443],{"class":288}," urls-before.txt",[264,1445,1446],{"class":288}," urls-after.txt",[264,1448,1429],{"class":277},[264,1450,1451],{"class":288}," missing.txt\n",[264,1453,1454,1457,1460,1463,1466,1469,1472,1475,1478,1480,1483,1486],{"class":266,"line":310},[264,1455,1456],{"class":281},"[ ",[264,1458,1459],{"class":277},"-s",[264,1461,1462],{"class":281}," missing.txt ] && { ",[264,1464,1465],{"class":366},"echo",[264,1467,1468],{"class":288}," \"MISSING URLS:\"",[264,1470,1471],{"class":281},"; ",[264,1473,1474],{"class":353},"cat",[264,1476,1477],{"class":288}," missing.txt",[264,1479,1471],{"class":281},[264,1481,1482],{"class":366},"exit",[264,1484,1485],{"class":366}," 1",[264,1487,1488],{"class":281},"; }\n",[264,1490,1491,1493],{"class":266,"line":325},[264,1492,1465],{"class":366},[264,1494,1495],{"class":288}," \"URL parity: OK\"\n",[14,1497,1498,1499,1502,1503,25],{},"Anything in ",[39,1500,1501],{},"missing.txt"," needs either a permalink rule or an alias — the mechanics of which are covered in ",[21,1504,1506],{"href":1505},"\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",[27,1508,1510],{"id":1509},"convert-includes-to-partials-or-shortcodes","Convert Includes to Partials or Shortcodes",[14,1512,1513,1514,1517,1518,1521,1522,1524],{},"Jekyll's ",[39,1515,1516],{},"{% include %}"," covers two different jobs that Hugo separates. An include used inside a ",[1229,1519,1520],{},"layout"," becomes a partial; an include used inside ",[1229,1523,450],{}," becomes a shortcode. Getting this wrong is why some converted pages render literal braces.",[255,1526,1530],{"className":1527,"code":1528,"language":1529,"meta":260,"style":260},"language-go-html-template shiki shiki-themes github-light github-dark","{{\u002F* layouts\u002Fshortcodes\u002Fnote.html — used in content as {{\u003C note >}}text{{\u003C \u002Fnote >}} *\u002F}}\n\u003Caside class=\"note\">\n  \u003Cstrong>Note:\u003C\u002Fstrong> {{ .Inner | markdownify }}\n\u003C\u002Faside>\n","go-html-template",[39,1531,1532,1537,1542,1547],{"__ignoreMap":260},[264,1533,1534],{"class":266,"line":267},[264,1535,1536],{},"{{\u002F* layouts\u002Fshortcodes\u002Fnote.html — used in content as {{\u003C note >}}text{{\u003C \u002Fnote >}} *\u002F}}\n",[264,1538,1539],{"class":266,"line":274},[264,1540,1541],{},"\u003Caside class=\"note\">\n",[264,1543,1544],{"class":266,"line":295},[264,1545,1546],{},"  \u003Cstrong>Note:\u003C\u002Fstrong> {{ .Inner | markdownify }}\n",[264,1548,1549],{"class":266,"line":310},[264,1550,1551],{},"\u003C\u002Faside>\n",[255,1553,1555],{"className":1527,"code":1554,"language":1529,"meta":260,"style":260},"{{\u002F* layouts\u002Fpartials\u002Ftoc.html — used in layouts as {{ partial \"toc.html\" . }} *\u002F}}\n{{ if gt (len .TableOfContents) 40 }}\n  \u003Cnav class=\"toc\" aria-label=\"On this page\">{{ .TableOfContents }}\u003C\u002Fnav>\n{{ end }}\n",[39,1556,1557,1562,1567,1572],{"__ignoreMap":260},[264,1558,1559],{"class":266,"line":267},[264,1560,1561],{},"{{\u002F* layouts\u002Fpartials\u002Ftoc.html — used in layouts as {{ partial \"toc.html\" . }} *\u002F}}\n",[264,1563,1564],{"class":266,"line":274},[264,1565,1566],{},"{{ if gt (len .TableOfContents) 40 }}\n",[264,1568,1569],{"class":266,"line":295},[264,1570,1571],{},"  \u003Cnav class=\"toc\" aria-label=\"On this page\">{{ .TableOfContents }}\u003C\u002Fnav>\n",[264,1573,1574],{"class":266,"line":310},[264,1575,1576],{},"{{ end }}\n",[14,1578,1579,1580,25],{},"The census from phase 1 tells you which are worth porting; the general mapping table is in ",[21,1581,1583],{"href":1582},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fporting-shortcodes-and-includes-between-generators\u002F","Porting Shortcodes and Includes Between Generators",[27,1585,1587],{"id":1586},"replace-the-asset-pipeline-deliberately","Replace the Asset Pipeline Deliberately",[14,1589,1590],{},"Jekyll sites usually build CSS through Sass and ship JavaScript as static files, sometimes with a plugin doing minification. Hugo Pipes covers all of it natively, and the conversion is a good moment to delete a build step rather than port it.",[72,1592,1593,1703],{},[75,1594,83,1599,83,1602,83,1605,83,1608,83,1696],{"viewBox":1595,"role":78,"ariaLabelledBy":1596,"xmlns":82},"0 0 760 290",[1597,1598],"jh-assets-title","jh-assets-desc",[85,1600,1601],{"id":1597},"Asset pipeline before and after",[89,1603,1604],{"id":1598},"Two pipelines. The Jekyll pipeline runs jekyll-sass-converter, a minifier plugin and a manual fingerprinting step, producing three separate tools to maintain. The Hugo pipeline chains resources.Get, toCSS, minify and fingerprint in a single template expression with no plugins.",[93,1606],{"x":95,"y":95,"width":96,"height":1607,"fill":98},"290",[100,1609,103,1610,103,1613,103,1617,103,1621,103,1626,103,1629,103,1633,103,1637,103,1641,103,1645,103,1649,103,1653,103,1656,103,1660,103,1664,103,1668,103,1672,103,1676,103,1688,103,1692,83],{"style":102},[105,1611,1612],{"x":107,"y":108,"fill":109,"style":110},"Three plugins become one template expression",[105,1614,118],{"x":126,"y":1615,"fill":116,"style":1616},"66","font-size:12px;font-weight:700",[93,1618],{"x":1619,"y":1620,"width":114,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"130","52",[105,1622,1625],{"x":1623,"y":1624,"fill":109,"style":137},"205","78","sass-converter",[93,1627],{"x":1628,"y":1620,"width":114,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"300",[105,1630,1632],{"x":1631,"y":1624,"fill":109,"style":137},"375","minifier plugin",[93,1634],{"x":1635,"y":1620,"width":1636,"height":129,"rx":130,"fill":131,"opacity":132,"stroke":116,"style":133},"470","180",[105,1638,1640],{"x":1639,"y":1624,"fill":109,"style":137},"560","manual fingerprinting",[105,1642,1644],{"x":126,"y":1643,"fill":122,"style":1616},"176","Hugo Pipes",[93,1646],{"x":1619,"y":1647,"width":114,"height":129,"rx":130,"fill":142,"opacity":1648,"stroke":122,"style":133},"162","0.18",[105,1650,1652],{"x":1623,"y":1651,"fill":109,"style":137},"188","resources.Get",[93,1654],{"x":1628,"y":1647,"width":1655,"height":129,"rx":130,"fill":142,"opacity":1648,"stroke":122,"style":133},"120",[105,1657,1659],{"x":1658,"y":1651,"fill":109,"style":137},"360","toCSS",[93,1661],{"x":1662,"y":1647,"width":1663,"height":129,"rx":130,"fill":142,"opacity":1648,"stroke":122,"style":133},"440","110",[105,1665,1667],{"x":1666,"y":1651,"fill":109,"style":137},"495","minify",[93,1669],{"x":1670,"y":1647,"width":1671,"height":129,"rx":130,"fill":142,"opacity":1648,"stroke":122,"style":133},"570","140",[105,1673,1675],{"x":1674,"y":1651,"fill":109,"style":137},"640","fingerprint",[100,1677,198,1678,198,1682,198,1685,103],{"stroke":163,"fill":196,"style":197},[200,1679],{"d":1680,"style":1681},"M282 183 L298 183","marker-end:url(#jh-asset-arrow)",[200,1683],{"d":1684,"style":1681},"M422 183 L438 183",[200,1686],{"d":1687,"style":1681},"M552 183 L568 183",[105,1689,1691],{"x":126,"y":1690,"fill":163,"style":216},"248","No gems to install, no version drift, and the integrity hash comes out of the same chain",[105,1693,1695],{"x":126,"y":1694,"fill":163,"style":216},"270","The output is byte-identical to what the plugin chain produced — verify with a checksum before deleting the old one",[219,1697,103,1698,83],{},[222,1699,198,1701,103],{"id":1700,"viewBox":225,"refX":130,"refY":226,"markerWidth":227,"markerHeight":227,"orient":228},"jh-asset-arrow",[200,1702],{"d":231,"fill":163},[233,1704,1705],{},"The whole chain is one expression, evaluated at build time, with the fingerprint available to the template that emits the link tag.",[255,1707,1709],{"className":1527,"code":1708,"language":1529,"meta":260,"style":260},"{{ $css := resources.Get \"scss\u002Fmain.scss\" | toCSS (dict \"outputStyle\" \"compressed\")\n           | minify | fingerprint \"sha384\" }}\n\u003Clink rel=\"stylesheet\" href=\"{{ $css.RelPermalink }}\" integrity=\"{{ $css.Data.Integrity }}\" crossorigin=\"anonymous\">\n",[39,1710,1711,1716,1721],{"__ignoreMap":260},[264,1712,1713],{"class":266,"line":267},[264,1714,1715],{},"{{ $css := resources.Get \"scss\u002Fmain.scss\" | toCSS (dict \"outputStyle\" \"compressed\")\n",[264,1717,1718],{"class":266,"line":274},[264,1719,1720],{},"           | minify | fingerprint \"sha384\" }}\n",[264,1722,1723],{"class":266,"line":295},[264,1724,1725],{},"\u003Clink rel=\"stylesheet\" href=\"{{ $css.RelPermalink }}\" integrity=\"{{ $css.Data.Integrity }}\" crossorigin=\"anonymous\">\n",[14,1727,1728,1729,1733,1734,1737],{},"The fingerprinted filename is what lets you cache the file immutably at the edge, which pairs with the policies in ",[21,1730,1732],{"href":1731},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002F","CDN Caching Rules for SSGs",". Images follow the same pattern through page bundles: put the image next to its Markdown, and ",[39,1735,1736],{},".Resources.GetMatch"," gives you a resource you can resize and convert at build time without a plugin.",[27,1739,1741],{"id":1740},"measured-impact","Measured Impact",[14,1743,1744,1745,1748,1749,1752],{},"A 1,200-page documentation site with 40 images per section, measured with ",[39,1746,1747],{},"hyperfine"," on a warm cache, GitHub Actions ",[39,1750,1751],{},"ubuntu-latest"," runner:",[1754,1755,1756,1775],"table",{},[1757,1758,1759],"thead",{},[1760,1761,1762,1766,1769,1772],"tr",{},[1763,1764,1765],"th",{},"Metric",[1763,1767,1768],{},"Jekyll 4.3",[1763,1770,1771],{},"Hugo 0.128 extended",[1763,1773,1774],{},"Change",[1776,1777,1778,1793,1807,1821,1835],"tbody",{},[1760,1779,1780,1784,1787,1790],{},[1781,1782,1783],"td",{},"Full build (cold)",[1781,1785,1786],{},"96.4 s",[1781,1788,1789],{},"3.4 s",[1781,1791,1792],{},"28× faster",[1760,1794,1795,1798,1801,1804],{},[1781,1796,1797],{},"Rebuild after one page edit",[1781,1799,1800],{},"21.8 s",[1781,1802,1803],{},"0.31 s",[1781,1805,1806],{},"70× faster",[1760,1808,1809,1812,1815,1818],{},[1781,1810,1811],{},"CI job wall clock (incl. install)",[1781,1813,1814],{},"4 m 10 s",[1781,1816,1817],{},"51 s",[1781,1819,1820],{},"−79%",[1760,1822,1823,1826,1829,1832],{},[1781,1824,1825],{},"Dependencies installed",[1781,1827,1828],{},"62 gems",[1781,1830,1831],{},"1 binary",[1781,1833,1834],{},"—",[1760,1836,1837,1840,1843,1846],{},[1781,1838,1839],{},"Output size",[1781,1841,1842],{},"88 MB",[1781,1844,1845],{},"84 MB",[1781,1847,1848],{},"−5%",[72,1850,1851,1934],{},[75,1852,83,1857,83,1860,83,1863,83,1866],{"viewBox":1853,"role":78,"ariaLabelledBy":1854,"xmlns":82},"0 0 760 280",[1855,1856],"jh-bars-title","jh-bars-desc",[85,1858,1859],{"id":1855},"Build time before and after the migration",[89,1861,1862],{"id":1856},"A horizontal bar chart on a shared scale. The Jekyll cold build takes 96.4 seconds and the Hugo cold build 3.4 seconds. The Jekyll single-page rebuild takes 21.8 seconds and the Hugo rebuild 0.31 seconds, which is a thin sliver at this scale.",[93,1864],{"x":95,"y":95,"width":96,"height":1865,"fill":98},"280",[100,1867,103,1868,103,1872,103,1878,103,1883,103,1887,103,1892,103,1896,103,1902,103,1906,103,1909,103,1916,103,1919,103,1923,103,1927,103,1930,83],{"style":102},[105,1869,1871],{"x":107,"y":1870,"fill":109,"style":110},"26","1,200 pages, same content, same runner",[266,1873],{"x1":1874,"y1":1875,"x2":1874,"y2":1876,"stroke":1877,"style":133},"260","44","222","#d9e2ef",[105,1879,1882],{"x":1880,"y":1881,"fill":109,"style":1616},"60","80","Jekyll cold build",[93,1884],{"x":1874,"y":1885,"width":1662,"height":1886,"rx":226,"fill":131,"opacity":143,"stroke":116,"style":133},"64","30",[105,1888,1786],{"x":1889,"y":1890,"fill":116,"style":1891},"480","84","font-size:12px;font-weight:700;text-anchor:middle",[105,1893,1895],{"x":1880,"y":1894,"fill":109,"style":1616},"132","Hugo cold build",[93,1897],{"x":1874,"y":1898,"width":1899,"height":1886,"rx":1900,"fill":142,"opacity":1901,"stroke":122,"style":133},"116","16","4","0.3",[105,1903,1905],{"x":1628,"y":1904,"fill":122,"style":1616},"136","3.4 s · 28× faster",[105,1907,1908],{"x":1880,"y":168,"fill":109,"style":1616},"Jekyll one-page rebuild",[93,1910],{"x":1874,"y":1911,"width":1912,"height":1886,"rx":226,"fill":1913,"opacity":1914,"stroke":1915,"style":133},"168","100","#ffca3a","0.36","#a97b00",[105,1917,1800],{"x":1918,"y":1651,"fill":1915,"style":1616},"384",[105,1920,1922],{"x":1880,"y":1921,"fill":109,"style":1616},"236","Hugo one-page rebuild",[93,1924],{"x":1874,"y":128,"width":1900,"height":1886,"rx":1925,"fill":142,"opacity":1926,"stroke":122,"style":133},"2","0.4",[105,1928,1803],{"x":1929,"y":184,"fill":122,"style":1616},"288",[105,1931,1933],{"x":1932,"y":1694,"fill":163,"style":216},"249","Shared linear scale · hyperfine, 10 runs, warm cache, GitHub Actions ubuntu-latest",[233,1935,1936],{},"The rebuild row is what writers feel. Twenty-two seconds per save is a workflow where people batch their edits; a third of a second is one where they do not think about the build at all.",[14,1938,1939,1940,25],{},"The CI row matters for a different reason: dropping from 62 gems to a single binary removed an entire class of dependency failure, and made cache warming almost irrelevant — the pattern discussed in ",[21,1941,1943],{"href":1942},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions\u002F","Caching Hugo Builds in GitHub Actions",[27,1945,1947],{"id":1946},"pitfalls-rollback","Pitfalls & Rollback",[32,1949,1950,1959,1968,1981,1987,1993],{},[35,1951,1952,1958],{},[1953,1954,1955,1956,25],"strong",{},"Forgetting ",[39,1957,1376],{}," Raw HTML in Markdown disappears silently. If pages look half-empty after conversion, check this first.",[35,1960,1961,1964,1965,1967],{},[1953,1962,1963],{},"Losing page order."," Jekyll's filename dates carry ordering that Hugo ignores. Write ",[39,1966,245],{}," during conversion.",[35,1969,1970,1980],{},[1953,1971,1972,1975,1976,1979],{},[39,1973,1974],{},"{% link %}"," and ",[39,1977,1978],{},"{{ site.* }}"," left in content."," They render as literal text. The unhandled-tag report catches them all.",[35,1982,1983,1986],{},[1953,1984,1985],{},"Assuming Kramdown and Goldmark agree."," Definition lists, footnote syntax and some table edge cases differ; check a page of each type early.",[35,1988,1989,1992],{},[1953,1990,1991],{},"Deleting the Jekyll site too soon."," Keep it building until the last section has been cut over and watched for a week.",[35,1994,1995,1998],{},[1953,1996,1997],{},"Rollback:"," until the DNS or edge route changes, the Jekyll site is still live and authoritative. After cutover, rolling back is re-pointing the route — which is why staging by path prefix is worth the setup.",[27,2000,2002],{"id":2001},"conclusion","Conclusion",[14,2004,2005,2006,25],{},"A Jekyll-to-Hugo migration is mostly mechanical: collections become sections, includes split into partials and shortcodes, and permalinks move from filenames into configuration. The work that is not mechanical is the Liquid inside content, which a conversion script can find for you exhaustively. Gate on URL parity, keep the old site building until every section is cut over, and expect the build-time difference to change how writers work more than it changes how the site performs. The general framing is in ",[21,2007,24],{"href":23},[27,2009,2011],{"id":2010},"faq","FAQ",[2013,2014,2016],"h3",{"id":2015},"does-hugo-read-jekyll-front-matter-as-is","Does Hugo read Jekyll front matter as is?",[14,2018,2019,2020,447,2022,1975,2024,2027],{},"Mostly. YAML front matter between triple dashes parses directly, and ",[39,2021,85],{},[39,2023,241],{},[39,2025,2026],{},"draft"," mean the same thing in both. What differs is everything Jekyll-specific: permalink patterns, categories used as paths, and layout names that must map to Hugo template names.",[2013,2029,2031],{"id":2030},"what-happens-to-my-liquid-tags","What happens to my Liquid tags?",[14,2033,2034,2035,2037,2038,2040],{},"They will not render. Hugo uses Go templates, so ",[39,2036,611],{}," blocks, ",[39,2039,759],{}," tags and any Liquid logic in content must be converted to fenced code blocks, shortcodes or plain Markdown. A conversion script handles the common ones; the rest show up as visible braces in the build output, which makes them easy to find.",[2013,2042,2044],{"id":2043},"how-do-i-keep-my-jekyll-urls","How do I keep my Jekyll URLs?",[14,2046,2047,2048,2050,2051,2053],{},"Set ",[39,2049,1286],{}," per section in the Hugo config to match Jekyll's pattern, and add an ",[39,2052,1235],{}," entry to any page whose path genuinely has to change. Verify with a URL diff between the old sitemap and the new build before any traffic moves.",[2013,2055,2057],{"id":2056},"is-hugo-faster-in-practice-or-only-in-benchmarks","Is Hugo faster in practice or only in benchmarks?",[14,2059,2060],{},"In practice, and the gap widens with page count. A 1,200-page docs site measured here went from 96 seconds to 3.4 seconds for a full build, because Hugo renders in parallel and does not pay Ruby's per-page overhead.",[2013,2062,2064],{"id":2063},"what-do-i-lose-by-leaving-jekyll","What do I lose by leaving Jekyll?",[14,2066,2067],{},"The Ruby plugin ecosystem and the GitHub Pages default build. Most plugin functionality exists natively in Hugo, but anything genuinely custom has to be rewritten as a template or a build step, and you will need your own CI pipeline to deploy.",[27,2069,2071],{"id":2070},"related","Related",[32,2073,2074,2083,2088,2093,2100],{},[35,2075,2076,2079,2080,2082],{},[1953,2077,2078],{},"Parent:"," ",[21,2081,24],{"href":23}," — the phased process this follows.",[35,2084,2085,2087],{},[21,2086,1583],{"href":1582}," — the include-to-shortcode mapping in detail.",[35,2089,2090,2092],{},[21,2091,1506],{"href":1505}," — aliases, redirect files and edge rules.",[35,2094,2095,2099],{},[21,2096,2098],{"href":2097},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002F","Hugo Build Times for Large Repositories"," — keeping the speed you just gained.",[35,2101,2102,2106],{},[21,2103,2105],{"href":2104},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002F","Jekyll Plugin Ecosystem"," — what you are leaving behind, and what replaces it.",[2108,2109,2110],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":260,"searchDepth":274,"depth":274,"links":2112},[2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2129],{"id":29,"depth":274,"text":30},{"id":54,"depth":274,"text":55},{"id":252,"depth":274,"text":253},{"id":1243,"depth":274,"text":1244},{"id":1509,"depth":274,"text":1510},{"id":1586,"depth":274,"text":1587},{"id":1740,"depth":274,"text":1741},{"id":1946,"depth":274,"text":1947},{"id":2001,"depth":274,"text":2002},{"id":2010,"depth":274,"text":2011,"children":2123},[2124,2125,2126,2127,2128],{"id":2015,"depth":295,"text":2016},{"id":2030,"depth":295,"text":2031},{"id":2043,"depth":295,"text":2044},{"id":2056,"depth":295,"text":2057},{"id":2063,"depth":295,"text":2064},{"id":2070,"depth":274,"text":2071},[2131,2133,2136,2137],{"name":2132,"item":502},"Home",{"name":2134,"item":2135},"Choosing the Right Static Site Generator for Production","\u002Fchoosing-the-right-static-site-generator-for-production\u002F",{"name":24,"item":23},{"name":5,"item":2138},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo\u002F","2026-08-01","Convert Jekyll collections, Liquid includes and permalinks to Hugo sections, partials and URL config — with a build that drops from 96 s to 3.4 s on 1,200 pages.",[2142,2147,2149,2151,2152],{"q":2016,"a":2143},{"Mostly":2144},{" YAML front matter between triple dashes parses directly, and title, date and draft mean the same thing in both":2145},{" What differs is everything Jekyll-specific":2146},"permalink patterns, categories used as paths, and layout names that must map to Hugo template names.",{"q":2031,"a":2148},"They will not render. Hugo uses Go templates, so highlight blocks, include tags and any Liquid logic in content must be converted to fenced code blocks, shortcodes or plain Markdown. A conversion script handles the common ones; the rest show up as visible braces in the build output, which makes them easy to find.",{"q":2044,"a":2150},"Set permalinks per section in the Hugo config to match Jekyll's pattern, and add an aliases entry to any page whose path genuinely has to change. Verify with a URL diff between the old sitemap and the new build before any traffic moves.",{"q":2057,"a":2060},{"q":2064,"a":2067},{},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo",{"title":5,"description":2140},"choosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo\u002Findex","article","djuITI0IpILpzmz7g8Gq3ESvTzg4SEq8GnerD0HpPXU",[2160,2163,2166,2169,2172,2174,2177,2180,2182,2185,2187,2190,2193,2195,2197,2198,2201,2203,2206,2209,2212,2215,2218,2221,2224,2227,2230,2232,2235,2238,2241,2244,2247,2250,2253,2256,2259,2262,2265,2268,2271,2274,2277,2280,2283,2286,2289,2292,2295,2298,2301,2304,2307,2310,2313,2316,2319,2322,2325,2328,2331,2334,2337,2340,2343,2346,2349,2351,2354,2357,2360,2363,2366,2369,2372,2375,2378,2381,2384,2387,2390,2393,2396],{"path":2161,"title":2162},"\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":2164,"title":2165},"\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":2167,"title":2168},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":2170,"title":2171},"\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":2173,"title":2098},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories",{"path":2175,"title":2176},"\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":2178,"title":2179},"\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":2181,"title":2134},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":2183,"title":2184},"\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":2186,"title":2105},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem",{"path":2188,"title":2189},"\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":2191,"title":2192},"\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":2194,"title":24},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators",{"path":2196,"title":1506},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration",{"path":2154,"title":5},{"path":2199,"title":2200},"\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":2202,"title":1583},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fporting-shortcodes-and-includes-between-generators",{"path":2204,"title":2205},"\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":2207,"title":2208},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":2210,"title":2211},"\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":2213,"title":2214},"\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":2216,"title":2217},"\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":2219,"title":2220},"\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":2222,"title":2223},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":2225,"title":2226},"\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":2228,"title":2229},"\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":2231,"title":1732},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs",{"path":2233,"title":2234},"\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":2236,"title":2237},"\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":2239,"title":2240},"\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":2242,"title":2243},"\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":2245,"title":2246},"\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":2248,"title":2249},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":2251,"title":2252},"\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":2254,"title":2255},"\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":2257,"title":2258},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":2260,"title":2261},"\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":2263,"title":2264},"\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":2266,"title":2267},"\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":2269,"title":2270},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":2272,"title":2273},"\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":2275,"title":2276},"\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":2278,"title":2279},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":2281,"title":2282},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":2284,"title":2285},"\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":2287,"title":2288},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":2290,"title":2291},"\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":2293,"title":2294},"\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":2296,"title":2297},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":2299,"title":2300},"\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":2302,"title":2303},"\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":2305,"title":2306},"\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":2308,"title":2309},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":2311,"title":2312},"\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":2314,"title":2315},"\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":2317,"title":2318},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":2320,"title":2321},"\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":2323,"title":2324},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":2326,"title":2327},"\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":2329,"title":2330},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":2332,"title":2333},"\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":2335,"title":2336},"\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":2338,"title":2339},"\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":2341,"title":2342},"\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":2344,"title":2345},"\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":2347,"title":2348},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":2350,"title":1943},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions",{"path":2352,"title":2353},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":2355,"title":2356},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":2358,"title":2359},"\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":2361,"title":2362},"\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":2364,"title":2365},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":2367,"title":2368},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":2370,"title":2371},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":2373,"title":2374},"\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":2376,"title":2377},"\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":2379,"title":2380},"\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":2382,"title":2383},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":2385,"title":2386},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":2388,"title":2389},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":2391,"title":2392},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":2394,"title":2395},"\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":2397,"title":2398},"\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",1785611671084]