[{"data":1,"prerenderedAt":2287},["ShallowReactive",2],{"page:\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https":3,"all-docs-nav":1139,"filed:\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https":2279},{"id":4,"title":5,"body":6,"breadcrumb":1115,"dateModified":1125,"datePublished":1125,"description":1126,"extension":1127,"faq":1128,"meta":1133,"navigation":346,"path":1134,"seo":1135,"slug":12,"stem":1136,"type":1137,"__hash__":1138},"content\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https\u002Findex.md","Serving a Static Site With Caddy and Automatic HTTPS",{"type":7,"value":8,"toc":1094},"minimark",[9,13,17,36,41,54,58,224,228,231,306,309,313,437,452,459,463,469,509,512,516,523,542,575,597,724,728,735,739,747,751,757,760,764,851,967,970,974,1007,1011,1014,1018,1023,1026,1030,1033,1037,1040,1044,1047,1051,1090],[10,11,5],"h1",{"id":12},"serving-a-static-site-with-caddy-and-automatic-https",[14,15,16],"p",{},"Caddy's headline feature is that HTTPS needs no configuration: write a domain name in the Caddyfile, start the server, and a trusted certificate appears and renews itself. For one site on one server that really is the whole story. Running several static sites in production on one Caddy server raises the questions the headline skips: what must be true of DNS and the network for issuance to work, how to test without burning through certificate authority rate limits, where certificates live and what happens when the server is rebuilt, and how to get wildcard certificates for preview subdomains.",[14,18,19,20,25,26,30,31,35],{},"This guide sets up a 2-vCPU VM that serves four static sites — documentation, marketing, a status page and per-branch previews — with Caddy 2.8, covering the certificate side end to end. It belongs to ",[21,22,24],"a",{"href":23},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002F","Self-Hosting Static Sites on S3, Nginx and Caddy","; the basic Caddy setup is in ",[21,27,29],{"href":28},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy\u002F","Serving a Static Site with Caddy",", and headers in ",[21,32,34],{"href":33},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecurity-headers-for-static-sites-served-by-caddy\u002F","Security Headers for Static Sites Served by Caddy",".",[37,38,40],"h2",{"id":39},"prerequisites","Prerequisites",[42,43,44,48,51],"ul",{},[45,46,47],"li",{},"A VM with a public IPv4 (and ideally IPv6) address, Caddy installed from its official package repository.",[45,49,50],{},"DNS for each domain you control, with A\u002FAAAA records you can point at the server.",[45,52,53],{},"Firewall rules allowing inbound TCP 80 and 443, and UDP 443 for HTTP\u002F3.",[37,55,57],{"id":56},"how-automatic-https-works","How Automatic HTTPS Works",[59,60,61,220],"figure",{},[62,63,70,71,70,75,70,79,70,86,70,205],"svg",{"viewBox":64,"role":65,"ariaLabelledBy":66,"xmlns":69},"0 0 760 360","img",[67,68],"caddyhttps-seq-title","caddyhttps-seq-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[72,73,74],"title",{"id":67},"Sequence of Caddy obtaining a certificate for a newly configured domain",[76,77,78],"desc",{"id":68},"Four actors, the Caddy server, Let's Encrypt, DNS and a reader. On startup Caddy sees docs.example.com in its config and requests a certificate from Let's Encrypt. Let's Encrypt resolves the domain through DNS to the server and sends a challenge over port 443 or 80. Caddy answers the challenge. Let's Encrypt issues the certificate, which Caddy stores in its data directory. Readers then connect over HTTPS, and Caddy renews about 30 days before expiry.",[80,81],"rect",{"x":82,"y":82,"width":83,"height":84,"fill":85},"0","760","360","#ffffff",[87,88,90,91,90,101,90,104,90,107,90,110,90,117,90,120,90,123,90,126,90,130,90,133,90,137,90,140,90,143,90,146,90,153,90,159,90,163,90,167,90,171,90,177,90,181,90,185,90,189,90,193,90,197,90,201,70],"g",{"style":89},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[80,92],{"x":93,"y":94,"width":95,"height":96,"rx":97,"fill":98,"stroke":99,"style":100},"30.0","56.0","160.0","42.9","8","#f8fafc","#d9e2ef","stroke-width:1.5px",[80,102],{"x":103,"y":94,"width":95,"height":96,"rx":97,"fill":98,"stroke":99,"style":100},"210.0",[80,105],{"x":106,"y":94,"width":95,"height":96,"rx":97,"fill":98,"stroke":99,"style":100},"390.0",[80,108],{"x":109,"y":94,"width":95,"height":96,"rx":97,"fill":98,"stroke":99,"style":100},"570.0",[111,112],"path",{"d":113,"fill":114,"stroke":115,"style":116},"M114.0 148.8 L284.0 148.8","none","#556071","stroke-width:1.8px;marker-end:url(#caddyhttps-seq-arrow)",[111,118],{"d":119,"fill":114,"stroke":115,"style":116},"M294.0 181.8 L464.0 181.8",[111,121],{"d":122,"fill":114,"stroke":115,"style":116},"M286.0 229.7 L116.0 229.7",[111,124],{"d":125,"fill":114,"stroke":115,"style":116},"M114.0 262.6 L284.0 262.6",[111,127],{"d":128,"fill":114,"stroke":115,"style":129},"M286.0 295.6 L116.0 295.6","stroke-width:1.8px;stroke-dasharray:5 4;marker-end:url(#caddyhttps-seq-arrow)",[111,131],{"d":132,"fill":114,"stroke":115,"style":116},"M646.0 328.5 L116.0 328.5",[111,134],{"d":135,"fill":114,"stroke":99,"style":136},"M110.0 100.9 L110.0 344.5","stroke-width:1.5px;stroke-dasharray:4 4",[111,138],{"d":139,"fill":114,"stroke":99,"style":136},"M290.0 100.9 L290.0 344.5",[111,141],{"d":142,"fill":114,"stroke":99,"style":136},"M470.0 100.9 L470.0 344.5",[111,144],{"d":145,"fill":114,"stroke":99,"style":136},"M650.0 100.9 L650.0 344.5",[147,148,152],"text",{"x":149,"y":93,"fill":150,"style":151},"380.0","#1f2937","font-size:16px;text-anchor:middle;font-weight:700","First request for a new domain",[147,154,158],{"x":155,"y":156,"fill":150,"style":157},"110.0","82.7","font-size:13px;text-anchor:middle;font-weight:700","Caddy",[147,160,162],{"x":161,"y":156,"fill":150,"style":157},"290.0","Let's Encrypt",[147,164,166],{"x":165,"y":156,"fill":150,"style":157},"470.0","DNS",[147,168,170],{"x":169,"y":156,"fill":150,"style":157},"650.0","Reader",[147,172,176],{"x":173,"y":174,"fill":150,"style":175},"200.0","125.8","font-size:11.5px;text-anchor:middle","order certificate for",[147,178,180],{"x":173,"y":179,"fill":150,"style":175},"140.8","docs.example.com",[147,182,184],{"x":149,"y":183,"fill":150,"style":175},"173.7","resolve docs.example.com",[147,186,188],{"x":173,"y":187,"fill":150,"style":175},"206.7","challenge on :443",[147,190,192],{"x":173,"y":191,"fill":150,"style":175},"221.6","(TLS-ALPN) or :80",[147,194,196],{"x":173,"y":195,"fill":150,"style":175},"254.6","challenge answered",[147,198,200],{"x":173,"y":199,"fill":115,"style":175},"287.5","certificate issued → stored",[147,202,204],{"x":149,"y":203,"fill":150,"style":175},"320.5","HTTPS from now on",[206,207,90,208,70],"defs",{},[209,210,216,217,90],"marker",{"id":211,"viewBox":212,"refX":97,"refY":213,"markerWidth":214,"markerHeight":214,"orient":215},"caddyhttps-seq-arrow","0 0 10 10","5","7","auto-start-reverse","\n      ",[111,218],{"d":219,"fill":115},"M0 0 L10 5 L0 10 z",[221,222,223],"figcaption",{},"Issuance takes a few seconds; nothing in the Caddyfile mentions certificates.",[37,225,227],{"id":226},"step-1-dns-and-network-first","Step 1: DNS and Network First",[14,229,230],{},"Most failed issuances are DNS or firewall problems. Before adding a domain to the Caddyfile, check from outside the server:",[232,233,238],"pre",{"className":234,"code":235,"language":236,"meta":237,"style":237},"language-sh shiki shiki-themes github-light github-dark","dig +short docs.example.com A @1.1.1.1      # must return the server's IP\ndig +short docs.example.com AAAA @1.1.1.1   # if present, must also be this server\ncurl -sI http:\u002F\u002Fdocs.example.com\u002F --max-time 5   # port 80 must reach Caddy\n","sh","",[239,240,241,267,284],"code",{"__ignoreMap":237},[242,243,246,250,254,257,260,263],"span",{"class":244,"line":245},"line",1,[242,247,249],{"class":248},"sScJk","dig",[242,251,253],{"class":252},"sZZnC"," +short",[242,255,256],{"class":252}," docs.example.com",[242,258,259],{"class":252}," A",[242,261,262],{"class":252}," @1.1.1.1",[242,264,266],{"class":265},"sJ8bj","      # must return the server's IP\n",[242,268,270,272,274,276,279,281],{"class":244,"line":269},2,[242,271,249],{"class":248},[242,273,253],{"class":252},[242,275,256],{"class":252},[242,277,278],{"class":252}," AAAA",[242,280,262],{"class":252},[242,282,283],{"class":265},"   # if present, must also be this server\n",[242,285,287,290,294,297,300,303],{"class":244,"line":286},3,[242,288,289],{"class":248},"curl",[242,291,293],{"class":292},"sj4cs"," -sI",[242,295,296],{"class":252}," http:\u002F\u002Fdocs.example.com\u002F",[242,298,299],{"class":292}," --max-time",[242,301,302],{"class":292}," 5",[242,304,305],{"class":265},"   # port 80 must reach Caddy\n",[14,307,308],{},"An AAAA record pointing at an old server is a classic trap: the certificate authority may validate over IPv6, reach the old machine and fail. Either point AAAA at the new server or remove it.",[37,310,312],{"id":311},"step-2-configure-the-sites-starting-with-the-staging-ca","Step 2: Configure the Sites, Starting With the Staging CA",[232,314,318],{"className":315,"code":316,"language":317,"meta":237,"style":237},"language-caddyfile shiki shiki-themes github-light github-dark","{\n    email ops@example.com\n    acme_ca https:\u002F\u002Facme-staging-v02.api.letsencrypt.org\u002Fdirectory   # remove after testing\n}\n\ndocs.example.com {\n    root * \u002Fsrv\u002Fdocs\u002Fcurrent\n    file_server { precompressed br gzip }\n    import security_headers\n}\n\nwww.example.com, example.com {\n    root * \u002Fsrv\u002Fwww\u002Fcurrent\n    file_server { precompressed br gzip }\n    import security_headers\n}\n\nstatus.example.com {\n    root * \u002Fsrv\u002Fstatus\u002Fcurrent\n    file_server\n}\n","caddyfile",[239,319,320,325,330,335,341,348,354,360,366,372,377,382,388,394,399,404,409,414,420,426,432],{"__ignoreMap":237},[242,321,322],{"class":244,"line":245},[242,323,324],{},"{\n",[242,326,327],{"class":244,"line":269},[242,328,329],{},"    email ops@example.com\n",[242,331,332],{"class":244,"line":286},[242,333,334],{},"    acme_ca https:\u002F\u002Facme-staging-v02.api.letsencrypt.org\u002Fdirectory   # remove after testing\n",[242,336,338],{"class":244,"line":337},4,[242,339,340],{},"}\n",[242,342,344],{"class":244,"line":343},5,[242,345,347],{"emptyLinePlaceholder":346},true,"\n",[242,349,351],{"class":244,"line":350},6,[242,352,353],{},"docs.example.com {\n",[242,355,357],{"class":244,"line":356},7,[242,358,359],{},"    root * \u002Fsrv\u002Fdocs\u002Fcurrent\n",[242,361,363],{"class":244,"line":362},8,[242,364,365],{},"    file_server { precompressed br gzip }\n",[242,367,369],{"class":244,"line":368},9,[242,370,371],{},"    import security_headers\n",[242,373,375],{"class":244,"line":374},10,[242,376,340],{},[242,378,380],{"class":244,"line":379},11,[242,381,347],{"emptyLinePlaceholder":346},[242,383,385],{"class":244,"line":384},12,[242,386,387],{},"www.example.com, example.com {\n",[242,389,391],{"class":244,"line":390},13,[242,392,393],{},"    root * \u002Fsrv\u002Fwww\u002Fcurrent\n",[242,395,397],{"class":244,"line":396},14,[242,398,365],{},[242,400,402],{"class":244,"line":401},15,[242,403,371],{},[242,405,407],{"class":244,"line":406},16,[242,408,340],{},[242,410,412],{"class":244,"line":411},17,[242,413,347],{"emptyLinePlaceholder":346},[242,415,417],{"class":244,"line":416},18,[242,418,419],{},"status.example.com {\n",[242,421,423],{"class":244,"line":422},19,[242,424,425],{},"    root * \u002Fsrv\u002Fstatus\u002Fcurrent\n",[242,427,429],{"class":244,"line":428},20,[242,430,431],{},"    file_server\n",[242,433,435],{"class":244,"line":434},21,[242,436,340],{},[14,438,439,440,443,444,447,448,451],{},"The staging CA issues untrusted certificates with much higher rate limits, so configuration mistakes during setup cost nothing. ",[239,441,442],{},"caddy validate"," checks syntax; ",[239,445,446],{},"journalctl -u caddy -f"," shows each issuance. Once all four names had staging certificates, the ",[239,449,450],{},"acme_ca"," line was removed and Caddy reloaded; production certificates were issued in about 20 seconds in total.",[14,453,454,455,458],{},"The ",[239,456,457],{},"email"," lets the certificate authority send expiry warnings if renewal ever fails, which is a useful second alarm.",[37,460,462],{"id":461},"step-3-redirect-apex-and-www","Step 3: Redirect Apex and www",[14,464,465,468],{},[239,466,467],{},"www.example.com, example.com"," in one block serves both names with the same content, which creates duplicate URLs. A separate block redirects one to the other:",[232,470,472],{"className":315,"code":471,"language":317,"meta":237,"style":237},"example.com {\n    redir https:\u002F\u002Fwww.example.com{uri} permanent\n}\nwww.example.com {\n    root * \u002Fsrv\u002Fwww\u002Fcurrent\n    file_server { precompressed br gzip }\n    import security_headers\n}\n",[239,473,474,479,484,488,493,497,501,505],{"__ignoreMap":237},[242,475,476],{"class":244,"line":245},[242,477,478],{},"example.com {\n",[242,480,481],{"class":244,"line":269},[242,482,483],{},"    redir https:\u002F\u002Fwww.example.com{uri} permanent\n",[242,485,486],{"class":244,"line":286},[242,487,340],{},[242,489,490],{"class":244,"line":337},[242,491,492],{},"www.example.com {\n",[242,494,495],{"class":244,"line":343},[242,496,393],{},[242,498,499],{"class":244,"line":350},[242,500,365],{},[242,502,503],{"class":244,"line":356},[242,504,371],{},[242,506,507],{"class":244,"line":362},[242,508,340],{},[14,510,511],{},"Caddy obtains certificates for both names, so the redirect itself is served over HTTPS without a warning.",[37,513,515],{"id":514},"step-4-wildcard-certificates-for-previews","Step 4: Wildcard Certificates for Previews",[14,517,518,519,522],{},"Branch previews are served at ",[239,520,521],{},"\u003Cbranch>.preview.example.com",", created and deleted by CI. One certificate per branch would hit rate limits on busy days. A wildcard certificate covers them all; it needs the DNS challenge, which needs Caddy built with the DNS provider's module:",[232,524,526],{"className":234,"code":525,"language":236,"meta":237,"style":237},"xcaddy build --with github.com\u002Fcaddy-dns\u002Fcloudflare\n",[239,527,528],{"__ignoreMap":237},[242,529,530,533,536,539],{"class":244,"line":245},[242,531,532],{"class":248},"xcaddy",[242,534,535],{"class":252}," build",[242,537,538],{"class":292}," --with",[242,540,541],{"class":252}," github.com\u002Fcaddy-dns\u002Fcloudflare\n",[232,543,545],{"className":315,"code":544,"language":317,"meta":237,"style":237},"*.preview.example.com {\n    tls { dns cloudflare {env.CF_API_TOKEN} }\n    root * \u002Fsrv\u002Fpreviews\u002F{labels.3}\n    file_server\n    header X-Robots-Tag \"noindex, nofollow\"\n}\n",[239,546,547,552,557,562,566,571],{"__ignoreMap":237},[242,548,549],{"class":244,"line":245},[242,550,551],{},"*.preview.example.com {\n",[242,553,554],{"class":244,"line":269},[242,555,556],{},"    tls { dns cloudflare {env.CF_API_TOKEN} }\n",[242,558,559],{"class":244,"line":286},[242,560,561],{},"    root * \u002Fsrv\u002Fpreviews\u002F{labels.3}\n",[242,563,564],{"class":244,"line":337},[242,565,431],{},[242,567,568],{"class":244,"line":343},[242,569,570],{},"    header X-Robots-Tag \"noindex, nofollow\"\n",[242,572,573],{"class":244,"line":350},[242,574,340],{},[14,576,577,580,581,584,585,588,589,592,593,35],{},[239,578,579],{},"{labels.3}"," is the branch label of the hostname, so ",[239,582,583],{},"feature-x.preview.example.com"," serves ",[239,586,587],{},"\u002Fsrv\u002Fpreviews\u002Ffeature-x",". The API token is scoped to DNS edits on the one zone. Previews get ",[239,590,591],{},"noindex",", as described in ",[21,594,596],{"href":595},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Ffixing-preview-deploys-leaking-into-search-results\u002F","Fixing Preview Deploys Leaking Into Search Results",[59,598,599,721],{},[62,600,70,605,70,608,70,611,70,614],{"viewBox":601,"role":65,"ariaLabelledBy":602,"xmlns":69},"0 0 760 236",[603,604],"caddyhttps-certs-title","caddyhttps-certs-desc",[72,606,607],{"id":603},"Certificates and challenge types for each hostname on the server",[76,609,610],{"id":604},"A matrix of four hostname groups. docs.example.com uses an individual certificate via the TLS-ALPN challenge. example.com and www.example.com use individual certificates via TLS-ALPN, with the apex redirecting to www. status.example.com uses an individual certificate. The preview wildcard uses one wildcard certificate via the DNS challenge with a scoped API token.",[80,612],{"x":82,"y":82,"width":83,"height":613,"fill":85},"236",[87,615,90,616,90,619,90,629,90,634,90,637,90,640,90,642,90,645,90,648,90,650,90,653,90,656,90,661,90,664,90,667,90,672,90,677,90,681,90,684,90,688,90,691,90,695,90,699,90,701,90,705,90,708,90,710,90,714,90,718,70],{"style":89},[111,617],{"d":618,"fill":114,"stroke":115,"style":100},"M20.0 86.0 L740.0 86.0",[80,620],{"x":621,"y":622,"width":623,"height":624,"rx":213,"fill":625,"opacity":626,"stroke":627,"style":628},"214.0","90.0","257.0","25.6","#8ac926","0.2","#5a8a16","stroke-width:1px",[80,630],{"x":631,"y":622,"width":623,"height":624,"rx":213,"fill":632,"opacity":633,"stroke":632,"style":628},"479.0","#1982c4","0.14",[111,635],{"d":636,"fill":114,"stroke":99,"style":628},"M20.0 119.6 L740.0 119.6",[80,638],{"x":621,"y":639,"width":623,"height":624,"rx":213,"fill":625,"opacity":626,"stroke":627,"style":628},"123.6",[80,641],{"x":631,"y":639,"width":623,"height":624,"rx":213,"fill":632,"opacity":633,"stroke":632,"style":628},[111,643],{"d":644,"fill":114,"stroke":99,"style":628},"M20.0 153.2 L740.0 153.2",[80,646],{"x":621,"y":647,"width":623,"height":624,"rx":213,"fill":625,"opacity":626,"stroke":627,"style":628},"157.2",[80,649],{"x":631,"y":647,"width":623,"height":624,"rx":213,"fill":632,"opacity":633,"stroke":632,"style":628},[111,651],{"d":652,"fill":114,"stroke":99,"style":628},"M20.0 186.8 L740.0 186.8",[80,654],{"x":621,"y":655,"width":623,"height":624,"rx":213,"fill":625,"opacity":626,"stroke":627,"style":628},"190.8",[80,657],{"x":631,"y":655,"width":623,"height":624,"rx":213,"fill":658,"opacity":659,"stroke":660,"style":628},"#ffca3a","0.24","#a97b00",[111,662],{"d":663,"fill":114,"stroke":99,"style":628},"M20.0 220.4 L740.0 220.4",[147,665,666],{"x":149,"y":93,"fill":150,"style":151},"Certificates on the server",[147,668,671],{"x":93,"y":669,"fill":150,"style":670},"75.2","font-size:12px;text-anchor:start;font-weight:700","Hostnames",[147,673,676],{"x":674,"y":669,"fill":150,"style":675},"342.5","font-size:12px;text-anchor:middle;font-weight:700","Certificate",[147,678,680],{"x":679,"y":669,"fill":150,"style":675},"607.5","Challenge",[147,682,180],{"x":93,"y":683,"fill":150,"style":670},"106.4",[147,685,687],{"x":674,"y":686,"fill":150,"style":175},"106.2","individual",[147,689,690],{"x":679,"y":686,"fill":150,"style":175},"TLS-ALPN (443)",[147,692,694],{"x":93,"y":693,"fill":150,"style":670},"140.0","example.com, www",[147,696,698],{"x":674,"y":697,"fill":150,"style":175},"139.8","two individual",[147,700,690],{"x":679,"y":697,"fill":150,"style":175},[147,702,704],{"x":93,"y":703,"fill":150,"style":670},"173.6","status.example.com",[147,706,687],{"x":674,"y":707,"fill":150,"style":175},"173.4",[147,709,690],{"x":679,"y":707,"fill":150,"style":175},[147,711,713],{"x":93,"y":712,"fill":150,"style":670},"207.2","*.preview.example.com",[147,715,717],{"x":674,"y":716,"fill":150,"style":175},"207.0","one wildcard",[147,719,720],{"x":679,"y":716,"fill":150,"style":175},"DNS (API token)",[221,722,723],{},"Five certificates cover four sites and unlimited preview subdomains.",[37,725,727],{"id":726},"step-5-persist-and-back-up-the-data-directory","Step 5: Persist and Back Up the Data Directory",[14,729,730,731,734],{},"Certificates, private keys and the ACME account live in Caddy's data directory (",[239,732,733],{},"\u002Fvar\u002Flib\u002Fcaddy\u002F.local\u002Fshare\u002Fcaddy"," for the packaged service). The VM is rebuilt from an image a few times a year; the first rebuild lost the directory, and Caddy reissued all five certificates on start — fine once, but a rebuild loop during an incident could have hit the duplicate-certificate limit. The directory now lives on an attached volume that survives rebuilds, and a nightly backup copies it to object storage, encrypted.",[37,736,738],{"id":737},"step-6-monitor-renewal-anyway","Step 6: Monitor Renewal Anyway",[14,740,741,742,746],{},"Caddy renews about 30 days before expiry and retries on failure, but renewal can still fail for reasons outside it: a DNS change, a firewall rule, an expired DNS API token for the wildcard. An external check alerts when any of the five certificates has fewer than 21 days left, as in ",[21,743,745],{"href":744},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fmonitoring-tls-certificate-expiry\u002F","Monitoring TLS Certificate Expiry",". In the first year it fired once — the DNS API token for the wildcard had been rotated without updating the server.",[37,748,750],{"id":749},"running-two-servers","Running Two Servers",[14,752,753,754,756],{},"The status page must stay up when the main server does not, so it also runs on a second small VM in another region. Two Caddy servers obtaining certificates for the same names independently would each work, but doubles issuance and can trip rate limits during rebuilds. Caddy supports shared storage for certificates — any storage module both servers can reach, such as a shared filesystem or an object store through a plugin — and coordinates issuance through it with locks, so one server obtains a certificate and both use it. The team used a small S3-compatible bucket through a storage module, with DNS failover health checks switching ",[239,755,704],{}," to the second VM if the first stops answering.",[14,758,759],{},"For the other sites, a single server behind a CDN was enough: the CDN serves cached pages through short origin outages, and a rebuilt server comes back with its certificates from the persistent volume in under a minute.",[37,761,763],{"id":762},"measured-impact","Measured Impact",[765,766,767,783],"table",{},[768,769,770],"thead",{},[771,772,773,777,780],"tr",{},[774,775,776],"th",{},"Measure",[774,778,779],{},"Value",[774,781,782],{},"Source",[784,785,786,798,816,827,838],"tbody",{},[771,787,788,792,795],{},[789,790,791],"td",{},"Time to add a new site with HTTPS",[789,793,794],{},"~5 min (DNS + 4 config lines)",[789,796,797],{},"Runbook timing",[771,799,800,803,813],{},[789,801,802],{},"Certificate-related config lines",[789,804,805,806,808,809,812],{},"2 (",[239,807,457],{},", wildcard ",[239,810,811],{},"tls",")",[789,814,815],{},"Caddyfile",[771,817,818,821,824],{},[789,819,820],{},"Renewal failures in 12 months",[789,822,823],{},"1 (rotated DNS token), caught at 21 days",[789,825,826],{},"Monitoring",[771,828,829,832,835],{},[789,830,831],{},"SSL Labs grade",[789,833,834],{},"A+ (with HSTS from the header snippet)",[789,836,837],{},"SSL Labs",[771,839,840,843,846],{},[789,841,842],{},"TLS handshake time p50 (TLS 1.3, HTTP\u002F3 available)",[789,844,845],{},"21 ms in-region",[789,847,848],{},[239,849,850],{},"curl -w",[59,852,853,964],{},[62,854,70,859,70,862,70,865,70,868,70,957],{"viewBox":855,"role":65,"ariaLabelledBy":856,"xmlns":69},"0 0 760 154",[857,858],"caddyhttps-add-title","caddyhttps-add-desc",[72,860,861],{"id":857},"Steps to add a new static site with HTTPS on the Caddy server",[76,863,864],{"id":858},"Five steps. Create A and AAAA records pointing at the server and check them from outside. Add a site block with the root and the header snippet. Validate the Caddyfile. Reload Caddy, which obtains the certificate in seconds. Add the hostname to the expiry monitor.",[80,866],{"x":82,"y":82,"width":83,"height":867,"fill":85},"154",[87,869,90,870,90,876,90,879,90,883,90,886,90,889,90,892,90,895,90,899,90,902,90,905,90,910,90,915,90,919,90,924,90,928,90,932,90,936,90,940,90,944,90,947,90,951,90,954,70],{"style":89},[80,871],{"x":872,"y":873,"width":874,"height":875,"rx":97,"fill":98,"stroke":99,"style":100},"20.0","64.0","116.8","74.1",[80,877],{"x":878,"y":873,"width":874,"height":875,"rx":97,"fill":632,"opacity":633,"stroke":632,"style":100},"170.8",[111,880],{"d":881,"fill":114,"stroke":115,"style":882},"M138.8 101.1 L166.8 101.1","stroke-width:2px;marker-end:url(#caddyhttps-add-arrow)",[80,884],{"x":885,"y":873,"width":874,"height":875,"rx":97,"fill":632,"opacity":633,"stroke":632,"style":100},"321.6",[111,887],{"d":888,"fill":114,"stroke":115,"style":882},"M289.6 101.1 L317.6 101.1",[80,890],{"x":891,"y":873,"width":874,"height":875,"rx":97,"fill":625,"opacity":626,"stroke":627,"style":100},"472.4",[111,893],{"d":894,"fill":114,"stroke":115,"style":882},"M440.4 101.1 L468.4 101.1",[80,896],{"x":897,"y":873,"width":874,"height":875,"rx":97,"fill":898,"opacity":633,"stroke":898,"style":100},"623.2","#6a4c93",[111,900],{"d":901,"fill":114,"stroke":115,"style":882},"M591.2 101.1 L619.2 101.1",[147,903,904],{"x":149,"y":93,"fill":150,"style":151},"Adding a site to the server",[147,906,909],{"x":907,"y":908,"fill":150,"style":157},"78.4","91.7","DNS records",[147,911,914],{"x":907,"y":912,"fill":115,"style":913},"108.6","font-size:11px;text-anchor:middle","check with dig",[147,916,918],{"x":907,"y":917,"fill":115,"style":913},"122.9","@1.1.1.1",[147,920,923],{"x":921,"y":922,"fill":150,"style":157},"229.2","98.8","Site block",[147,925,927],{"x":921,"y":926,"fill":115,"style":913},"115.7","root + snippet",[147,929,931],{"x":149,"y":930,"fill":150,"style":157},"90.4","caddy",[147,933,935],{"x":149,"y":934,"fill":150,"style":157},"107.3","validate",[147,937,939],{"x":149,"y":938,"fill":115,"style":913},"124.2","syntax check",[147,941,943],{"x":942,"y":922,"fill":150,"style":157},"530.8","caddy reload",[147,945,946],{"x":942,"y":926,"fill":115,"style":913},"certificate issued",[147,948,950],{"x":949,"y":930,"fill":150,"style":157},"681.6","Add to",[147,952,953],{"x":949,"y":934,"fill":150,"style":157},"monitor",[147,955,956],{"x":949,"y":938,"fill":115,"style":913},"expiry alert",[206,958,90,959,70],{},[209,960,216,962,90],{"id":961,"viewBox":212,"refX":97,"refY":213,"markerWidth":214,"markerHeight":214,"orient":215},"caddyhttps-add-arrow",[111,963],{"d":219,"fill":115},[221,965,966],{},"The whole procedure is in the runbook and takes about five minutes, most of it DNS propagation.",[14,968,969],{},"No certificate has expired on the server since it went live.",[37,971,973],{"id":972},"pitfalls-rollback","Pitfalls & Rollback",[42,975,976,983,989,995,1001],{},[45,977,978,982],{},[979,980,981],"strong",{},"Stale AAAA records."," Validation over IPv6 reaches the wrong server.",[45,984,985,988],{},[979,986,987],{},"Testing against the production CA."," Use the staging CA until everything works.",[45,990,991,994],{},[979,992,993],{},"Ephemeral data directories."," Persist and back up certificates and keys.",[45,996,997,1000],{},[979,998,999],{},"Unmonitored DNS tokens for wildcards."," Rotations break renewal silently.",[45,1002,1003,1006],{},[979,1004,1005],{},"Rollback:"," each site is an independent block; removing it and reloading takes it offline without affecting the others.",[37,1008,1010],{"id":1009},"conclusion","Conclusion",[14,1012,1013],{},"Automatic HTTPS in Caddy is genuinely automatic once its preconditions hold: correct A and AAAA records, open ports 80 and 443, a persistent data directory and, for wildcards, a scoped DNS token. Testing against the staging CA, keeping certificates on a persistent volume and monitoring expiry independently turned four static sites and unlimited preview subdomains into five certificates that renewed themselves for a year with one caught failure.",[37,1015,1017],{"id":1016},"faq","FAQ",[1019,1020,1022],"h3",{"id":1021},"what-does-caddy-need-to-obtain-certificates-automatically","What does Caddy need to obtain certificates automatically?",[14,1024,1025],{},"A public DNS record pointing the domain at the server, ports 80 and 443 reachable from the internet for the HTTP and TLS-ALPN challenges, and a writable data directory to store certificates and account keys. With those in place, putting the domain name in the Caddyfile is enough.",[1019,1027,1029],{"id":1028},"how-do-i-avoid-hitting-lets-encrypt-rate-limits-while-testing","How do I avoid hitting Let's Encrypt rate limits while testing?",[14,1031,1032],{},"Point Caddy at the Let's Encrypt staging environment with the acme_ca global option while setting up, which has much higher limits and issues untrusted test certificates. Switch back to production once the configuration works. Caddy also falls back to ZeroSSL automatically if Let's Encrypt fails.",[1019,1034,1036],{"id":1035},"can-caddy-issue-wildcard-certificates","Can Caddy issue wildcard certificates?",[14,1038,1039],{},"Yes, using the DNS challenge, which requires a Caddy build with the DNS provider module for your DNS host and an API token. Wildcards are useful for many subdomains such as per-branch previews; for a handful of fixed hostnames, individual certificates through the default challenges are simpler.",[1019,1041,1043],{"id":1042},"what-happens-to-certificates-if-the-server-is-rebuilt","What happens to certificates if the server is rebuilt?",[14,1045,1046],{},"Caddy stores certificates in its data directory. If that directory is lost, Caddy requests new certificates on start, which works but counts against rate limits and fails if many domains are reissued at once. Back up the data directory or put it on persistent storage that survives rebuilds.",[37,1048,1050],{"id":1049},"related","Related",[42,1052,1053,1062,1067,1074,1079],{},[45,1054,1055,1058,1059,1061],{},[979,1056,1057],{},"Parent:"," ",[21,1060,24],{"href":23}," — running your own hosting.",[45,1063,1064,1066],{},[21,1065,29],{"href":28}," — the basic setup.",[45,1068,1069,1073],{},[21,1070,1072],{"href":1071},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fnginx-vs-caddy-for-serving-static-sites\u002F","Nginx vs Caddy for Serving Static Sites"," — why Caddy for this server.",[45,1075,1076,1078],{},[21,1077,34],{"href":33}," — the header snippet imported here.",[45,1080,1081,1085,1086,1089],{},[21,1082,1084],{"href":1083},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fzero-downtime-deploys-with-symlink-swaps\u002F","Zero-Downtime Deploys with Symlink Swaps"," — the ",[239,1087,1088],{},"current"," directories each site serves.",[1091,1092,1093],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .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":237,"searchDepth":269,"depth":269,"links":1095},[1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1114],{"id":39,"depth":269,"text":40},{"id":56,"depth":269,"text":57},{"id":226,"depth":269,"text":227},{"id":311,"depth":269,"text":312},{"id":461,"depth":269,"text":462},{"id":514,"depth":269,"text":515},{"id":726,"depth":269,"text":727},{"id":737,"depth":269,"text":738},{"id":749,"depth":269,"text":750},{"id":762,"depth":269,"text":763},{"id":972,"depth":269,"text":973},{"id":1009,"depth":269,"text":1010},{"id":1016,"depth":269,"text":1017,"children":1109},[1110,1111,1112,1113],{"id":1021,"depth":286,"text":1022},{"id":1028,"depth":286,"text":1029},{"id":1035,"depth":286,"text":1036},{"id":1042,"depth":286,"text":1043},{"id":1049,"depth":269,"text":1050},[1116,1119,1122,1123],{"name":1117,"item":1118},"Home","\u002F",{"name":1120,"item":1121},"Production-Ready Deployment & CI\u002FCD for SSGs","\u002Fproduction-ready-deployment-cicd-workflows\u002F",{"name":24,"item":23},{"name":5,"item":1124},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https\u002F","2026-10-02","Run several static sites on one Caddy server with automatic certificates: DNS and ports, staging CA tests, rate limits, storage and wildcards.","md",[1129,1130,1131,1132],{"q":1022,"a":1025},{"q":1029,"a":1032},{"q":1036,"a":1039},{"q":1043,"a":1046},{},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https",{"title":5,"description":1126},"production-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy-and-automatic-https\u002Findex","article","mBghZUfkpZ8AaJvaPwaa7nTl4cSUGmpPd750jlCGqgw",[1140,1143,1146,1149,1152,1155,1158,1161,1164,1167,1170,1173,1176,1179,1182,1185,1188,1191,1194,1197,1200,1203,1206,1209,1212,1215,1218,1221,1224,1227,1230,1233,1236,1239,1242,1245,1248,1251,1254,1257,1260,1263,1266,1269,1272,1275,1278,1281,1284,1287,1290,1293,1296,1299,1302,1305,1308,1311,1314,1317,1320,1323,1326,1329,1332,1335,1338,1341,1344,1347,1350,1353,1356,1359,1362,1365,1368,1371,1374,1377,1380,1383,1386,1389,1392,1395,1398,1401,1404,1407,1410,1413,1416,1419,1422,1425,1428,1431,1434,1437,1440,1443,1446,1449,1452,1455,1458,1461,1464,1467,1470,1473,1476,1479,1482,1485,1488,1491,1494,1497,1500,1503,1506,1509,1512,1515,1518,1521,1524,1527,1530,1533,1536,1539,1542,1545,1548,1551,1554,1557,1560,1563,1566,1569,1572,1575,1578,1581,1584,1587,1590,1593,1596,1599,1602,1605,1608,1611,1614,1617,1620,1623,1626,1629,1632,1635,1638,1641,1644,1647,1650,1653,1656,1659,1662,1665,1668,1671,1674,1677,1680,1683,1686,1689,1692,1695,1698,1701,1704,1707,1710,1713,1716,1719,1722,1725,1728,1731,1734,1737,1740,1743,1746,1749,1752,1755,1758,1761,1764,1767,1770,1773,1776,1779,1782,1785,1788,1791,1794,1797,1800,1803,1806,1809,1812,1815,1818,1821,1824,1827,1830,1833,1836,1839,1842,1845,1848,1851,1854,1857,1860,1863,1866,1869,1872,1875,1878,1881,1884,1887,1890,1893,1896,1899,1902,1905,1908,1911,1914,1917,1920,1923,1926,1929,1932,1935,1938,1941,1944,1947,1950,1953,1956,1959,1962,1965,1968,1971,1974,1977,1980,1983,1986,1989,1992,1995,1998,2001,2004,2007,2010,2013,2016,2018,2021,2024,2027,2030,2033,2036,2038,2041,2044,2047,2050,2053,2056,2059,2062,2065,2068,2071,2074,2077,2080,2083,2086,2089,2092,2095,2098,2100,2103,2106,2109,2112,2115,2118,2121,2124,2127,2130,2133,2136,2139,2142,2145,2148,2151,2154,2157,2160,2163,2166,2169,2172,2175,2178,2180,2183,2186,2189,2192,2195,2198,2201,2204,2207,2209,2211,2214,2215,2217,2220,2223,2225,2228,2231,2234,2237,2240,2243,2246,2249,2252,2255,2258,2261,2264,2267,2270,2273,2276],{"path":1141,"title":1142},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Faccessible-code-blocks-in-documentation-sites","Accessible Code Blocks in Documentation Sites",{"path":1144,"title":1145},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Faccessible-dark-mode-toggles-for-static-sites","Accessible Dark Mode Toggles for Static Sites",{"path":1147,"title":1148},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Faccessible-svg-diagrams-on-static-sites","Accessible SVG Diagrams on Static Sites",{"path":1150,"title":1151},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Fenforcing-alt-text-for-markdown-images-at-build-time","Enforcing Alt Text for Markdown Images at Build Time",{"path":1153,"title":1154},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Ffixing-heading-order-problems-in-markdown-content","Fixing Heading Order Problems in Markdown Content",{"path":1156,"title":1157},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Ffixing-low-color-contrast-flagged-by-lighthouse","Fixing Low Color Contrast Flagged by Lighthouse",{"path":1159,"title":1160},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites","Accessibility for Static Sites",{"path":1162,"title":1163},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Fkeyboard-navigation-and-focus-order-on-static-sites","Keyboard Navigation and Focus Order on Static Sites",{"path":1165,"title":1166},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Faccessibility-for-static-sites\u002Fskip-links-and-landmarks-in-ssg-layouts","Skip Links and Landmarks in SSG Layouts",{"path":1168,"title":1169},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fastro-vs-eleventy-build-times-at-10000-pages","Astro vs Eleventy Build Times at 10,000 Pages",{"path":1171,"title":1172},"\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":1174,"title":1175},"\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":1177,"title":1178},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fdev-server-performance-astro-vs-eleventy","Dev Server Performance: Astro vs Eleventy",{"path":1180,"title":1181},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Ffixing-astro-build-errors-after-upgrading-to-astro-5","Fixing Astro Build Errors After Upgrading to Astro 5",{"path":1183,"title":1184},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Ffixing-duplicate-permalink-errors-in-eleventy","Fixing Duplicate Permalink Errors in Eleventy",{"path":1186,"title":1187},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Ffixing-eleventy-out-of-memory-errors-on-large-collections","Fixing Eleventy Out-of-Memory Errors on Large Collections",{"path":1189,"title":1190},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Ffixing-slow-astro-builds-caused-by-large-mdx-collections","Fixing Slow Astro Builds Caused by Large MDX Collections",{"path":1192,"title":1193},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":1195,"title":1196},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Floading-remote-content-with-astro-content-layer-loaders","Loading Remote Content With Astro Content Layer Loaders",{"path":1198,"title":1199},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fmarkdown-pipelines-remark-vs-markdown-it","Markdown Pipelines: remark vs markdown-it",{"path":1201,"title":1202},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fshortcodes-vs-components-for-docs-authors","Shortcodes vs Components for Docs Authors",{"path":1204,"title":1205},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fsidebar-navigation-in-astro-and-eleventy","Sidebar Navigation in Astro and Eleventy",{"path":1207,"title":1208},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fsyntax-highlighting-with-shiki-in-astro-and-eleventy","Syntax Highlighting with Shiki in Astro and Eleventy",{"path":1210,"title":1211},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fupgrading-eleventy-2-to-3-with-esm-configuration","Upgrading Eleventy 2 to 3 With ESM Configuration",{"path":1213,"title":1214},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fadding-local-search-to-a-vitepress-site","Adding Local Search to a VitePress Site",{"path":1216,"title":1217},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcomparing-docs-framework-build-times","Comparing Docs Framework Build Times",{"path":1219,"title":1220},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcustomizing-starlight-without-forking-the-theme","Customizing Starlight Without Forking the Theme",{"path":1222,"title":1223},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fdocusaurus-vs-starlight-for-product-documentation","Docusaurus vs Starlight for Product Documentation",{"path":1225,"title":1226},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Ffixing-broken-links-reported-by-docusaurus-builds","Fixing Broken Links Reported by Docusaurus Builds",{"path":1228,"title":1229},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fgenerating-api-reference-pages-in-starlight-from-openapi","Generating API Reference Pages in Starlight From OpenAPI",{"path":1231,"title":1232},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress","Docs Frameworks: Docusaurus, Starlight and VitePress",{"path":1234,"title":1235},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Finternationalizing-starlight-docs","Internationalizing Starlight Docs",{"path":1237,"title":1238},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmdx-vs-markdoc-for-docs-content","MDX vs Markdoc for Docs Content",{"path":1240,"title":1241},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-from-mkdocs-to-starlight","Migrating from MkDocs to Starlight",{"path":1243,"title":1244},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-mkdocs-documentation-to-vitepress","Migrating MkDocs Documentation to VitePress",{"path":1246,"title":1247},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fspeeding-up-docusaurus-builds-with-rspack","Speeding Up Docusaurus Builds With Rspack",{"path":1249,"title":1250},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioned-documentation-with-docusaurus","Versioned Documentation with Docusaurus",{"path":1252,"title":1253},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioning-vitepress-documentation-without-a-plugin","Versioning VitePress Documentation Without a Plugin",{"path":1255,"title":1256},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-for-library-documentation","VitePress for Library Documentation",{"path":1258,"title":1259},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-vs-starlight-for-vue-and-astro-teams","VitePress vs Starlight for Vue and Astro Teams",{"path":1261,"title":1262},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Ffixing-hugo-builds-that-fail-after-a-version-upgrade","Fixing Hugo Builds That Fail After a Version Upgrade",{"path":1264,"title":1265},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Ffixing-hugo-builds-that-slow-down-after-adding-taxonomies","Fixing Hugo Builds That Slow Down After Adding Taxonomies",{"path":1267,"title":1268},"\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":1270,"title":1271},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-image-processing-cache-in-ci","Hugo Image Processing Cache in CI",{"path":1273,"title":1274},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-modules-and-dependency-caching","Hugo Modules and Dependency Caching",{"path":1276,"title":1277},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-partialcached-for-faster-builds","Hugo partialCached for Faster Builds",{"path":1279,"title":1280},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":1282,"title":1283},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fparallel-hugo-builds-across-ci-jobs","Parallel Hugo Builds Across CI Jobs",{"path":1285,"title":1286},"\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":1288,"title":1289},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Freducing-hugo-memory-usage-on-ci-runners","Reducing Hugo Memory Usage on CI Runners",{"path":1291,"title":1292},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fsharing-a-theme-across-hugo-sites-with-modules","Sharing a Theme Across Hugo Sites With Modules",{"path":1294,"title":1295},"\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":1297,"title":1298},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fsplitting-large-hugo-sites-with-segments","Splitting Large Hugo Sites with Segments",{"path":1300,"title":1301},"\u002Fchoosing-the-right-static-site-generator-for-production","Choosing the Right Static Site Generator for Production",{"path":1303,"title":1304},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Ffixing-hreflang-errors-reported-in-search-console","Fixing Hreflang Errors Reported in Search Console",{"path":1306,"title":1307},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fhreflang-and-language-alternates-on-static-sites","hreflang and Language Alternates on Static Sites",{"path":1309,"title":1310},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fi18n-routing-in-astro","i18n Routing in Astro",{"path":1312,"title":1313},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites","Internationalization for Static Sites",{"path":1315,"title":1316},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Flanguage-detection-and-redirects-at-the-edge","Language Detection and Redirects at the Edge",{"path":1318,"title":1319},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fmultilingual-eleventy-sites-with-the-i18n-plugin","Multilingual Eleventy Sites With the i18n Plugin",{"path":1321,"title":1322},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fmultilingual-sites-with-hugo","Multilingual Sites with Hugo",{"path":1324,"title":1325},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fright-to-left-layouts-on-static-sites","Right-to-Left Layouts on Static Sites",{"path":1327,"title":1328},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Fsubdirectories-vs-subdomains-for-translated-static-sites","Subdirectories vs Subdomains for Translated Static Sites",{"path":1330,"title":1331},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Finternationalization-for-static-sites\u002Ftranslation-workflows-with-git-and-crowdin","Translation Workflows with Git and Crowdin",{"path":1333,"title":1334},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fcustom-domains-and-https-for-jekyll-on-github-pages","Custom Domains and HTTPS for Jekyll on GitHub Pages",{"path":1336,"title":1337},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fdeploying-jekyll-with-github-actions","Deploying Jekyll with GitHub Actions",{"path":1339,"title":1340},"\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":1342,"title":1343},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Ffixing-jekyll-builds-that-break-after-a-ruby-upgrade","Fixing Jekyll Builds That Break After a Ruby Upgrade",{"path":1345,"title":1346},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":1348,"title":1349},"\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":1351,"title":1352},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Frunning-jekyll-in-docker-for-reproducible-builds","Running Jekyll in Docker for Reproducible Builds",{"path":1354,"title":1355},"\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":1357,"title":1358},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds","Speeding Up Slow Jekyll Builds",{"path":1360,"title":1361},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fupgrading-jekyll-and-ruby-versions-safely","Upgrading Jekyll and Ruby Versions Safely",{"path":1363,"title":1364},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fauditing-content-parity-after-a-migration","Auditing Content Parity After a Migration",{"path":1366,"title":1367},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fconverting-front-matter-at-scale-during-migration","Converting Front Matter at Scale During Migration",{"path":1369,"title":1370},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1372,"title":1373},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration","Keeping Redirects Working After an SSG Migration",{"path":1375,"title":1376},"\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":1378,"title":1379},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-wordpress-export-to-eleventy","Migrating a WordPress Export to Eleventy",{"path":1381,"title":1382},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-docusaurus-to-starlight","Migrating from Docusaurus to Starlight",{"path":1384,"title":1385},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-gatsby-to-astro","Migrating from Gatsby to Astro",{"path":1387,"title":1388},"\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":1390,"title":1391},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-nextjs-pages-router-to-astro","Migrating from Next.js Pages Router to Astro",{"path":1393,"title":1394},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-wordpress-to-a-static-site-generator","Migrating WordPress to a Static Site Generator",{"path":1396,"title":1397},"\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":1399,"title":1400},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Frecovering-search-traffic-lost-after-a-generator-migration","Recovering Search Traffic Lost After a Generator Migration",{"path":1402,"title":1403},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Freplacing-gatsby-graphql-queries-during-a-migration","Replacing Gatsby GraphQL Queries During a Migration",{"path":1405,"title":1406},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Ffixing-404s-on-refresh-in-nextjs-static-export","Fixing 404s on Refresh in Next.js Static Export",{"path":1408,"title":1409},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fgenerating-sitemaps-and-rss-in-nextjs-static-export","Generating Sitemaps and RSS in Next.js Static Export",{"path":1411,"title":1412},"\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":1414,"title":1415},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":1417,"title":1418},"\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":1420,"title":1421},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations","Next.js App Router Static Export Limitations",{"path":1423,"title":1424},"\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":1426,"title":1427},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-static-export-vs-gatsby-for-existing-react-sites","Next.js Static Export vs Gatsby for Existing React Sites",{"path":1429,"title":1430},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Foptimizing-images-in-nextjs-static-export","Optimizing Images in Next.js Static Export",{"path":1432,"title":1433},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Ftrailing-slash-and-basepath-in-nextjs-static-export","Trailing Slash and basePath in Next.js Static Export",{"path":1435,"title":1436},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fusing-mdx-in-nextjs-static-export","Using MDX in Next.js Static Export",{"path":1438,"title":1439},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Faccessible-search-ui-for-static-sites","Accessible Search UI for Static Sites",{"path":1441,"title":1442},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fadding-pagefind-to-an-astro-site","Adding Pagefind to an Astro Site",{"path":1444,"title":1445},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fbuilding-a-lunr-index-at-build-time-in-eleventy","Building a Lunr Index at Build Time in Eleventy",{"path":1447,"title":1448},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fcustomizing-the-pagefind-ui","Customizing the Pagefind UI",{"path":1450,"title":1451},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Ffixing-missing-results-in-pagefind-indexes","Fixing Missing Results in Pagefind Indexes",{"path":1453,"title":1454},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites","Search for Static Sites",{"path":1456,"title":1457},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Findexing-hugo-sites-with-pagefind","Indexing Hugo Sites with Pagefind",{"path":1459,"title":1460},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fmultilingual-search-on-static-sites","Multilingual Search on Static Sites",{"path":1462,"title":1463},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-algolia-docsearch","Pagefind vs Algolia DocSearch",{"path":1465,"title":1466},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-lunr-for-small-documentation-sites","Pagefind vs Lunr for Small Documentation Sites",{"path":1468,"title":1469},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fsearch-index-size-budgets-for-large-docs","Search Index Size Budgets for Large Docs",{"path":1471,"title":1472},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fself-hosting-typesense-for-a-static-site","Self-Hosting Typesense for a Static Site",{"path":1474,"title":1475},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Ftracking-zero-result-searches","Tracking Zero-Result Searches",{"path":1477,"title":1478},"\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":1480,"title":1481},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-a-marketing-site-with-non-technical-editors","Choosing an SSG for a Marketing Site with Non-Technical Editors",{"path":1483,"title":1484},"\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":1486,"title":1487},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fevaluating-ssg-accessibility-defaults","Evaluating SSG Accessibility Defaults",{"path":1489,"title":1490},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fgatsby-vs-astro-for-content-sites-in-2026","Gatsby vs Astro for Content Sites in 2026",{"path":1492,"title":1493},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":1495,"title":1496},"\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":1498,"title":1499},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fscoring-ssg-long-term-maintenance-risk","Scoring SSG Long-Term Maintenance Risk",{"path":1501,"title":1502},"\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":1504,"title":1505},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Ftotal-cost-of-ownership-for-static-site-generators","Total Cost of Ownership for Static Site Generators",{"path":1507,"title":1508},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fwhen-a-static-site-generator-is-the-wrong-choice","When a Static Site Generator Is the Wrong Choice",{"path":1510,"title":1511},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Fadding-json-ld-structured-data-at-build-time","Adding JSON-LD Structured Data at Build Time",{"path":1513,"title":1514},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Fcanonical-urls-and-duplicate-content-on-static-sites","Canonical URLs and Duplicate Content on Static Sites",{"path":1516,"title":1517},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Ffixing-pages-crawled-but-not-indexed-on-static-sites","Fixing Pages Crawled but Not Indexed on Static Sites",{"path":1519,"title":1520},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Ffixing-soft-404s-on-static-hosts","Fixing Soft 404s on Static Hosts",{"path":1522,"title":1523},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Fgenerating-breadcrumb-structured-data-in-astro","Generating Breadcrumb Structured Data in Astro",{"path":1525,"title":1526},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Fgenerating-sitemaps-for-large-static-sites","Generating Sitemaps for Large Static Sites",{"path":1528,"title":1529},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites","Technical SEO for Static Sites",{"path":1531,"title":1532},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Frobots-txt-and-noindex-for-preview-and-staging","robots.txt and noindex for Preview and Staging",{"path":1534,"title":1535},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Frss-and-atom-feeds-for-static-blogs","RSS and Atom Feeds for Static Blogs",{"path":1537,"title":1538},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Ftechnical-seo-for-static-sites\u002Fseo-safe-pagination-and-tag-pages","SEO-Safe Pagination and Tag Pages",{"path":1540,"title":1541},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-busting-with-content-hashed-filenames","Cache Busting with Content-Hashed Filenames",{"path":1543,"title":1544},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-control-headers-for-static-sites-in-nginx","Cache-Control Headers for Static Sites in Nginx",{"path":1546,"title":1547},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-control-headers-on-s3-and-cloudfront","Cache-Control Headers on S3 and CloudFront",{"path":1549,"title":1550},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-control-headers-on-vercel-for-static-sites","Cache-Control Headers on Vercel for Static Sites",{"path":1552,"title":1553},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-keys-and-query-strings-on-cdns","Cache Keys and Query Strings on CDNs",{"path":1555,"title":1556},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcaching-404s-and-redirects-at-the-edge","Caching 404s and Redirects at the Edge",{"path":1558,"title":1559},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcloudflare-vs-cloudfront-cache-hit-ratios-for-static-sites","Cloudflare vs CloudFront Cache Hit Ratios for Static Sites",{"path":1561,"title":1562},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Ffixing-stale-html-after-deploys-on-cloudflare","Fixing Stale HTML After Deploys on Cloudflare",{"path":1564,"title":1565},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":1567,"title":1568},"\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":1570,"title":1571},"\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":1573,"title":1574},"\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":1576,"title":1577},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fstale-while-revalidate-for-static-html","Stale-While-Revalidate for Static HTML",{"path":1579,"title":1580},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Ftiered-caching-and-origin-shield","Tiered Caching and Origin Shield",{"path":1582,"title":1583},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fcode-splitting-and-module-preload-in-vite-based-ssgs","Code Splitting and Module Preload in Vite-Based SSGs",{"path":1585,"title":1586},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Ffixing-missing-tailwind-classes-in-production-builds","Fixing Missing Tailwind Classes in Production Builds",{"path":1588,"title":1589},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Ffixing-unused-javascript-warnings-on-static-pages","Fixing Unused JavaScript Warnings on Static Pages",{"path":1591,"title":1592},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization","CSS and JavaScript Asset Optimization",{"path":1594,"title":1595},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Finlining-critical-css-on-static-sites","Inlining Critical CSS on Static Sites",{"path":1597,"title":1598},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fkeeping-tailwind-css-output-small-on-static-sites","Keeping Tailwind CSS Output Small on Static Sites",{"path":1600,"title":1601},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fminifying-html-css-and-js-in-eleventy","Minifying HTML, CSS and JS in Eleventy",{"path":1603,"title":1604},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fprecompressing-assets-with-brotli-and-zstd","Precompressing Assets with Brotli and Zstd",{"path":1606,"title":1607},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fpurging-unused-css-with-tailwind-and-lightningcss","Purging Unused CSS with Tailwind and Lightning CSS",{"path":1609,"title":1610},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Fsvg-icon-sprites-vs-inline-icons","SVG Icon Sprites vs Inline Icons",{"path":1612,"title":1613},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcss-and-javascript-asset-optimization\u002Ftailwind-v4-in-astro-without-postcss-plugins","Tailwind v4 in Astro Without PostCSS Plugins",{"path":1615,"title":1616},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Fcls-from-client-side-rendered-components","CLS from Client-Side Rendered Components",{"path":1618,"title":1619},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Fdebugging-cls-with-the-layout-instability-api","Debugging CLS with the Layout Instability API",{"path":1621,"title":1622},"\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":1624,"title":1625},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-cookie-banners","Fixing CLS from Cookie Banners",{"path":1627,"title":1628},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-dynamic-table-of-contents-widgets","Fixing CLS From Dynamic Table of Contents Widgets",{"path":1630,"title":1631},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-images-without-dimensions-in-markdown","Fixing CLS From Images Without Dimensions in Markdown",{"path":1633,"title":1634},"\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":1636,"title":1637},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-sticky-headers-and-anchor-links","Fixing CLS from Sticky Headers and Anchor Links",{"path":1639,"title":1640},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1642,"title":1643},"\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":1645,"title":1646},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-ad-and-promo-slots","Reserving Space for Ad and Promo Slots",{"path":1648,"title":1649},"\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":1651,"title":1652},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fauditing-font-payload-per-page","Auditing Font Payload per Page",{"path":1654,"title":1655},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Ffixing-invisible-text-while-web-fonts-load","Fixing Invisible Text While Web Fonts Load",{"path":1657,"title":1658},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Ffont-display-optional-vs-swap","font-display: optional vs swap",{"path":1660,"title":1661},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1663,"title":1664},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fmetric-matched-fallback-fonts-with-size-adjust","Metric-Matched Fallback Fonts with size-adjust",{"path":1666,"title":1667},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fpreloading-fonts-without-double-downloads","Preloading Fonts Without Double Downloads",{"path":1669,"title":1670},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fself-hosted-fonts-vs-google-fonts-for-static-sites","Self-Hosted Fonts vs Google Fonts for Static Sites",{"path":1672,"title":1673},"\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":1675,"title":1676},"\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":1678,"title":1679},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fusing-system-font-stacks-to-skip-webfonts","Using System Font Stacks to Skip Web Fonts",{"path":1681,"title":1682},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fvariable-fonts-vs-static-weights","Variable Fonts vs Static Weights",{"path":1684,"title":1685},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fart-direction-with-the-picture-element","Art Direction with the Picture Element",{"path":1687,"title":1688},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fblur-up-placeholders-with-lqip","Blur-Up Placeholders with LQIP",{"path":1690,"title":1691},"\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":1693,"title":1694},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fcaching-processed-images-between-builds","Caching Processed Images Between Builds",{"path":1696,"title":1697},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Ffixing-blurry-images-from-astro-assets-resizing","Fixing Blurry Images From astro:assets Resizing",{"path":1699,"title":1700},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fgenerating-open-graph-images-at-build-time","Generating Open Graph Images at Build Time",{"path":1702,"title":1703},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1705,"title":1706},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Flazy-loading-images-without-hurting-lcp","Lazy-Loading Images Without Hurting LCP",{"path":1708,"title":1709},"\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":1711,"title":1712},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fresponsive-images-with-srcset-in-eleventy","Responsive Images with srcset in Eleventy",{"path":1714,"title":1715},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fserving-astro-images-through-cloudflare-image-resizing","Serving Astro Images Through Cloudflare Image Resizing",{"path":1717,"title":1718},"\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":1720,"title":1721},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1723,"title":1724},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":1726,"title":1727},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fbreaking-up-long-tasks-on-static-sites","Breaking Up Long Tasks on Static Sites",{"path":1729,"title":1730},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fdeferring-hydration-with-client-visible-in-astro","Deferring Hydration with client:visible in Astro",{"path":1732,"title":1733},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Ffixing-hydration-mismatch-errors-in-astro-islands","Fixing Hydration Mismatch Errors in Astro Islands",{"path":1735,"title":1736},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Ffixing-poor-inp-on-static-pages-with-heavy-widgets","Fixing Poor INP on Static Pages With Heavy Widgets",{"path":1738,"title":1739},"\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":1741,"title":1742},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1744,"title":1745},"\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":1747,"title":1748},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fpreact-vs-react-islands-bundle-size","Preact vs React Islands Bundle Size",{"path":1750,"title":1751},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Freplacing-react-islands-with-web-components","Replacing React Islands with Web Components",{"path":1753,"title":1754},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fserver-islands-in-astro","Server Islands in Astro",{"path":1756,"title":1757},"\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":1759,"title":1760},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-lcp-on-text-heavy-documentation-pages","Fixing LCP on Text-Heavy Documentation Pages",{"path":1762,"title":1763},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-lcp-regressions-caused-by-cookie-consent-tools","Fixing LCP Regressions Caused by Cookie Consent Tools",{"path":1765,"title":1766},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-lcp-when-the-hero-is-a-background-image","Fixing LCP When the Hero Is a Background Image",{"path":1768,"title":1769},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-slow-lcp-on-pages-with-embedded-video","Fixing Slow LCP on Pages With Embedded Video",{"path":1771,"title":1772},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Fimproving-ttfb-for-static-html","Improving TTFB for Static HTML",{"path":1774,"title":1775},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1777,"title":1778},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Fmeasuring-lcp-subparts-with-devtools","Measuring LCP Subparts with DevTools",{"path":1780,"title":1781},"\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":1783,"title":1784},"\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":1786,"title":1787},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fcomparing-lab-and-field-data-with-crux","Comparing Lab and Field Data with CrUX",{"path":1789,"title":1790},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci","Performance Budgets and Lighthouse CI",{"path":1792,"title":1793},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Flighthouse-ci-vs-webpagetest-for-regression-gates","Lighthouse CI vs WebPageTest for Regression Gates",{"path":1795,"title":1796},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fmeasuring-web-vitals-in-playwright-tests","Measuring Web Vitals in Playwright Tests",{"path":1798,"title":1799},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fper-template-performance-budgets","Per-Template Performance Budgets",{"path":1801,"title":1802},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fperformance-testing-on-throttled-mobile-profiles","Performance Testing on Throttled Mobile Profiles",{"path":1804,"title":1805},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Freducing-lighthouse-score-variance-in-ci","Reducing Lighthouse Score Variance in CI",{"path":1807,"title":1808},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Frunning-webpagetest-scripts-against-preview-deploys","Running WebPageTest Scripts Against Preview Deploys",{"path":1810,"title":1811},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fsetting-up-lighthouse-ci-for-a-static-site","Setting Up Lighthouse CI for a Static Site",{"path":1813,"title":1814},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Ftracking-bundle-size-per-pull-request","Tracking Bundle Size per Pull Request",{"path":1816,"title":1817},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Ftracking-page-weight-over-time","Tracking Page Weight Over Time",{"path":1819,"title":1820},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fwriting-a-performance-budget-that-fails-builds","Writing a Performance Budget That Fails Builds",{"path":1822,"title":1823},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fauditing-unused-preloads","Auditing Unused Preloads",{"path":1825,"title":1826},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fearly-hints-103-on-cloudflare","Early Hints (103) on Cloudflare",{"path":1828,"title":1829},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Ffetchpriority-beyond-the-hero-image","Fetchpriority Beyond the Hero Image",{"path":1831,"title":1832},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Ffixing-wasted-preloads-flagged-by-chrome","Fixing Wasted Preloads Flagged by Chrome",{"path":1834,"title":1835},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed","Resource Hints and Navigation Speed",{"path":1837,"title":1838},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Finstant-navigation-with-speculation-rules","Instant Navigation with Speculation Rules",{"path":1840,"title":1841},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fpreconnect-vs-dns-prefetch-on-static-sites","Preconnect vs DNS-Prefetch on Static Sites",{"path":1843,"title":1844},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fprefetching-links-in-astro","Prefetching Links in Astro",{"path":1846,"title":1847},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fview-transitions-in-astro-without-hurting-vitals","View Transitions in Astro Without Hurting Vitals",{"path":1849,"title":1850},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fview-transitions-on-multi-page-static-sites","View Transitions on Multi-Page Static Sites",{"path":1852,"title":1853},"\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":1855,"title":1856},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Ffacades-for-chat-widgets-and-maps","Facades for Chat Widgets and Maps",{"path":1858,"title":1859},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Ffixing-main-thread-blocking-from-chat-widgets","Fixing Main-Thread Blocking From Chat Widgets",{"path":1861,"title":1862},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1864,"title":1865},"\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":1867,"title":1868},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Floading-google-tag-manager-without-hurting-inp","Loading Google Tag Manager Without Hurting INP",{"path":1870,"title":1871},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fmeasuring-third-party-cost-with-request-blocking","Measuring Third-Party Cost with Request Blocking",{"path":1873,"title":1874},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fprivacy-friendly-analytics-compared-by-page-weight","Privacy-Friendly Analytics Compared by Page Weight",{"path":1876,"title":1877},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Frunning-third-party-scripts-in-a-web-worker-with-partytown","Running Third-Party Scripts in a Web Worker with Partytown",{"path":1879,"title":1880},"\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":1882,"title":1883},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":1885,"title":1886},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fbranch-deploy-controls-on-cloudflare-pages","Branch Deploy Controls on Cloudflare Pages",{"path":1888,"title":1889},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fcloudflare-pages-functions-middleware","Cloudflare Pages Functions Middleware",{"path":1891,"title":1892},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fconfiguring-redirects-on-cloudflare-pages","Configuring Redirects on Cloudflare Pages",{"path":1894,"title":1895},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fcustom-domains-and-tls-on-cloudflare-pages","Custom Domains and TLS on Cloudflare Pages",{"path":1897,"title":1898},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fdeploying-astro-to-cloudflare-workers-static-assets","Deploying Astro to Cloudflare Workers Static Assets",{"path":1900,"title":1901},"\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":1903,"title":1904},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fdeploying-to-cloudflare-from-github-actions-with-wrangler","Deploying to Cloudflare From GitHub Actions With Wrangler",{"path":1906,"title":1907},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Ffixing-redirect-loops-on-cloudflare-pages","Fixing Redirect Loops on Cloudflare Pages",{"path":1909,"title":1910},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":1912,"title":1913},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fmigrating-from-cloudflare-pages-to-workers-static-assets","Migrating from Cloudflare Pages to Workers Static Assets",{"path":1915,"title":1916},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fchecking-links-in-pull-requests","Checking Links in Pull Requests",{"path":1918,"title":1919},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fcontent-linting-with-markdownlint","Content Linting with markdownlint",{"path":1921,"title":1922},"\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":1924,"title":1925},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Feditorial-checks-with-vale-in-ci","Editorial Checks with Vale in CI",{"path":1927,"title":1928},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fgit-based-cms-options-for-static-sites-compared","Git-Based CMS Options for Static Sites Compared",{"path":1930,"title":1931},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":1933,"title":1934},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fmanaging-images-in-docs-as-code-repos","Managing Images in Docs-as-Code Repos",{"path":1936,"title":1937},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Frelease-notes-and-changelogs-from-git","Release Notes and Changelogs from Git",{"path":1939,"title":1940},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fscheduled-content-publishing-with-github-actions","Scheduled Content Publishing With GitHub Actions",{"path":1942,"title":1943},"\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":1945,"title":1946},"\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":1948,"title":1949},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fbuilding-astro-sites-with-github-actions","Building Astro Sites with GitHub Actions",{"path":1951,"title":1952},"\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":1954,"title":1955},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fconcurrency-groups-to-cancel-stale-builds","Concurrency Groups to Cancel Stale Builds",{"path":1957,"title":1958},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-github-pages-with-actions","Deploying to GitHub Pages with Actions",{"path":1960,"title":1961},"\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":1963,"title":1964},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Ffixing-flaky-static-site-builds-in-github-actions","Fixing Flaky Static Site Builds in GitHub Actions",{"path":1966,"title":1967},"\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":1969,"title":1970},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1972,"title":1973},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fmatrix-builds-for-multi-site-monorepos","Matrix Builds for Multi-Site Monorepos",{"path":1975,"title":1976},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fpinning-actions-by-commit-sha","Pinning Actions by Commit SHA",{"path":1978,"title":1979},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fpublishing-any-generator-to-github-pages-with-actions","Publishing Any Generator to GitHub Pages With Actions",{"path":1981,"title":1982},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Freusable-workflows-for-ssg-builds","Reusable Workflows for SSG Builds",{"path":1984,"title":1985},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fbuild-caching-on-netlify-and-vercel","Build Caching on Netlify and Vercel",{"path":1987,"title":1988},"\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":1990,"title":1991},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fdeploying-only-changed-files","Deploying Only Changed Files",{"path":1993,"title":1994},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":1996,"title":1997},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Ffixing-stale-pages-from-incremental-builds","Fixing Stale Pages From Incremental Builds",{"path":1999,"title":2000},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fincremental-builds-in-astro-with-the-content-layer","Incremental Builds in Astro with the Content Layer",{"path":2002,"title":2003},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fincremental-rebuild-times-across-astro-eleventy-and-hugo","Incremental Rebuild Times Across Astro, Eleventy and Hugo",{"path":2005,"title":2006},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":2008,"title":2009},"\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":2011,"title":2012},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fremote-caching-with-turborepo-for-ssg-monorepos","Remote Caching with Turborepo for SSG Monorepos",{"path":2014,"title":2015},"\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":2017,"title":1120},"\u002Fproduction-ready-deployment-cicd-workflows",{"path":2019,"title":2020},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Falerting-on-cache-hit-ratio-drops","Alerting on Cache Hit Ratio Drops",{"path":2022,"title":2023},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fbuilding-a-core-web-vitals-dashboard-from-rum-data","Building a Core Web Vitals Dashboard from RUM Data",{"path":2025,"title":2026},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fcrawling-for-broken-links-on-a-schedule","Crawling for Broken Links on a Schedule",{"path":2028,"title":2029},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Ffinding-the-cause-of-a-sudden-field-lcp-drop","Finding the Cause of a Sudden Field LCP Drop",{"path":2031,"title":2032},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production","Monitoring Static Sites in Production",{"path":2034,"title":2035},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Flogging-404s-at-the-edge","Logging 404s at the Edge",{"path":2037,"title":745},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fmonitoring-tls-certificate-expiry",{"path":2039,"title":2040},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Freal-user-error-tracking-on-static-sites","Real-User Error Tracking on Static Sites",{"path":2042,"title":2043},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fsynthetic-monitoring-with-scheduled-playwright-checks","Synthetic Monitoring With Scheduled Playwright Checks",{"path":2045,"title":2046},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Ftracking-deploy-markers-in-analytics","Tracking Deploy Markers in Analytics",{"path":2048,"title":2049},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fuptime-and-synthetic-checks-for-static-sites","Uptime and Synthetic Checks for Static Sites",{"path":2051,"title":2052},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fbandwidth-pricing-for-static-sites-across-netlify-vercel-and-cloudflare","Static Site Bandwidth Pricing: Netlify, Vercel, Cloudflare",{"path":2054,"title":2055},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fconfiguring-redirects-on-vercel-for-static-sites","Configuring Redirects on Vercel for Static Sites",{"path":2057,"title":2058},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fconfiguring-vercel-for-hugo-and-eleventy","Configuring Vercel for Hugo and Eleventy",{"path":2060,"title":2061},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fdeploying-astro-to-vercel-as-a-fully-static-site","Deploying Astro to Vercel as a Fully Static Site",{"path":2063,"title":2064},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Ffixing-netlify-builds-that-exceed-the-time-limit","Fixing Netlify Builds That Exceed the Time Limit",{"path":2066,"title":2067},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Ffixing-vercel-builds-that-run-out-of-memory","Fixing Vercel Builds That Run Out of Memory",{"path":2069,"title":2070},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":2072,"title":2073},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":2075,"title":2076},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-edge-functions-for-static-sites","Netlify Edge Functions for Static Sites",{"path":2078,"title":2079},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-redirects-and-rewrites-for-static-sites","Netlify Redirects and Rewrites for Static Sites",{"path":2081,"title":2082},"\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":2084,"title":2085},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-build-output-api-for-custom-ssgs","Vercel Build Output API for Custom SSGs",{"path":2087,"title":2088},"\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":2090,"title":2091},"\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":2093,"title":2094},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":2096,"title":2097},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcommenting-on-preview-deploys","Commenting on Preview Deploys",{"path":2099,"title":596},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Ffixing-preview-deploys-leaking-into-search-results",{"path":2101,"title":2102},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":2104,"title":2105},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpassword-protecting-preview-deployments","Password-Protecting Preview Deployments",{"path":2107,"title":2108},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpreview-deploys-for-monorepos","Preview Deploys for Monorepos",{"path":2110,"title":2111},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpreviewing-headless-cms-drafts","Previewing Headless CMS Drafts",{"path":2113,"title":2114},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpull-request-previews-for-github-pages-sites","Pull Request Previews for GitHub Pages Sites",{"path":2116,"title":2117},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fvisual-regression-testing-on-preview-deploys","Visual Regression Testing on Preview Deploys",{"path":2119,"title":2120},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":2122,"title":2123},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fblue-green-deploys-for-static-sites","Blue-Green Deploys for Static Sites",{"path":2125,"title":2126},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fcanary-releases-for-static-sites","Canary Releases for Static Sites",{"path":2128,"title":2129},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Ffeature-flags-on-static-sites","Feature Flags on Static Sites",{"path":2131,"title":2132},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":2134,"title":2135},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fkeeping-old-assets-alive-after-deploy","Keeping Old Assets Alive After Deploy",{"path":2137,"title":2138},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fpost-deploy-verification-checklists","Post-Deploy Verification Checklists",{"path":2140,"title":2141},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frecovering-from-a-deploy-that-deleted-live-assets","Recovering From a Deploy That Deleted Live Assets",{"path":2143,"title":2144},"\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":2146,"title":2147},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frolling-back-netlify-deploys-from-the-cli-and-api","Rolling Back Netlify Deploys From the CLI and API",{"path":2149,"title":2150},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frolling-back-s3-and-cloudfront-deploys-with-versioned-prefixes","Rolling Back S3 and CloudFront Deploys With Versioned Prefixes",{"path":2152,"title":2153},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url","Running Smoke Tests Against a Preview URL",{"path":2155,"title":2156},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fauditing-npm-dependencies-in-ssg-pipelines","Auditing npm Dependencies in SSG Pipelines",{"path":2158,"title":2159},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fenabling-hsts-and-preload-safely","Enabling HSTS and Preload Safely",{"path":2161,"title":2162},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Ffixing-content-security-policy-violations-from-inline-scripts","Fixing Content Security Policy Violations From Inline Scripts",{"path":2164,"title":2165},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Ffixing-mixed-content-warnings-after-moving-to-https","Fixing Mixed Content Warnings After Moving to HTTPS",{"path":2167,"title":2168},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fhash-based-csp-for-inline-scripts-in-astro","Hash-Based CSP for Inline Scripts in Astro",{"path":2170,"title":2171},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites","Security Headers and Hardening for Static Sites",{"path":2173,"title":2174},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fpermissions-policy-and-cross-origin-headers","Permissions-Policy and Cross-Origin Headers",{"path":2176,"title":2177},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecuring-deploy-credentials-with-github-oidc","Securing Deploy Credentials with GitHub OIDC",{"path":2179,"title":34},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecurity-headers-for-static-sites-served-by-caddy",{"path":2181,"title":2182},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecurity-headers-on-vercel-for-static-sites","Security Headers on Vercel for Static Sites",{"path":2184,"title":2185},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecurity-txt-and-disclosure-for-static-sites","security.txt and Disclosure for Static Sites",{"path":2187,"title":2188},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsubresource-integrity-for-third-party-assets","Subresource Integrity for Third-Party Assets",{"path":2190,"title":2191},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fwriting-a-content-security-policy-for-a-static-site","Writing a Content Security Policy for a Static Site",{"path":2193,"title":2194},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fbrotli-and-gzip-precompression-served-by-nginx","Brotli and Gzip Precompression Served by Nginx",{"path":2196,"title":2197},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3","Clean URLs and Trailing Slashes on S3",{"path":2199,"title":2200},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fcloudfront-functions-for-redirects","CloudFront Functions for Redirects",{"path":2202,"title":2203},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fdeploying-a-static-site-to-s3-and-cloudfront","Deploying a Static Site to S3 and CloudFront",{"path":2205,"title":2206},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fhosting-on-azure-static-web-apps","Hosting on Azure Static Web Apps",{"path":2208,"title":24},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites",{"path":2210,"title":1072},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fnginx-vs-caddy-for-serving-static-sites",{"path":2212,"title":2213},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-from-a-docker-container-with-nginx","Serving a Static Site From a Docker Container With Nginx",{"path":1134,"title":5},{"path":2216,"title":29},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy",{"path":2218,"title":2219},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-nginx","Serving a Static Site with Nginx",{"path":2221,"title":2222},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fstatic-hosting-on-google-cloud-storage","Static Hosting on Google Cloud Storage",{"path":2224,"title":1084},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fzero-downtime-deploys-with-symlink-swaps",{"path":2226,"title":2227},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fadding-a-contact-form-with-cloudflare-workers","Adding a Contact Form with Cloudflare Workers",{"path":2229,"title":2230},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Ffixing-cold-starts-in-netlify-functions-for-forms","Fixing Cold Starts in Netlify Functions for Forms",{"path":2232,"title":2233},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fhandling-form-submissions-on-a-static-site","Handling Form Submissions on a Static Site",{"path":2235,"title":2236},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites","Serverless Functions for Static Sites",{"path":2238,"title":2239},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fnetlify-functions-vs-cloudflare-workers","Netlify Functions vs Cloudflare Workers",{"path":2241,"title":2242},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fnewsletter-signup-with-an-edge-function","Newsletter Signup with an Edge Function",{"path":2244,"title":2245},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fprotecting-a-static-site-behind-authentication","Protecting a Static Site Behind Authentication",{"path":2247,"title":2248},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fproxying-third-party-apis-from-an-edge-function","Proxying Third-Party APIs from an Edge Function",{"path":2250,"title":2251},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Frate-limiting-edge-functions","Rate Limiting Edge Functions",{"path":2253,"title":2254},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Faccessibility-testing-with-axe-and-pa11y-in-ci","Accessibility Testing with axe and pa11y in CI",{"path":2256,"title":2257},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Fend-to-end-tests-for-static-sites-with-playwright","End-to-End Tests for Static Sites with Playwright",{"path":2259,"title":2260},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Ffixing-flaky-playwright-tests-against-preview-deploys","Fixing Flaky Playwright Tests Against Preview Deploys",{"path":2262,"title":2263},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci","Testing Static Sites in CI",{"path":2265,"title":2266},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Fsnapshot-testing-build-output","Snapshot Testing Build Output",{"path":2268,"title":2269},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Ftesting-redirects-and-headers-before-deploy","Testing Redirects and Headers Before Deploy",{"path":2271,"title":2272},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Ftesting-search-and-navigation-flows-with-playwright","Testing Search and Navigation Flows With Playwright",{"path":2274,"title":2275},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Ftesting-structured-data-and-meta-tags","Testing Structured Data and Meta Tags",{"path":2277,"title":2278},"\u002Fproduction-ready-deployment-cicd-workflows\u002Ftesting-static-sites-in-ci\u002Fvalidating-html-output-in-ci","Validating HTML Output in CI",{"kind":2280,"tools":2284},{"label":2281,"plural":2282,"u":2283},"How-to","How-tos","\u002Fguides\u002Fhow-to\u002F",[2285],{"label":158,"u":2286},"\u002Ftools\u002Fcaddy\u002F",1790943197958]