[{"data":1,"prerenderedAt":2228},["ShallowReactive",2],{"page:\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites":3,"all-docs-nav":1985},{"id":4,"title":5,"body":6,"breadcrumb":1959,"dateModified":1968,"datePublished":1968,"description":1969,"extension":1970,"faq":1971,"meta":1979,"navigation":254,"path":1980,"seo":1981,"slug":12,"stem":1982,"type":1983,"__hash__":1984},"content\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites\u002Findex.md","Lazy-Loading YouTube Embeds on Static Sites",{"type":7,"value":8,"toc":1937},"minimark",[9,13,17,26,31,48,52,182,186,191,194,577,580,584,595,774,785,1148,1152,1378,1389,1393,1396,1453,1456,1460,1463,1575,1578,1584,1588,1591,1687,1772,1775,1779,1827,1831,1836,1840,1844,1847,1851,1854,1858,1861,1865,1874,1878,1892,1896,1933],[10,11,5],"h1",{"id":12},"lazy-loading-youtube-embeds-on-static-sites",[14,15,16],"p",{},"A standard YouTube embed costs roughly 780 KB of transfer and 310 ms of main-thread time on a mid-tier phone — before the reader decides whether they want to watch anything. On a documentation page where the video is a supplement rather than the point, most readers never press play, so that cost buys nothing.",[14,18,19,20,25],{},"The fix is a facade: render a poster image and a play button at build time, and swap in the real iframe on click. This guide builds one that is accessible, layout-stable and generator-agnostic, then measures what it saves. It is the detailed version of the facade pattern recommended in ",[21,22,24],"a",{"href":23},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002F","Third-Party Script Performance on Static Sites",".",[27,28,30],"h2",{"id":29},"prerequisites","Prerequisites",[32,33,34,38,41],"ul",{},[35,36,37],"li",{},"A static generator with a shortcode, component or template partial you can call from content (Hugo shortcodes, Astro components, Eleventy shortcodes, MDX components).",[35,39,40],{},"A build step that can download and optimise a poster image, or the willingness to commit posters to the repository.",[35,42,43,44,25],{},"A CSS aspect-ratio wrapper, so the facade and the player occupy the same box — see ",[21,45,47],{"href":46},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-images-and-embeds-to-stop-layout-shift\u002F","Reserving Space for Images and Embeds",[27,49,51],{"id":50},"what-the-facade-replaces","What the Facade Replaces",[53,54,55,178],"figure",{},[56,57,64,65,64,69,64,73,64,80],"svg",{"viewBox":58,"role":59,"ariaLabelledBy":60,"xmlns":63},"0 0 760 300","img",[61,62],"yt-swap-title","yt-swap-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[66,67,68],"title",{"id":61},"Facade versus embedded player on first load",[70,71,72],"desc",{"id":62},"Two panels. The embedded player loads 780 kilobytes across four third-party origins and uses 310 milliseconds of main thread on every page view. The facade loads a 24 kilobyte poster from the site's own origin and uses 2 milliseconds, deferring the player until a click.",[74,75],"rect",{"x":76,"y":76,"width":77,"height":78,"fill":79},"0","760","300","#ffffff",[81,82,84,85,84,93,84,104,84,110,84,118,84,123,84,128,84,133,84,137,84,141,84,148,84,152,84,157,84,160,84,163,84,166,84,169,84,172,64],"g",{"style":83},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[86,87,92],"text",{"x":88,"y":89,"fill":90,"style":91},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","Everyone pays, or only the people who watch",[74,94],{"x":95,"y":96,"width":97,"height":98,"rx":99,"fill":100,"opacity":101,"stroke":102,"style":103},"40","52","330","200","12","#ff595e","0.12","#d83b41","stroke-width:1.5px",[86,105,109],{"x":106,"y":107,"fill":90,"style":108},"205","78","font-size:13px;font-weight:700;text-anchor:middle","Embedded player",[74,111],{"x":112,"y":113,"width":114,"height":115,"rx":116,"fill":100,"opacity":117,"stroke":102,"style":103},"66","94","278","60","8","0.16",[86,119,122],{"x":106,"y":120,"fill":90,"style":121},"120","font-size:12px;font-weight:700;text-anchor:middle","780 KB · 4 origins",[86,124,127],{"x":106,"y":125,"fill":90,"style":126},"140","font-size:12px;text-anchor:middle","310 ms main thread",[86,129,132],{"x":112,"y":130,"fill":90,"style":131},"180","font-size:12px","paid on 100% of page views",[86,134,136],{"x":112,"y":135,"fill":90,"style":131},"204","player cookies set immediately",[86,138,140],{"x":112,"y":139,"fill":90,"style":131},"228","iframe grows after load",[74,142],{"x":143,"y":96,"width":144,"height":98,"rx":99,"fill":145,"opacity":146,"stroke":147,"style":103},"400","320","#8ac926","0.14","#5a8a16",[86,149,151],{"x":150,"y":107,"fill":90,"style":108},"560","Poster facade",[74,153],{"x":154,"y":113,"width":155,"height":115,"rx":116,"fill":145,"opacity":156,"stroke":147,"style":103},"424","272","0.2",[86,158,159],{"x":150,"y":120,"fill":90,"style":121},"24 KB · own origin",[86,161,162],{"x":150,"y":125,"fill":90,"style":126},"2 ms main thread",[86,164,165],{"x":154,"y":130,"fill":90,"style":131},"player loads on click only",[86,167,168],{"x":154,"y":135,"fill":90,"style":131},"no third-party cookies until then",[86,170,171],{"x":154,"y":139,"fill":90,"style":131},"same box before and after",[86,173,177],{"x":95,"y":174,"fill":175,"style":176},"282","#556071","font-size:11px","Measured with the Lighthouse third-party summary on a mid-tier Android profile, fast 3G",[179,180,181],"figcaption",{},"The facade is not a lighter player — it is no player at all until someone asks for one, which is why the saving is proportional to how few readers press play.",[27,183,185],{"id":184},"the-recipe","The Recipe",[187,188,190],"h3",{"id":189},"_1-fetch-the-poster-at-build-time","1. Fetch the poster at build time",[14,192,193],{},"Hot-linking the platform's thumbnail keeps a third-party connection, so download it during the build and optimise it like any other image:",[195,196,201],"pre",{"className":197,"code":198,"language":199,"meta":200,"style":200},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F scripts\u002Ffetch-posters.mjs — run before the build\nimport { mkdir, writeFile } from 'node:fs\u002Fpromises';\nimport sharp from 'sharp';\n\nconst ids = process.argv.slice(2);\nawait mkdir('public\u002Fimg\u002Fposters', { recursive: true });\n\nfor (const id of ids) {\n  const res = await fetch(`https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F${id}\u002Fmaxresdefault.jpg`);\n  if (!res.ok) throw new Error(`poster fetch failed for ${id}: ${res.status}`);\n  const buf = Buffer.from(await res.arrayBuffer());\n  await sharp(buf).resize(1280, 720, { fit: 'cover' }).avif({ quality: 60 })\n    .toFile(`public\u002Fimg\u002Fposters\u002F${id}.avif`);\n  await writeFile(`public\u002Fimg\u002Fposters\u002F${id}.jpg`, await sharp(buf).jpeg({ quality: 72 }).toBuffer());\n}\nconsole.log(`fetched ${ids.length} poster(s)`);\n","javascript","",[202,203,204,213,234,249,256,285,308,313,333,363,409,437,483,504,544,550],"code",{"__ignoreMap":200},[205,206,209],"span",{"class":207,"line":208},"line",1,[205,210,212],{"class":211},"sJ8bj","\u002F\u002F scripts\u002Ffetch-posters.mjs — run before the build\n",[205,214,216,220,224,227,231],{"class":207,"line":215},2,[205,217,219],{"class":218},"szBVR","import",[205,221,223],{"class":222},"sVt8B"," { mkdir, writeFile } ",[205,225,226],{"class":218},"from",[205,228,230],{"class":229},"sZZnC"," 'node:fs\u002Fpromises'",[205,232,233],{"class":222},";\n",[205,235,237,239,242,244,247],{"class":207,"line":236},3,[205,238,219],{"class":218},[205,240,241],{"class":222}," sharp ",[205,243,226],{"class":218},[205,245,246],{"class":229}," 'sharp'",[205,248,233],{"class":222},[205,250,252],{"class":207,"line":251},4,[205,253,255],{"emptyLinePlaceholder":254},true,"\n",[205,257,259,262,266,269,272,276,279,282],{"class":207,"line":258},5,[205,260,261],{"class":218},"const",[205,263,265],{"class":264},"sj4cs"," ids",[205,267,268],{"class":218}," =",[205,270,271],{"class":222}," process.argv.",[205,273,275],{"class":274},"sScJk","slice",[205,277,278],{"class":222},"(",[205,280,281],{"class":264},"2",[205,283,284],{"class":222},");\n",[205,286,288,291,294,296,299,302,305],{"class":207,"line":287},6,[205,289,290],{"class":218},"await",[205,292,293],{"class":274}," mkdir",[205,295,278],{"class":222},[205,297,298],{"class":229},"'public\u002Fimg\u002Fposters'",[205,300,301],{"class":222},", { recursive: ",[205,303,304],{"class":264},"true",[205,306,307],{"class":222}," });\n",[205,309,311],{"class":207,"line":310},7,[205,312,255],{"emptyLinePlaceholder":254},[205,314,316,319,322,324,327,330],{"class":207,"line":315},8,[205,317,318],{"class":218},"for",[205,320,321],{"class":222}," (",[205,323,261],{"class":218},[205,325,326],{"class":264}," id",[205,328,329],{"class":218}," of",[205,331,332],{"class":222}," ids) {\n",[205,334,336,339,342,344,347,350,352,355,358,361],{"class":207,"line":335},9,[205,337,338],{"class":218},"  const",[205,340,341],{"class":264}," res",[205,343,268],{"class":218},[205,345,346],{"class":218}," await",[205,348,349],{"class":274}," fetch",[205,351,278],{"class":222},[205,353,354],{"class":229},"`https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F${",[205,356,357],{"class":222},"id",[205,359,360],{"class":229},"}\u002Fmaxresdefault.jpg`",[205,362,284],{"class":222},[205,364,366,369,371,374,377,380,383,386,388,391,393,396,399,401,404,407],{"class":207,"line":365},10,[205,367,368],{"class":218},"  if",[205,370,321],{"class":222},[205,372,373],{"class":218},"!",[205,375,376],{"class":222},"res.ok) ",[205,378,379],{"class":218},"throw",[205,381,382],{"class":218}," new",[205,384,385],{"class":274}," Error",[205,387,278],{"class":222},[205,389,390],{"class":229},"`poster fetch failed for ${",[205,392,357],{"class":222},[205,394,395],{"class":229},"}: ${",[205,397,398],{"class":222},"res",[205,400,25],{"class":229},[205,402,403],{"class":222},"status",[205,405,406],{"class":229},"}`",[205,408,284],{"class":222},[205,410,412,414,417,419,422,424,426,428,431,434],{"class":207,"line":411},11,[205,413,338],{"class":218},[205,415,416],{"class":264}," buf",[205,418,268],{"class":218},[205,420,421],{"class":222}," Buffer.",[205,423,226],{"class":274},[205,425,278],{"class":222},[205,427,290],{"class":218},[205,429,430],{"class":222}," res.",[205,432,433],{"class":274},"arrayBuffer",[205,435,436],{"class":222},"());\n",[205,438,440,443,446,449,452,454,457,460,463,466,469,472,475,478,480],{"class":207,"line":439},12,[205,441,442],{"class":218},"  await",[205,444,445],{"class":274}," sharp",[205,447,448],{"class":222},"(buf).",[205,450,451],{"class":274},"resize",[205,453,278],{"class":222},[205,455,456],{"class":264},"1280",[205,458,459],{"class":222},", ",[205,461,462],{"class":264},"720",[205,464,465],{"class":222},", { fit: ",[205,467,468],{"class":229},"'cover'",[205,470,471],{"class":222}," }).",[205,473,474],{"class":274},"avif",[205,476,477],{"class":222},"({ quality: ",[205,479,115],{"class":264},[205,481,482],{"class":222}," })\n",[205,484,486,489,492,494,497,499,502],{"class":207,"line":485},13,[205,487,488],{"class":222},"    .",[205,490,491],{"class":274},"toFile",[205,493,278],{"class":222},[205,495,496],{"class":229},"`public\u002Fimg\u002Fposters\u002F${",[205,498,357],{"class":222},[205,500,501],{"class":229},"}.avif`",[205,503,284],{"class":222},[205,505,507,509,512,514,516,518,521,523,525,527,529,532,534,537,539,542],{"class":207,"line":506},14,[205,508,442],{"class":218},[205,510,511],{"class":274}," writeFile",[205,513,278],{"class":222},[205,515,496],{"class":229},[205,517,357],{"class":222},[205,519,520],{"class":229},"}.jpg`",[205,522,459],{"class":222},[205,524,290],{"class":218},[205,526,445],{"class":274},[205,528,448],{"class":222},[205,530,531],{"class":274},"jpeg",[205,533,477],{"class":222},[205,535,536],{"class":264},"72",[205,538,471],{"class":222},[205,540,541],{"class":274},"toBuffer",[205,543,436],{"class":222},[205,545,547],{"class":207,"line":546},15,[205,548,549],{"class":222},"}\n",[205,551,553,556,559,561,564,567,569,572,575],{"class":207,"line":552},16,[205,554,555],{"class":222},"console.",[205,557,558],{"class":274},"log",[205,560,278],{"class":222},[205,562,563],{"class":229},"`fetched ${",[205,565,566],{"class":222},"ids",[205,568,25],{"class":229},[205,570,571],{"class":264},"length",[205,573,574],{"class":229},"} poster(s)`",[205,576,284],{"class":222},[14,578,579],{},"Commit the output or cache it between builds. Either way the reader gets a 20-30 KB AVIF from your own domain rather than a 90 KB JPEG from a fourth origin.",[187,581,583],{"id":582},"_2-render-the-facade-as-a-real-button","2. Render the facade as a real button",[14,585,586,587,590,591,594],{},"Accessibility is where this pattern is usually botched. A ",[202,588,589],{},"div"," with a click handler cannot be reached by keyboard and announces nothing useful. Use a ",[202,592,593],{},"button",":",[195,596,600],{"className":597,"code":598,"language":599,"meta":200,"style":200},"language-html shiki shiki-themes github-light github-dark","\u003Cfigure class=\"video\">\n  \u003Cbutton class=\"video-facade\" data-video-id=\"dQw4w9WgXcQ\"\n          aria-label=\"Play video: Deploying a static site to the edge (7 min)\">\n    \u003Cimg src=\"\u002Fimg\u002Fposters\u002FdQw4w9WgXcQ.avif\" width=\"1280\" height=\"720\" alt=\"\"\n         loading=\"lazy\" decoding=\"async\">\n    \u003Cspan class=\"video-facade-play\" aria-hidden=\"true\">\u003C\u002Fspan>\n  \u003C\u002Fbutton>\n  \u003Cfigcaption>Deploying a static site to the edge — 7 minutes.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n","html",[202,601,602,622,644,656,695,715,743,752,765],{"__ignoreMap":200},[205,603,604,607,610,613,616,619],{"class":207,"line":208},[205,605,606],{"class":222},"\u003C",[205,608,53],{"class":609},"s9eBZ",[205,611,612],{"class":274}," class",[205,614,615],{"class":222},"=",[205,617,618],{"class":229},"\"video\"",[205,620,621],{"class":222},">\n",[205,623,624,627,629,631,633,636,639,641],{"class":207,"line":215},[205,625,626],{"class":222},"  \u003C",[205,628,593],{"class":609},[205,630,612],{"class":274},[205,632,615],{"class":222},[205,634,635],{"class":229},"\"video-facade\"",[205,637,638],{"class":274}," data-video-id",[205,640,615],{"class":222},[205,642,643],{"class":229},"\"dQw4w9WgXcQ\"\n",[205,645,646,649,651,654],{"class":207,"line":236},[205,647,648],{"class":274},"          aria-label",[205,650,615],{"class":222},[205,652,653],{"class":229},"\"Play video: Deploying a static site to the edge (7 min)\"",[205,655,621],{"class":222},[205,657,658,661,663,666,668,671,674,676,679,682,684,687,690,692],{"class":207,"line":251},[205,659,660],{"class":222},"    \u003C",[205,662,59],{"class":609},[205,664,665],{"class":274}," src",[205,667,615],{"class":222},[205,669,670],{"class":229},"\"\u002Fimg\u002Fposters\u002FdQw4w9WgXcQ.avif\"",[205,672,673],{"class":274}," width",[205,675,615],{"class":222},[205,677,678],{"class":229},"\"1280\"",[205,680,681],{"class":274}," height",[205,683,615],{"class":222},[205,685,686],{"class":229},"\"720\"",[205,688,689],{"class":274}," alt",[205,691,615],{"class":222},[205,693,694],{"class":229},"\"\"\n",[205,696,697,700,702,705,708,710,713],{"class":207,"line":258},[205,698,699],{"class":274},"         loading",[205,701,615],{"class":222},[205,703,704],{"class":229},"\"lazy\"",[205,706,707],{"class":274}," decoding",[205,709,615],{"class":222},[205,711,712],{"class":229},"\"async\"",[205,714,621],{"class":222},[205,716,717,719,721,723,725,728,731,733,736,739,741],{"class":207,"line":287},[205,718,660],{"class":222},[205,720,205],{"class":609},[205,722,612],{"class":274},[205,724,615],{"class":222},[205,726,727],{"class":229},"\"video-facade-play\"",[205,729,730],{"class":274}," aria-hidden",[205,732,615],{"class":222},[205,734,735],{"class":229},"\"true\"",[205,737,738],{"class":222},">\u003C\u002F",[205,740,205],{"class":609},[205,742,621],{"class":222},[205,744,745,748,750],{"class":207,"line":310},[205,746,747],{"class":222},"  \u003C\u002F",[205,749,593],{"class":609},[205,751,621],{"class":222},[205,753,754,756,758,761,763],{"class":207,"line":315},[205,755,626],{"class":222},[205,757,179],{"class":609},[205,759,760],{"class":222},">Deploying a static site to the edge — 7 minutes.\u003C\u002F",[205,762,179],{"class":609},[205,764,621],{"class":222},[205,766,767,770,772],{"class":207,"line":335},[205,768,769],{"class":222},"\u003C\u002F",[205,771,53],{"class":609},[205,773,621],{"class":222},[14,775,776,777,780,781,784],{},"The ",[202,778,779],{},"alt"," is deliberately empty: the button's ",[202,782,783],{},"aria-label"," already carries the meaning, and a duplicate description makes the control noisier to navigate. Include the duration in the label so keyboard and screen-reader users get the same information sighted readers take from the thumbnail.",[195,786,790],{"className":787,"code":788,"language":789,"meta":200,"style":200},"language-css shiki shiki-themes github-light github-dark",".video { aspect-ratio: 16 \u002F 9; position: relative; margin: 1.6rem 0; }\n.video-facade { position: absolute; inset: 0; width: 100%; height: 100%;\n  padding: 0; border: 0; cursor: pointer; background: none; }\n.video-facade img { width: 100%; height: 100%; object-fit: cover; border-radius: 0.6rem; }\n.video-facade:focus-visible { outline: 3px solid #6a4c93; outline-offset: 3px; }\n.video-facade-play { position: absolute; inset: 50% auto auto 50%;\n  transform: translate(-50%, -50%); width: 4rem; height: 4rem; border-radius: 50%;\n  background: rgba(15, 23, 42, 0.72); }\n","css",[202,791,792,845,894,934,985,1022,1058,1115],{"__ignoreMap":200},[205,793,794,797,800,803,806,809,812,815,818,821,823,826,828,831,833,836,839,842],{"class":207,"line":208},[205,795,796],{"class":274},".video",[205,798,799],{"class":222}," { ",[205,801,802],{"class":264},"aspect-ratio",[205,804,805],{"class":222},": ",[205,807,808],{"class":264},"16",[205,810,811],{"class":222}," \u002F ",[205,813,814],{"class":264},"9",[205,816,817],{"class":222},"; ",[205,819,820],{"class":264},"position",[205,822,805],{"class":222},[205,824,825],{"class":264},"relative",[205,827,817],{"class":222},[205,829,830],{"class":264},"margin",[205,832,805],{"class":222},[205,834,835],{"class":264},"1.6",[205,837,838],{"class":218},"rem",[205,840,841],{"class":264}," 0",[205,843,844],{"class":222},"; }\n",[205,846,847,850,852,854,856,859,861,864,866,868,870,873,875,878,881,883,886,888,890,892],{"class":207,"line":215},[205,848,849],{"class":274},".video-facade",[205,851,799],{"class":222},[205,853,820],{"class":264},[205,855,805],{"class":222},[205,857,858],{"class":264},"absolute",[205,860,817],{"class":222},[205,862,863],{"class":264},"inset",[205,865,805],{"class":222},[205,867,76],{"class":264},[205,869,817],{"class":222},[205,871,872],{"class":264},"width",[205,874,805],{"class":222},[205,876,877],{"class":264},"100",[205,879,880],{"class":218},"%",[205,882,817],{"class":222},[205,884,885],{"class":264},"height",[205,887,805],{"class":222},[205,889,877],{"class":264},[205,891,880],{"class":218},[205,893,233],{"class":222},[205,895,896,899,901,903,905,908,910,912,914,917,919,922,924,927,929,932],{"class":207,"line":236},[205,897,898],{"class":264},"  padding",[205,900,805],{"class":222},[205,902,76],{"class":264},[205,904,817],{"class":222},[205,906,907],{"class":264},"border",[205,909,805],{"class":222},[205,911,76],{"class":264},[205,913,817],{"class":222},[205,915,916],{"class":264},"cursor",[205,918,805],{"class":222},[205,920,921],{"class":264},"pointer",[205,923,817],{"class":222},[205,925,926],{"class":264},"background",[205,928,805],{"class":222},[205,930,931],{"class":264},"none",[205,933,844],{"class":222},[205,935,936,938,941,943,945,947,949,951,953,955,957,959,961,963,966,968,971,973,976,978,981,983],{"class":207,"line":251},[205,937,849],{"class":274},[205,939,940],{"class":609}," img",[205,942,799],{"class":222},[205,944,872],{"class":264},[205,946,805],{"class":222},[205,948,877],{"class":264},[205,950,880],{"class":218},[205,952,817],{"class":222},[205,954,885],{"class":264},[205,956,805],{"class":222},[205,958,877],{"class":264},[205,960,880],{"class":218},[205,962,817],{"class":222},[205,964,965],{"class":264},"object-fit",[205,967,805],{"class":222},[205,969,970],{"class":264},"cover",[205,972,817],{"class":222},[205,974,975],{"class":264},"border-radius",[205,977,805],{"class":222},[205,979,980],{"class":264},"0.6",[205,982,838],{"class":218},[205,984,844],{"class":222},[205,986,987,990,992,995,997,1000,1003,1006,1009,1011,1014,1016,1018,1020],{"class":207,"line":258},[205,988,989],{"class":274},".video-facade:focus-visible",[205,991,799],{"class":222},[205,993,994],{"class":264},"outline",[205,996,805],{"class":222},[205,998,999],{"class":264},"3",[205,1001,1002],{"class":218},"px",[205,1004,1005],{"class":264}," solid",[205,1007,1008],{"class":264}," #6a4c93",[205,1010,817],{"class":222},[205,1012,1013],{"class":264},"outline-offset",[205,1015,805],{"class":222},[205,1017,999],{"class":264},[205,1019,1002],{"class":218},[205,1021,844],{"class":222},[205,1023,1024,1027,1029,1031,1033,1035,1037,1039,1041,1044,1046,1049,1051,1054,1056],{"class":207,"line":287},[205,1025,1026],{"class":274},".video-facade-play",[205,1028,799],{"class":222},[205,1030,820],{"class":264},[205,1032,805],{"class":222},[205,1034,858],{"class":264},[205,1036,817],{"class":222},[205,1038,863],{"class":264},[205,1040,805],{"class":222},[205,1042,1043],{"class":264},"50",[205,1045,880],{"class":218},[205,1047,1048],{"class":264}," auto",[205,1050,1048],{"class":264},[205,1052,1053],{"class":264}," 50",[205,1055,880],{"class":218},[205,1057,233],{"class":222},[205,1059,1060,1063,1065,1068,1070,1073,1075,1077,1079,1081,1084,1086,1088,1091,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113],{"class":207,"line":310},[205,1061,1062],{"class":264},"  transform",[205,1064,805],{"class":222},[205,1066,1067],{"class":264},"translate",[205,1069,278],{"class":222},[205,1071,1072],{"class":264},"-50",[205,1074,880],{"class":218},[205,1076,459],{"class":222},[205,1078,1072],{"class":264},[205,1080,880],{"class":218},[205,1082,1083],{"class":222},"); ",[205,1085,872],{"class":264},[205,1087,805],{"class":222},[205,1089,1090],{"class":264},"4",[205,1092,838],{"class":218},[205,1094,817],{"class":222},[205,1096,885],{"class":264},[205,1098,805],{"class":222},[205,1100,1090],{"class":264},[205,1102,838],{"class":218},[205,1104,817],{"class":222},[205,1106,975],{"class":264},[205,1108,805],{"class":222},[205,1110,1043],{"class":264},[205,1112,880],{"class":218},[205,1114,233],{"class":222},[205,1116,1117,1120,1122,1125,1127,1130,1132,1135,1137,1140,1142,1145],{"class":207,"line":315},[205,1118,1119],{"class":264},"  background",[205,1121,805],{"class":222},[205,1123,1124],{"class":264},"rgba",[205,1126,278],{"class":222},[205,1128,1129],{"class":264},"15",[205,1131,459],{"class":222},[205,1133,1134],{"class":264},"23",[205,1136,459],{"class":222},[205,1138,1139],{"class":264},"42",[205,1141,459],{"class":222},[205,1143,1144],{"class":264},"0.72",[205,1146,1147],{"class":222},"); }\n",[187,1149,1151],{"id":1150},"_3-swap-on-click-with-autoplay","3. Swap on click, with autoplay",[195,1153,1155],{"className":197,"code":1154,"language":199,"meta":200,"style":200},"document.querySelectorAll('.video-facade').forEach((btn) => {\n  btn.addEventListener('click', () => {\n    const frame = document.createElement('iframe');\n    frame.src = `https:\u002F\u002Fwww.youtube-nocookie.com\u002Fembed\u002F${btn.dataset.videoId}?autoplay=1&rel=0`;\n    frame.title = btn.getAttribute('aria-label').replace(\u002F^Play video: \u002F, '');\n    frame.allow = 'accelerometer; autoplay; encrypted-media; picture-in-picture';\n    frame.allowFullscreen = true;\n    frame.loading = 'eager';\n    btn.replaceWith(frame);\n    frame.focus();\n  }, { once: true });\n});\n",[202,1156,1157,1192,1212,1235,1262,1306,1318,1330,1342,1353,1364,1373],{"__ignoreMap":200},[205,1158,1159,1162,1165,1167,1170,1173,1176,1179,1183,1186,1189],{"class":207,"line":208},[205,1160,1161],{"class":222},"document.",[205,1163,1164],{"class":274},"querySelectorAll",[205,1166,278],{"class":222},[205,1168,1169],{"class":229},"'.video-facade'",[205,1171,1172],{"class":222},").",[205,1174,1175],{"class":274},"forEach",[205,1177,1178],{"class":222},"((",[205,1180,1182],{"class":1181},"s4XuR","btn",[205,1184,1185],{"class":222},") ",[205,1187,1188],{"class":218},"=>",[205,1190,1191],{"class":222}," {\n",[205,1193,1194,1197,1200,1202,1205,1208,1210],{"class":207,"line":215},[205,1195,1196],{"class":222},"  btn.",[205,1198,1199],{"class":274},"addEventListener",[205,1201,278],{"class":222},[205,1203,1204],{"class":229},"'click'",[205,1206,1207],{"class":222},", () ",[205,1209,1188],{"class":218},[205,1211,1191],{"class":222},[205,1213,1214,1217,1220,1222,1225,1228,1230,1233],{"class":207,"line":236},[205,1215,1216],{"class":218},"    const",[205,1218,1219],{"class":264}," frame",[205,1221,268],{"class":218},[205,1223,1224],{"class":222}," document.",[205,1226,1227],{"class":274},"createElement",[205,1229,278],{"class":222},[205,1231,1232],{"class":229},"'iframe'",[205,1234,284],{"class":222},[205,1236,1237,1240,1242,1245,1247,1249,1252,1254,1257,1260],{"class":207,"line":251},[205,1238,1239],{"class":222},"    frame.src ",[205,1241,615],{"class":218},[205,1243,1244],{"class":229}," `https:\u002F\u002Fwww.youtube-nocookie.com\u002Fembed\u002F${",[205,1246,1182],{"class":222},[205,1248,25],{"class":229},[205,1250,1251],{"class":222},"dataset",[205,1253,25],{"class":229},[205,1255,1256],{"class":222},"videoId",[205,1258,1259],{"class":229},"}?autoplay=1&rel=0`",[205,1261,233],{"class":222},[205,1263,1264,1267,1269,1272,1275,1277,1280,1282,1285,1287,1290,1293,1297,1299,1301,1304],{"class":207,"line":258},[205,1265,1266],{"class":222},"    frame.title ",[205,1268,615],{"class":218},[205,1270,1271],{"class":222}," btn.",[205,1273,1274],{"class":274},"getAttribute",[205,1276,278],{"class":222},[205,1278,1279],{"class":229},"'aria-label'",[205,1281,1172],{"class":222},[205,1283,1284],{"class":274},"replace",[205,1286,278],{"class":222},[205,1288,1289],{"class":229},"\u002F",[205,1291,1292],{"class":218},"^",[205,1294,1296],{"class":1295},"sA_wV","Play video: ",[205,1298,1289],{"class":229},[205,1300,459],{"class":222},[205,1302,1303],{"class":229},"''",[205,1305,284],{"class":222},[205,1307,1308,1311,1313,1316],{"class":207,"line":287},[205,1309,1310],{"class":222},"    frame.allow ",[205,1312,615],{"class":218},[205,1314,1315],{"class":229}," 'accelerometer; autoplay; encrypted-media; picture-in-picture'",[205,1317,233],{"class":222},[205,1319,1320,1323,1325,1328],{"class":207,"line":310},[205,1321,1322],{"class":222},"    frame.allowFullscreen ",[205,1324,615],{"class":218},[205,1326,1327],{"class":264}," true",[205,1329,233],{"class":222},[205,1331,1332,1335,1337,1340],{"class":207,"line":315},[205,1333,1334],{"class":222},"    frame.loading ",[205,1336,615],{"class":218},[205,1338,1339],{"class":229}," 'eager'",[205,1341,233],{"class":222},[205,1343,1344,1347,1350],{"class":207,"line":335},[205,1345,1346],{"class":222},"    btn.",[205,1348,1349],{"class":274},"replaceWith",[205,1351,1352],{"class":222},"(frame);\n",[205,1354,1355,1358,1361],{"class":207,"line":365},[205,1356,1357],{"class":222},"    frame.",[205,1359,1360],{"class":274},"focus",[205,1362,1363],{"class":222},"();\n",[205,1365,1366,1369,1371],{"class":207,"line":411},[205,1367,1368],{"class":222},"  }, { once: ",[205,1370,304],{"class":264},[205,1372,307],{"class":222},[205,1374,1375],{"class":207,"line":439},[205,1376,1377],{"class":222},"});\n",[14,1379,1380,1381,1384,1385,1388],{},"Three details matter. ",[202,1382,1383],{},"youtube-nocookie.com"," avoids setting tracking cookies until playback actually starts. ",[202,1386,1387],{},"autoplay=1"," means the reader presses play once rather than twice. And moving focus to the new iframe keeps keyboard users oriented — without it, focus falls back to the document body and their next Tab starts from the top of the page.",[187,1390,1392],{"id":1391},"_4-wrap-it-in-a-generator-shortcode","4. Wrap it in a generator shortcode",[14,1394,1395],{},"Do not ask authors to write that markup. In Hugo:",[195,1397,1401],{"className":1398,"code":1399,"language":1400,"meta":200,"style":200},"language-go-html-template shiki shiki-themes github-light github-dark","{{\u002F* layouts\u002Fshortcodes\u002Fvideo.html — {{\u003C video id=\"abc123\" title=\"…\" dur=\"7 min\" >}} *\u002F}}\n\u003Cfigure class=\"video\">\n  \u003Cbutton class=\"video-facade\" data-video-id=\"{{ .Get \"id\" }}\"\n          aria-label=\"Play video: {{ .Get \"title\" }} ({{ .Get \"dur\" }})\">\n    \u003Cimg src=\"\u002Fimg\u002Fposters\u002F{{ .Get \"id\" }}.avif\" width=\"1280\" height=\"720\" alt=\"\"\n         loading=\"lazy\" decoding=\"async\">\n    \u003Cspan class=\"video-facade-play\" aria-hidden=\"true\">\u003C\u002Fspan>\n  \u003C\u002Fbutton>\n  \u003Cfigcaption>{{ .Get \"title\" }} — {{ .Get \"dur\" }}.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n","go-html-template",[202,1402,1403,1408,1413,1418,1423,1428,1433,1438,1443,1448],{"__ignoreMap":200},[205,1404,1405],{"class":207,"line":208},[205,1406,1407],{},"{{\u002F* layouts\u002Fshortcodes\u002Fvideo.html — {{\u003C video id=\"abc123\" title=\"…\" dur=\"7 min\" >}} *\u002F}}\n",[205,1409,1410],{"class":207,"line":215},[205,1411,1412],{},"\u003Cfigure class=\"video\">\n",[205,1414,1415],{"class":207,"line":236},[205,1416,1417],{},"  \u003Cbutton class=\"video-facade\" data-video-id=\"{{ .Get \"id\" }}\"\n",[205,1419,1420],{"class":207,"line":251},[205,1421,1422],{},"          aria-label=\"Play video: {{ .Get \"title\" }} ({{ .Get \"dur\" }})\">\n",[205,1424,1425],{"class":207,"line":258},[205,1426,1427],{},"    \u003Cimg src=\"\u002Fimg\u002Fposters\u002F{{ .Get \"id\" }}.avif\" width=\"1280\" height=\"720\" alt=\"\"\n",[205,1429,1430],{"class":207,"line":287},[205,1431,1432],{},"         loading=\"lazy\" decoding=\"async\">\n",[205,1434,1435],{"class":207,"line":310},[205,1436,1437],{},"    \u003Cspan class=\"video-facade-play\" aria-hidden=\"true\">\u003C\u002Fspan>\n",[205,1439,1440],{"class":207,"line":315},[205,1441,1442],{},"  \u003C\u002Fbutton>\n",[205,1444,1445],{"class":207,"line":335},[205,1446,1447],{},"  \u003Cfigcaption>{{ .Get \"title\" }} — {{ .Get \"dur\" }}.\u003C\u002Ffigcaption>\n",[205,1449,1450],{"class":207,"line":365},[205,1451,1452],{},"\u003C\u002Ffigure>\n",[14,1454,1455],{},"Astro and Eleventy equivalents are the same markup inside a component or shortcode. Centralising it means a later improvement — a better poster format, a different privacy domain — ships everywhere at once.",[27,1457,1459],{"id":1458},"the-consent-side-effect","The Consent Side Effect",[14,1461,1462],{},"A facade changes more than performance. A standard embed contacts the video platform, and in many configurations sets cookies, the moment the page loads — which means the embed is a consent-relevant third party on every page that carries one, whether or not anyone watches. Because the facade contacts nobody until a click, the page starts with no third-party state at all.",[53,1464,1465,1572],{},[56,1466,64,1470,64,1473,64,1476,64,1478,64,1558],{"viewBox":58,"role":59,"ariaLabelledBy":1467,"xmlns":63},[1468,1469],"yt-consent-title","yt-consent-desc",[66,1471,1472],{"id":1468},"Third-party contact with and without a facade",[70,1474,1475],{"id":1469},"Two states. With a standard embed the page load itself contacts the video platform, so consent must be resolved before the page renders the video. With a facade the page load contacts nobody, and the platform is only contacted after the reader clicks play, at which point consent can be requested in context.",[74,1477],{"x":76,"y":76,"width":77,"height":78,"fill":79},[81,1479,84,1480,84,1483,84,1489,84,1494,84,1499,84,1502,84,1506,84,1509,84,1514,84,1518,84,1521,84,1524,84,1527,84,1531,84,1534,84,1537,84,1540,64],{"style":83},[86,1481,1482],{"x":88,"y":89,"fill":90,"style":91},"When the third party is first contacted",[74,1484],{"x":95,"y":115,"width":1485,"height":115,"rx":1486,"fill":1487,"opacity":1488,"stroke":175,"style":103},"150","10","#d9e2ef","0.5",[86,1490,1493],{"x":1491,"y":1492,"fill":90,"style":121},"115","84","Page load",[86,1495,1498],{"x":1491,"y":1496,"fill":175,"style":1497},"104","font-size:11px;text-anchor:middle","HTML from your CDN",[74,1500],{"x":1501,"y":115,"width":98,"height":115,"rx":1486,"fill":100,"opacity":146,"stroke":102,"style":103},"250",[86,1503,1505],{"x":1504,"y":1492,"fill":90,"style":121},"350","Standard embed",[86,1507,1508],{"x":1504,"y":1496,"fill":102,"style":1497},"platform contacted now",[74,1510],{"x":1511,"y":115,"width":1512,"height":115,"rx":1486,"fill":100,"opacity":1513,"stroke":102,"style":103},"510","210","0.1",[86,1515,1517],{"x":1516,"y":1492,"fill":90,"style":121},"615","Consent needed",[86,1519,1520],{"x":1516,"y":1496,"fill":175,"style":1497},"before the page settles",[74,1522],{"x":1501,"y":130,"width":98,"height":115,"rx":1486,"fill":145,"opacity":1523,"stroke":147,"style":103},"0.18",[86,1525,1526],{"x":1504,"y":135,"fill":90,"style":121},"Facade",[86,1528,1530],{"x":1504,"y":1529,"fill":147,"style":1497},"224","nobody contacted",[74,1532],{"x":1511,"y":130,"width":1512,"height":115,"rx":1486,"fill":1533,"opacity":146,"stroke":1533,"style":103},"#1982c4",[86,1535,1536],{"x":1516,"y":135,"fill":90,"style":121},"Click → platform",[86,1538,1539],{"x":1516,"y":1529,"fill":175,"style":1497},"consent asked in context",[81,1541,1543,1544,1543,1549,1543,1552,1543,1555,84],{"stroke":175,"fill":931,"style":1542},"stroke-width:2px","\n      ",[1545,1546],"path",{"d":1547,"style":1548},"M190 90 L248 90","marker-end:url(#yt-consent-arrow)",[1545,1550],{"d":1551,"style":1548},"M450 90 L508 90",[1545,1553],{"d":1554,"style":1548},"M150 120 L280 178",[1545,1556],{"d":1557,"style":1548},"M450 210 L508 210",[1559,1560,84,1561,64],"defs",{},[1562,1563,1543,1569,84],"marker",{"id":1564,"viewBox":1565,"refX":116,"refY":1566,"markerWidth":1567,"markerHeight":1567,"orient":1568},"yt-consent-arrow","0 0 10 10","5","7","auto-start-reverse",[1545,1570],{"d":1571,"fill":175},"M0 0 L10 5 L0 10 z",[179,1573,1574],{},"Deferring the contact also defers the consent question to the moment it is relevant, which is both easier to explain to a reader and cheaper to render.",[14,1576,1577],{},"Two practical consequences. If your consent platform currently blocks video embeds until a reader accepts, the facade lets you drop that rule: nothing to block until the click, and the click itself is a reasonable moment to surface the platform's terms. And if you must keep the block, the facade is what makes the blocked state look deliberate — a poster with a play button reads as a video, whereas a suppressed iframe reads as a broken page.",[14,1579,1580,1581,1583],{},"Use ",[202,1582,1383],{}," for the swapped-in player regardless. It defers cookie setting until playback begins, so a reader who clicks and then changes their mind leaves no more state behind than one who never clicked.",[27,1585,1587],{"id":1586},"measured-impact","Measured Impact",[14,1589,1590],{},"Documentation page with one video, mid-tier Android profile, Chrome 4× CPU throttle, fast 3G, median of five runs:",[1592,1593,1594,1616],"table",{},[1595,1596,1597],"thead",{},[1598,1599,1600,1604,1607,1610,1613],"tr",{},[1601,1602,1603],"th",{},"Setup",[1601,1605,1606],{},"Transfer",[1601,1608,1609],{},"Blocking time",[1601,1611,1612],{},"Origins",[1601,1614,1615],{},"LCP",[1617,1618,1619,1636,1654,1671],"tbody",{},[1598,1620,1621,1625,1628,1631,1633],{},[1622,1623,1624],"td",{},"Standard iframe embed",[1622,1626,1627],{},"780 KB",[1622,1629,1630],{},"310 ms",[1622,1632,1090],{},[1622,1634,1635],{},"3.4 s",[1598,1637,1638,1644,1646,1649,1651],{},[1622,1639,1640,1641],{},"Iframe with ",[202,1642,1643],{},"loading=\"lazy\"",[1622,1645,1627],{},[1622,1647,1648],{},"300 ms",[1622,1650,1090],{},[1622,1652,1653],{},"2.6 s",[1598,1655,1656,1659,1662,1665,1668],{},[1622,1657,1658],{},"Poster facade (this recipe)",[1622,1660,1661],{},"24 KB",[1622,1663,1664],{},"2 ms",[1622,1666,1667],{},"1",[1622,1669,1670],{},"1.9 s",[1598,1672,1673,1676,1679,1682,1684],{},[1622,1674,1675],{},"Facade, after the reader clicks",[1622,1677,1678],{},"804 KB",[1622,1680,1681],{},"312 ms",[1622,1683,1090],{},[1622,1685,1686],{},"n\u002Fa",[53,1688,1689,1769],{},[56,1690,64,1695,64,1698,64,1701,64,1704],{"viewBox":1691,"role":59,"ariaLabelledBy":1692,"xmlns":63},"0 0 760 280",[1693,1694],"yt-bars-title","yt-bars-desc",[66,1696,1697],{"id":1693},"Transfer and blocking time by embed strategy",[70,1699,1700],{"id":1694},"A horizontal bar chart on a shared scale. The standard embed transfers 780 kilobytes with 310 milliseconds blocking. Lazy loading the iframe transfers the same for readers who scroll. The facade transfers 24 kilobytes with 2 milliseconds, and only readers who click pay the full cost.",[74,1702],{"x":76,"y":76,"width":77,"height":1703,"fill":79},"280",[81,1705,84,1706,84,1710,84,1714,84,1718,84,1722,84,1727,84,1731,84,1734,84,1738,84,1744,84,1748,84,1751,84,1755,84,1760,84,1764,64],{"style":83},[86,1707,1709],{"x":88,"y":1708,"fill":90,"style":91},"26","First-load cost by strategy",[207,1711],{"x1":1501,"y1":1712,"x2":1501,"y2":1713,"stroke":1487,"style":103},"44","220",[86,1715,1505],{"x":115,"y":1716,"fill":90,"style":1717},"80","font-size:12px;font-weight:700",[86,1719,1721],{"x":115,"y":1720,"fill":175,"style":176},"96","every reader",[74,1723],{"x":1501,"y":1724,"width":1725,"height":1726,"rx":1566,"fill":100,"opacity":117,"stroke":102,"style":103},"64","450","30",[86,1728,1730],{"x":1729,"y":1492,"fill":102,"style":121},"475","780 KB · 310 ms",[86,1732,1733],{"x":115,"y":125,"fill":90,"style":1717},"lazy iframe",[86,1735,1737],{"x":115,"y":1736,"fill":175,"style":176},"156","readers who scroll",[74,1739],{"x":1501,"y":1740,"width":1725,"height":1726,"rx":1566,"fill":1741,"opacity":1742,"stroke":1743,"style":103},"124","#ffca3a","0.34","#a97b00",[86,1745,1747],{"x":1729,"y":1746,"fill":1743,"style":121},"144","780 KB · 300 ms, just later",[86,1749,1750],{"x":115,"y":98,"fill":90,"style":1717},"poster facade",[86,1752,1754],{"x":115,"y":1753,"fill":175,"style":176},"216","readers who click",[74,1756],{"x":1501,"y":1757,"width":1758,"height":1726,"rx":1090,"fill":145,"opacity":1759,"stroke":147,"style":103},"184","14","0.3",[86,1761,1763],{"x":1762,"y":135,"fill":147,"style":1717},"290","24 KB · 2 ms",[86,1765,1768],{"x":1766,"y":1767,"fill":175,"style":176},"219","252","Shared linear scale · 1.5 s of LCP improvement came from the origins the facade removes",[179,1770,1771],{},"Lazy loading moves the cost; the facade removes it for the roughly 95% of readers on a docs page who never press play.",[14,1773,1774],{},"Analytics on the site measured showed 4.6% of readers on pages with a video pressed play. The facade therefore removed 780 KB from about 95 of every 100 page views, and the 1.5 s LCP improvement came mostly from the three third-party origins that no longer competed for bandwidth during load.",[27,1776,1778],{"id":1777},"pitfalls-rollback","Pitfalls & Rollback",[32,1780,1781,1793,1799,1805,1815,1821],{},[35,1782,1783,1792],{},[1784,1785,1786,1787,1789,1790,25],"strong",{},"A ",[202,1788,589],{}," instead of a ",[202,1791,593],{}," Not focusable, not announced, not operable by keyboard. This is the most common defect in published facade snippets.",[35,1794,1795,1798],{},[1784,1796,1797],{},"Hot-linking the thumbnail."," Keeps a third-party connection and usually serves an over-sized JPEG. Fetch and optimise at build time.",[35,1800,1801,1804],{},[1784,1802,1803],{},"Forgetting autoplay."," Without it the reader presses play twice and the facade feels broken.",[35,1806,1807,1810,1811,1814],{},[1784,1808,1809],{},"Losing focus on swap."," Call ",[202,1812,1813],{},"focus()"," on the new iframe so keyboard navigation continues from the video.",[35,1816,1817,1820],{},[1784,1818,1819],{},"Mismatched box."," If the facade and the player have different sizes the swap shifts the page — although a swap within 500 ms of a click is excluded from CLS, a slow network can push it past that window.",[35,1822,1823,1826],{},[1784,1824,1825],{},"Rollback:"," the shortcode is one template. Replacing its body with the original iframe restores the previous behaviour on the next build, with no content changes.",[27,1828,1830],{"id":1829},"conclusion","Conclusion",[14,1832,1833,1834,25],{},"A video embed is the largest single third party most content pages carry, and the facade pattern removes it for everyone who does not watch. Fetch the poster at build time, render a real button with a descriptive label, swap on click with autoplay and focus management, and wrap the whole thing in a shortcode so authors never see the markup. Then apply the same tiering to the rest of the page's third parties with ",[21,1835,24],{"href":23},[27,1837,1839],{"id":1838},"faq","FAQ",[187,1841,1843],{"id":1842},"does-loading-equals-lazy-on-the-iframe-solve-this","Does loading equals lazy on the iframe solve this?",[14,1845,1846],{},"Only partly. It delays the request until the element is near the viewport, which helps a page whose video sits far below the fold, but any reader who scrolls still pays the full 780 kilobytes and the player still runs on the main thread. A facade means most readers never pay it at all.",[187,1848,1850],{"id":1849},"do-i-lose-analytics-from-the-video-platform","Do I lose analytics from the video platform?",[14,1852,1853],{},"No. The player loads normally once someone clicks, and it reports playback exactly as it would have. What you lose is impression data for readers who never pressed play, which was never a meaningful signal anyway.",[187,1855,1857],{"id":1856},"where-should-the-poster-image-come-from","Where should the poster image come from?",[14,1859,1860],{},"Download it at build time and serve it from your own domain, optimised and correctly sized. Hot-linking the platform's thumbnail re-introduces a third-party connection, which is most of what the facade was meant to remove.",[187,1862,1864],{"id":1863},"is-a-facade-accessible","Is a facade accessible?",[14,1866,1867,1868,1870,1871,1873],{},"It is if you build it as a real ",[202,1869,593],{}," with a descriptive label and a visible focus ring. A ",[202,1872,589],{}," with a click handler is not keyboard operable and gives screen-reader users nothing to act on, which is the most common way this pattern is implemented badly.",[187,1875,1877],{"id":1876},"should-the-video-autoplay-after-the-click","Should the video autoplay after the click?",[14,1879,1880,1881,1883,1884,1887,1888,1891],{},"Yes. The reader has just expressed intent, and without autoplay they have to press play twice. Append ",[202,1882,1387],{}," to the embed URL and include ",[202,1885,1886],{},"autoplay"," in the iframe's ",[202,1889,1890],{},"allow"," attribute.",[27,1893,1895],{"id":1894},"related","Related",[32,1897,1898,1907,1914,1921,1926],{},[35,1899,1900,1903,1904,1906],{},[1784,1901,1902],{},"Parent:"," ",[21,1905,24],{"href":23}," — where facades fit the loading tiers.",[35,1908,1909,1913],{},[21,1910,1912],{"href":1911},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-late-loading-embeds\u002F","Fixing CLS From Late-Loading Embeds"," — keeping the swap from moving the page.",[35,1915,1916,1920],{},[21,1917,1919],{"href":1918},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fself-hosting-analytics-to-cut-third-party-requests\u002F","Self-Hosting Analytics to Cut Third-Party Requests"," — removing the other common third-party origin.",[35,1922,1923,1925],{},[21,1924,47],{"href":46}," — the aspect-ratio wrapper this depends on.",[35,1927,1928,1932],{},[21,1929,1931],{"href":1930},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002F","Image Optimization Pipelines in Astro"," — optimise the poster like any other build-time image.",[1934,1935,1936],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":200,"searchDepth":215,"depth":215,"links":1938},[1939,1940,1941,1947,1948,1949,1950,1951,1958],{"id":29,"depth":215,"text":30},{"id":50,"depth":215,"text":51},{"id":184,"depth":215,"text":185,"children":1942},[1943,1944,1945,1946],{"id":189,"depth":236,"text":190},{"id":582,"depth":236,"text":583},{"id":1150,"depth":236,"text":1151},{"id":1391,"depth":236,"text":1392},{"id":1458,"depth":215,"text":1459},{"id":1586,"depth":215,"text":1587},{"id":1777,"depth":215,"text":1778},{"id":1829,"depth":215,"text":1830},{"id":1838,"depth":215,"text":1839,"children":1952},[1953,1954,1955,1956,1957],{"id":1842,"depth":236,"text":1843},{"id":1849,"depth":236,"text":1850},{"id":1856,"depth":236,"text":1857},{"id":1863,"depth":236,"text":1864},{"id":1876,"depth":236,"text":1877},{"id":1894,"depth":215,"text":1895},[1960,1962,1965,1966],{"name":1961,"item":1289},"Home",{"name":1963,"item":1964},"Performance Optimization & Core Web Vitals for SSGs","\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002F",{"name":24,"item":23},{"name":5,"item":1967},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites\u002F","2026-08-01","Replace the iframe player with a build-time poster facade: 780 KB and 310 ms of blocking time removed from every page load, with keyboard and screen-reader support intact.","md",[1972,1973,1974,1975,1977],{"q":1843,"a":1846},{"q":1850,"a":1853},{"q":1857,"a":1860},{"q":1864,"a":1976},"It is if you build it as a real button with a descriptive label and a visible focus ring. A div with a click handler is not keyboard operable and gives screen-reader users nothing to act on, which is the most common way this pattern is implemented badly.",{"q":1877,"a":1978},"Yes. The reader has just expressed intent, and without autoplay they have to press play twice. Append autoplay equals 1 to the embed URL and include autoplay in the iframe allow attribute.",{},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites",{"title":5,"description":1969},"performance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites\u002Findex","article","ZkuRHgC85dsjQRdS6SjchVy5DKvKx2stRuIkbis28xE",[1986,1989,1992,1995,1998,2001,2004,2007,2010,2013,2016,2019,2022,2025,2028,2031,2034,2037,2040,2043,2046,2049,2052,2055,2058,2061,2064,2067,2070,2073,2076,2079,2081,2084,2087,2089,2092,2095,2098,2101,2103,2106,2109,2112,2115,2118,2121,2124,2127,2130,2133,2136,2139,2141,2142,2144,2147,2150,2153,2156,2159,2162,2165,2168,2171,2174,2177,2180,2183,2186,2189,2192,2195,2198,2201,2204,2207,2210,2213,2216,2219,2222,2225],{"path":1987,"title":1988},"\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":1990,"title":1991},"\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":1993,"title":1994},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":1996,"title":1997},"\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":1999,"title":2000},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":2002,"title":2003},"\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":2005,"title":2006},"\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":2008,"title":2009},"\u002Fchoosing-the-right-static-site-generator-for-production","Choosing the Right Static Site Generator for Production",{"path":2011,"title":2012},"\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":2014,"title":2015},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":2017,"title":2018},"\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":2020,"title":2021},"\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":2023,"title":2024},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":2026,"title":2027},"\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":2029,"title":2030},"\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":2032,"title":2033},"\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":2035,"title":2036},"\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":2038,"title":2039},"\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":2041,"title":2042},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":2044,"title":2045},"\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":2047,"title":2048},"\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":2050,"title":2051},"\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":2053,"title":2054},"\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":2056,"title":2057},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":2059,"title":2060},"\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":2062,"title":2063},"\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":2065,"title":2066},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":2068,"title":2069},"\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":2071,"title":2072},"\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":2074,"title":2075},"\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":2077,"title":2078},"\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":2080,"title":1912},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-late-loading-embeds",{"path":2082,"title":2083},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":2085,"title":2086},"\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":2088,"title":47},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-images-and-embeds-to-stop-layout-shift",{"path":2090,"title":2091},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":2093,"title":2094},"\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":2096,"title":2097},"\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":2099,"title":2100},"\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":2102,"title":1931},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro",{"path":2104,"title":2105},"\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":2107,"title":2108},"\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":2110,"title":2111},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":2113,"title":2114},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":2116,"title":2117},"\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":2119,"title":2120},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":2122,"title":2123},"\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":2125,"title":2126},"\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":2128,"title":2129},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":2131,"title":2132},"\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":2134,"title":2135},"\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":2137,"title":2138},"\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":2140,"title":24},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites",{"path":1980,"title":5},{"path":2143,"title":1919},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fself-hosting-analytics-to-cut-third-party-requests",{"path":2145,"title":2146},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":2148,"title":2149},"\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":2151,"title":2152},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":2154,"title":2155},"\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":2157,"title":2158},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":2160,"title":2161},"\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":2163,"title":2164},"\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":2166,"title":2167},"\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":2169,"title":2170},"\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":2172,"title":2173},"\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":2175,"title":2176},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":2178,"title":2179},"\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":2181,"title":2182},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":2184,"title":2185},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":2187,"title":2188},"\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":2190,"title":2191},"\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":2193,"title":2194},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":2196,"title":2197},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":2199,"title":2200},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":2202,"title":2203},"\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":2205,"title":2206},"\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":2208,"title":2209},"\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":2211,"title":2212},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":2214,"title":2215},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":2217,"title":2218},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":2220,"title":2221},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":2223,"title":2224},"\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":2226,"title":2227},"\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",1785611671575]