[{"data":1,"prerenderedAt":3353},["ShallowReactive",2],{"blog:\u002Fblog\u002Fios26-safari-toolbar-colors":3},{"page":4,"surround":1476},{"id":5,"title":6,"author":7,"body":8,"brandColor":1458,"colorBg":1458,"colorBgSecondary":1458,"colorBrand":1458,"colorFooter":1458,"colorFooterText":1458,"colorHeaders":1458,"colorInvertedText":1458,"colorText":1458,"colorTopbar":1458,"coverImage":1458,"date":1459,"description":1460,"draft":1461,"extension":1462,"galleryDark":1461,"galleryImage":1458,"gallerySize":1458,"h1":1463,"hoverVideo":1458,"label":1464,"meta":1465,"navigation":353,"order":52,"path":1466,"seo":1467,"stem":1468,"tags":1469,"theme":1474,"__hash__":1475},"blog\u002Fblog\u002Fios26-safari-toolbar-colors.mdc","Why iOS 26 Safari Toolbar Colors Work Differently - Ben Nasedkin","Ben Nasedkin",{"type":9,"value":10,"toc":1425},"minimark",[11,16,25,28,33,39,83,86,89,92,116,119,123,126,131,134,140,143,147,150,153,157,160,166,170,173,177,191,259,262,265,269,275,305,308,318,384,388,391,398,402,405,409,412,483,486,490,493,598,602,608,611,615,619,622,625,629,632,730,733,737,740,841,844,848,851,854,858,861,867,870,874,877,929,932,942,946,949,1027,1030,1034,1037,1219,1222,1225,1231,1237,1241,1244,1260,1263,1267,1270,1273,1276,1279,1282,1286,1308,1311,1315,1336,1353,1370,1387,1404,1421],[12,13,15],"h1",{"id":14},"why-ios-26-safari-toolbar-colors-work-differently","Why iOS 26 Safari Toolbar Colors Work Differently",[17,18,19,20,24],"p",{},"If you've updated to iOS 26, you've noticed. The Safari toolbar looks different. Colors shift as you scroll. Your carefully chosen ",[21,22,23],"code",{},"theme-color"," meta tag does nothing.",[17,26,27],{},"This isn't a bug. It's a philosophy shift.",[29,30,32],"h2",{"id":31},"what-changed","What Changed",[17,34,35,36,38],{},"Safari 15 through 18.6 supported the ",[21,37,23],{}," meta tag:",[40,41,46],"pre",{"className":42,"code":43,"language":44,"meta":45,"style":45},"language-html shiki shiki-themes github-light github-dark","\u003Cmeta name=\"theme-color\" content=\"#1a1a1a\">\n","html","",[21,47,48],{"__ignoreMap":45},[49,50,53,57,61,65,68,72,75,77,80],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"sVt8B","\u003C",[49,58,60],{"class":59},"s9eBZ","meta",[49,62,64],{"class":63},"sScJk"," name",[49,66,67],{"class":55},"=",[49,69,71],{"class":70},"sZZnC","\"theme-color\"",[49,73,74],{"class":63}," content",[49,76,67],{"class":55},[49,78,79],{"class":70},"\"#1a1a1a\"",[49,81,82],{"class":55},">\n",[17,84,85],{},"Developers declared toolbar colors explicitly. Simple, predictable, controllable.",[17,87,88],{},"Safari 26 dropped this. The meta tag still parses — Safari ignores the value.",[17,90,91],{},"Instead, Safari now derives toolbar colors automatically from your CSS:",[93,94,95,103,113],"ol",{},[96,97,98,99,102],"li",{},"First, from the ",[21,100,101],{},"background-color"," of fixed or sticky elements near the viewport edges",[96,104,105,106,108,109,112],{},"Fallback to the ",[21,107,101],{}," of the ",[21,110,111],{},"\u003Cbody>"," element",[96,114,115],{},"If neither exists, system default",[17,117,118],{},"This happens at render time. JavaScript changes to background colors after initial paint don't update the toolbar.",[29,120,122],{"id":121},"why-apple-made-this-change","Why Apple Made This Change",[17,124,125],{},"The answer is Liquid Glass.",[127,128,130],"h3",{"id":129},"content-first-design","Content-First Design",[17,132,133],{},"Apple's new design language prioritizes content over chrome. The interface should disappear during use, not demand attention.",[17,135,136,137,139],{},"A hardcoded ",[21,138,23],{}," creates a static toolbar. It doesn't respond to content. It competes with it.",[17,141,142],{},"By deriving colors from actual page elements, the toolbar becomes contextual. It reflects what you're looking at, not what the developer decided months ago.",[127,144,146],{"id":145},"dynamic-immersion","Dynamic Immersion",[17,148,149],{},"On iOS 26, the address bar blends with the webpage. On macOS Tahoe, toolbars reflect page colors as you scroll. The UI feels alive.",[17,151,152],{},"This only works if Safari controls the color derivation. A static meta tag breaks the illusion.",[127,154,156],{"id":155},"cross-platform-consistency","Cross-Platform Consistency",[17,158,159],{},"Liquid Glass spans iOS, iPadOS, macOS, watchOS, and tvOS. A unified visual language requires unified behavior.",[17,161,162,163,165],{},"The ",[21,164,23],{}," meta tag was a web-only concept. Dropping it aligns Safari with native app behavior, where system chrome adapts to content automatically.",[29,167,169],{"id":168},"the-derivation-logic","The Derivation Logic",[17,171,172],{},"Safari's color algorithm follows a specific hierarchy.",[127,174,176],{"id":175},"fixed-and-sticky-elements-take-priority","Fixed and Sticky Elements Take Priority",[17,178,179,180,183,184,187,188,190],{},"If you have a header with ",[21,181,182],{},"position: fixed"," or ",[21,185,186],{},"position: sticky"," near the top of the viewport, Safari samples its ",[21,189,101],{}," for the toolbar.",[40,192,196],{"className":193,"code":194,"language":195,"meta":45,"style":45},"language-css shiki shiki-themes github-light github-dark","header {\n  position: fixed;\n  top: 0;\n  background-color: #1a1a1a; \u002F* This becomes toolbar color *\u002F\n}\n","css",[21,197,198,206,222,235,253],{"__ignoreMap":45},[49,199,200,203],{"class":51,"line":52},[49,201,202],{"class":59},"header",[49,204,205],{"class":55}," {\n",[49,207,209,213,216,219],{"class":51,"line":208},2,[49,210,212],{"class":211},"sj4cs","  position",[49,214,215],{"class":55},": ",[49,217,218],{"class":211},"fixed",[49,220,221],{"class":55},";\n",[49,223,225,228,230,233],{"class":51,"line":224},3,[49,226,227],{"class":211},"  top",[49,229,215],{"class":55},[49,231,232],{"class":211},"0",[49,234,221],{"class":55},[49,236,238,241,243,246,249],{"class":51,"line":237},4,[49,239,240],{"class":211},"  background-color",[49,242,215],{"class":55},[49,244,245],{"class":211},"#1a1a1a",[49,247,248],{"class":55},"; ",[49,250,252],{"class":251},"sJ8bj","\u002F* This becomes toolbar color *\u002F\n",[49,254,256],{"class":51,"line":255},5,[49,257,258],{"class":55},"}\n",[17,260,261],{},"The logic: fixed elements border the \"obscured content inset\" — the area where browser UI overlaps your content. Safari extends the fixed element's color into the toolbar to create visual continuity.",[17,263,264],{},"This matters more on iPhone. The blur effect under the toolbar is softer than on macOS. More of your page shows through. Color mismatches become jarring.",[127,266,268],{"id":267},"body-background-as-fallback","Body Background as Fallback",[17,270,271,272,274],{},"Without fixed elements, Safari falls back to ",[21,273,111],{}," background color.",[40,276,278],{"className":193,"code":277,"language":195,"meta":45,"style":45},"body {\n  background-color: #ffffff; \u002F* Toolbar color if no fixed elements *\u002F\n}\n",[21,279,280,287,301],{"__ignoreMap":45},[49,281,282,285],{"class":51,"line":52},[49,283,284],{"class":59},"body",[49,286,205],{"class":55},[49,288,289,291,293,296,298],{"class":51,"line":208},[49,290,240],{"class":211},[49,292,215],{"class":55},[49,294,295],{"class":211},"#ffffff",[49,297,248],{"class":55},[49,299,300],{"class":251},"\u002F* Toolbar color if no fixed elements *\u002F\n",[49,302,303],{"class":51,"line":224},[49,304,258],{"class":55},[17,306,307],{},"This is also what determines the overscroll \"rubber band\" color. When users pull past the content boundary, they see the body background. Safari uses the same value for toolbar tinting.",[17,309,310,311,314,315,317],{},"Note: ",[21,312,313],{},"\u003Chtml>"," background is ignored for this purpose. Only ",[21,316,111],{}," matters.",[40,319,321],{"className":193,"code":320,"language":195,"meta":45,"style":45},"\u002F* This does NOT affect toolbar or overscroll *\u002F\nhtml {\n  background-color: #ff0000;\n}\n\n\u002F* This DOES affect toolbar and overscroll *\u002F\nbody {\n  background-color: #1a1a1a;\n}\n",[21,322,323,328,334,345,349,355,361,368,379],{"__ignoreMap":45},[49,324,325],{"class":51,"line":52},[49,326,327],{"class":251},"\u002F* This does NOT affect toolbar or overscroll *\u002F\n",[49,329,330,332],{"class":51,"line":208},[49,331,44],{"class":59},[49,333,205],{"class":55},[49,335,336,338,340,343],{"class":51,"line":224},[49,337,240],{"class":211},[49,339,215],{"class":55},[49,341,342],{"class":211},"#ff0000",[49,344,221],{"class":55},[49,346,347],{"class":51,"line":237},[49,348,258],{"class":55},[49,350,351],{"class":51,"line":255},[49,352,354],{"emptyLinePlaceholder":353},true,"\n",[49,356,358],{"class":51,"line":357},6,[49,359,360],{"class":251},"\u002F* This DOES affect toolbar and overscroll *\u002F\n",[49,362,364,366],{"class":51,"line":363},7,[49,365,284],{"class":59},[49,367,205],{"class":55},[49,369,371,373,375,377],{"class":51,"line":370},8,[49,372,240],{"class":211},[49,374,215],{"class":55},[49,376,245],{"class":211},[49,378,221],{"class":55},[49,380,382],{"class":51,"line":381},9,[49,383,258],{"class":55},[127,385,387],{"id":386},"the-rendering-window","The Rendering Window",[17,389,390],{},"Safari samples colors at initial render. Changes via JavaScript don't trigger re-sampling.",[17,392,393,394,397],{},"If you dynamically change ",[21,395,396],{},"document.body.style.backgroundColor",", the toolbar won't update. This is intentional — constant toolbar color changes would be visually chaotic.",[29,399,401],{"id":400},"the-problems-this-creates","The Problems This Creates",[17,403,404],{},"Apple's logic makes sense in theory. In practice, edge cases break.",[127,406,408],{"id":407},"dialog-and-popover-conflicts","Dialog and Popover Conflicts",[17,410,411],{},"When you show a modal with a semi-transparent backdrop, Safari might sample the backdrop's background color for the toolbar.",[40,413,415],{"className":193,"code":414,"language":195,"meta":45,"style":45},".modal-backdrop {\n  position: fixed;\n  inset: 0;\n  background-color: rgba(0, 0, 0, 0.5); \u002F* Safari may sample this *\u002F\n}\n",[21,416,417,424,434,445,479],{"__ignoreMap":45},[49,418,419,422],{"class":51,"line":52},[49,420,421],{"class":63},".modal-backdrop",[49,423,205],{"class":55},[49,425,426,428,430,432],{"class":51,"line":208},[49,427,212],{"class":211},[49,429,215],{"class":55},[49,431,218],{"class":211},[49,433,221],{"class":55},[49,435,436,439,441,443],{"class":51,"line":224},[49,437,438],{"class":211},"  inset",[49,440,215],{"class":55},[49,442,232],{"class":211},[49,444,221],{"class":55},[49,446,447,449,451,454,457,459,462,464,466,468,470,473,476],{"class":51,"line":237},[49,448,240],{"class":211},[49,450,215],{"class":55},[49,452,453],{"class":211},"rgba",[49,455,456],{"class":55},"(",[49,458,232],{"class":211},[49,460,461],{"class":55},", ",[49,463,232],{"class":211},[49,465,461],{"class":55},[49,467,232],{"class":211},[49,469,461],{"class":55},[49,471,472],{"class":211},"0.5",[49,474,475],{"class":55},"); ",[49,477,478],{"class":251},"\u002F* Safari may sample this *\u002F\n",[49,480,481],{"class":51,"line":255},[49,482,258],{"class":55},[17,484,485],{},"Your dark overlay suddenly tints the entire toolbar dark — even though your actual content underneath is light.",[127,487,489],{"id":488},"multiple-fixed-elements","Multiple Fixed Elements",[17,491,492],{},"If you have both a fixed header and a fixed footer, Safari picks one. The algorithm isn't always predictable.",[40,494,496],{"className":193,"code":495,"language":195,"meta":45,"style":45},".header {\n  position: fixed;\n  top: 0;\n  background-color: #ffffff;\n}\n\n.footer {\n  position: fixed;\n  bottom: 0;\n  background-color: #1a1a1a;\n}\n\n\u002F* Which color wins? Safari decides. *\u002F\n",[21,497,498,505,515,525,535,539,543,550,560,571,582,587,592],{"__ignoreMap":45},[49,499,500,503],{"class":51,"line":52},[49,501,502],{"class":63},".header",[49,504,205],{"class":55},[49,506,507,509,511,513],{"class":51,"line":208},[49,508,212],{"class":211},[49,510,215],{"class":55},[49,512,218],{"class":211},[49,514,221],{"class":55},[49,516,517,519,521,523],{"class":51,"line":224},[49,518,227],{"class":211},[49,520,215],{"class":55},[49,522,232],{"class":211},[49,524,221],{"class":55},[49,526,527,529,531,533],{"class":51,"line":237},[49,528,240],{"class":211},[49,530,215],{"class":55},[49,532,295],{"class":211},[49,534,221],{"class":55},[49,536,537],{"class":51,"line":255},[49,538,258],{"class":55},[49,540,541],{"class":51,"line":357},[49,542,354],{"emptyLinePlaceholder":353},[49,544,545,548],{"class":51,"line":363},[49,546,547],{"class":63},".footer",[49,549,205],{"class":55},[49,551,552,554,556,558],{"class":51,"line":370},[49,553,212],{"class":211},[49,555,215],{"class":55},[49,557,218],{"class":211},[49,559,221],{"class":55},[49,561,562,565,567,569],{"class":51,"line":381},[49,563,564],{"class":211},"  bottom",[49,566,215],{"class":55},[49,568,232],{"class":211},[49,570,221],{"class":55},[49,572,574,576,578,580],{"class":51,"line":573},10,[49,575,240],{"class":211},[49,577,215],{"class":55},[49,579,245],{"class":211},[49,581,221],{"class":55},[49,583,585],{"class":51,"line":584},11,[49,586,258],{"class":55},[49,588,590],{"class":51,"line":589},12,[49,591,354],{"emptyLinePlaceholder":353},[49,593,595],{"class":51,"line":594},13,[49,596,597],{"class":251},"\u002F* Which color wins? Safari decides. *\u002F\n",[127,599,601],{"id":600},"no-override-mechanism","No Override Mechanism",[17,603,604,605,607],{},"Unlike ",[21,606,23],{},", you can't explicitly tell Safari what color to use. You're at the mercy of the derivation algorithm.",[17,609,610],{},"If your design requires a specific toolbar color that doesn't match any element's background, you have no clean solution.",[29,612,614],{"id":613},"what-this-means-for-design","What This Means for Design",[127,616,618],{"id":617},"design-with-derivation-in-mind","Design with derivation in mind",[17,620,621],{},"Your fixed header's background color is now your toolbar color. Plan accordingly.",[17,623,624],{},"If you want a white toolbar, your header needs a white (or near-white) background. If you want the toolbar to match your brand color, that color needs to exist on a fixed element.",[127,626,628],{"id":627},"transparency-is-risky","Transparency is risky",[17,630,631],{},"Semi-transparent backgrounds on fixed elements create unpredictable toolbar colors. Safari samples the computed color, which depends on what's behind the transparent layer.",[40,633,635],{"className":193,"code":634,"language":195,"meta":45,"style":45},"\u002F* Unpredictable — computed color depends on content behind *\u002F\nheader {\n  position: fixed;\n  background-color: rgba(255, 255, 255, 0.8);\n}\n\n\u002F* Predictable — Safari gets exactly this color *\u002F\nheader {\n  position: fixed;\n  background-color: #ffffff;\n}\n",[21,636,637,642,648,658,687,691,695,700,706,716,726],{"__ignoreMap":45},[49,638,639],{"class":51,"line":52},[49,640,641],{"class":251},"\u002F* Unpredictable — computed color depends on content behind *\u002F\n",[49,643,644,646],{"class":51,"line":208},[49,645,202],{"class":59},[49,647,205],{"class":55},[49,649,650,652,654,656],{"class":51,"line":224},[49,651,212],{"class":211},[49,653,215],{"class":55},[49,655,218],{"class":211},[49,657,221],{"class":55},[49,659,660,662,664,666,668,671,673,675,677,679,681,684],{"class":51,"line":237},[49,661,240],{"class":211},[49,663,215],{"class":55},[49,665,453],{"class":211},[49,667,456],{"class":55},[49,669,670],{"class":211},"255",[49,672,461],{"class":55},[49,674,670],{"class":211},[49,676,461],{"class":55},[49,678,670],{"class":211},[49,680,461],{"class":55},[49,682,683],{"class":211},"0.8",[49,685,686],{"class":55},");\n",[49,688,689],{"class":51,"line":255},[49,690,258],{"class":55},[49,692,693],{"class":51,"line":357},[49,694,354],{"emptyLinePlaceholder":353},[49,696,697],{"class":51,"line":363},[49,698,699],{"class":251},"\u002F* Predictable — Safari gets exactly this color *\u002F\n",[49,701,702,704],{"class":51,"line":370},[49,703,202],{"class":59},[49,705,205],{"class":55},[49,707,708,710,712,714],{"class":51,"line":381},[49,709,212],{"class":211},[49,711,215],{"class":55},[49,713,218],{"class":211},[49,715,221],{"class":55},[49,717,718,720,722,724],{"class":51,"line":573},[49,719,240],{"class":211},[49,721,215],{"class":55},[49,723,295],{"class":211},[49,725,221],{"class":55},[49,727,728],{"class":51,"line":584},[49,729,258],{"class":55},[17,731,732],{},"Solid colors give you control. Transparency gives Safari control.",[127,734,736],{"id":735},"test-the-overscroll","Test the overscroll",[17,738,739],{},"Pull up and down on your page. Watch what color appears in the rubber band effect. That's your body background. That's also influencing your toolbar.",[40,741,743],{"className":193,"code":742,"language":195,"meta":45,"style":45},"\u002F* Dark site with white overscroll — jarring *\u002F\nbody {\n  background-color: #ffffff;\n}\n\n.page-wrapper {\n  background-color: #1a1a1a;\n  min-height: 100vh;\n}\n\n\u002F* Dark site with matching overscroll — seamless *\u002F\nbody {\n  background-color: #1a1a1a;\n}\n",[21,744,745,750,756,766,770,774,781,791,807,811,815,820,826,836],{"__ignoreMap":45},[49,746,747],{"class":51,"line":52},[49,748,749],{"class":251},"\u002F* Dark site with white overscroll — jarring *\u002F\n",[49,751,752,754],{"class":51,"line":208},[49,753,284],{"class":59},[49,755,205],{"class":55},[49,757,758,760,762,764],{"class":51,"line":224},[49,759,240],{"class":211},[49,761,215],{"class":55},[49,763,295],{"class":211},[49,765,221],{"class":55},[49,767,768],{"class":51,"line":237},[49,769,258],{"class":55},[49,771,772],{"class":51,"line":255},[49,773,354],{"emptyLinePlaceholder":353},[49,775,776,779],{"class":51,"line":357},[49,777,778],{"class":63},".page-wrapper",[49,780,205],{"class":55},[49,782,783,785,787,789],{"class":51,"line":363},[49,784,240],{"class":211},[49,786,215],{"class":55},[49,788,245],{"class":211},[49,790,221],{"class":55},[49,792,793,796,798,801,805],{"class":51,"line":370},[49,794,795],{"class":211},"  min-height",[49,797,215],{"class":55},[49,799,800],{"class":211},"100",[49,802,804],{"class":803},"szBVR","vh",[49,806,221],{"class":55},[49,808,809],{"class":51,"line":381},[49,810,258],{"class":55},[49,812,813],{"class":51,"line":573},[49,814,354],{"emptyLinePlaceholder":353},[49,816,817],{"class":51,"line":584},[49,818,819],{"class":251},"\u002F* Dark site with matching overscroll — seamless *\u002F\n",[49,821,822,824],{"class":51,"line":589},[49,823,284],{"class":59},[49,825,205],{"class":55},[49,827,828,830,832,834],{"class":51,"line":594},[49,829,240],{"class":211},[49,831,215],{"class":55},[49,833,245],{"class":211},[49,835,221],{"class":55},[49,837,839],{"class":51,"line":838},14,[49,840,258],{"class":55},[17,842,843],{},"If your body background is white but your design is dark, you'll see jarring white flashes during overscroll.",[127,845,847],{"id":846},"accept-the-constraint","Accept the constraint",[17,849,850],{},"Apple made a design decision. Fighting it creates more problems than accepting it.",[17,852,853],{},"Design your fixed elements with toolbar tinting in mind. Choose body backgrounds that work for overscroll. Let Safari do its thing.",[29,855,857],{"id":856},"when-one-color-isnt-enough","When One Color Isn't Enough",[17,859,860],{},"The body background rule assumes your page is one color. Many designs aren't.",[17,862,863,864,866],{},"A light page with a dark footer needs two overscroll colors. Pull down at the top — you should see light. Pull up past the footer — you should see dark. One ",[21,865,101],{}," can't do both.",[17,868,869],{},"The obvious solutions don't work.",[127,871,873],{"id":872},"the-fixed-gradient","The fixed gradient",[17,875,876],{},"Split the canvas at the viewport middle:",[40,878,880],{"className":193,"code":879,"language":195,"meta":45,"style":45},"html {\n  background: linear-gradient(#f2f4f3 50%, #0b1626 50%) fixed;\n}\n",[21,881,882,888,925],{"__ignoreMap":45},[49,883,884,886],{"class":51,"line":52},[49,885,44],{"class":59},[49,887,205],{"class":55},[49,889,890,893,895,898,900,903,906,909,911,914,916,918,921,923],{"class":51,"line":208},[49,891,892],{"class":211},"  background",[49,894,215],{"class":55},[49,896,897],{"class":211},"linear-gradient",[49,899,456],{"class":55},[49,901,902],{"class":211},"#f2f4f3",[49,904,905],{"class":211}," 50",[49,907,908],{"class":803},"%",[49,910,461],{"class":55},[49,912,913],{"class":211},"#0b1626",[49,915,905],{"class":211},[49,917,908],{"class":803},[49,919,920],{"class":55},") ",[49,922,218],{"class":211},[49,924,221],{"class":55},[49,926,927],{"class":51,"line":224},[49,928,258],{"class":55},[17,930,931],{},"Works on macOS. Does nothing on iOS.",[17,933,934,935,938,939,941],{},"Safari paints the rubber band from the computed background color. Background images never reach it. And the ",[21,936,937],{},"background"," shorthand resets ",[21,940,101],{}," to transparent — you've removed the one value Safari reads.",[127,943,945],{"id":944},"the-hanging-block","The hanging block",[17,947,948],{},"Absolutely position a dark slab below the footer:",[40,950,952],{"className":193,"code":951,"language":195,"meta":45,"style":45},"footer::after {\n  content: \"\";\n  position: absolute;\n  top: 100%;\n  height: 60vh;\n  background: #0b1626;\n}\n",[21,953,954,964,976,987,999,1013,1023],{"__ignoreMap":45},[49,955,956,959,962],{"class":51,"line":52},[49,957,958],{"class":59},"footer",[49,960,961],{"class":63},"::after",[49,963,205],{"class":55},[49,965,966,969,971,974],{"class":51,"line":208},[49,967,968],{"class":211},"  content",[49,970,215],{"class":55},[49,972,973],{"class":70},"\"\"",[49,975,221],{"class":55},[49,977,978,980,982,985],{"class":51,"line":224},[49,979,212],{"class":211},[49,981,215],{"class":55},[49,983,984],{"class":211},"absolute",[49,986,221],{"class":55},[49,988,989,991,993,995,997],{"class":51,"line":237},[49,990,227],{"class":211},[49,992,215],{"class":55},[49,994,800],{"class":211},[49,996,908],{"class":803},[49,998,221],{"class":55},[49,1000,1001,1004,1006,1009,1011],{"class":51,"line":255},[49,1002,1003],{"class":211},"  height",[49,1005,215],{"class":55},[49,1007,1008],{"class":211},"60",[49,1010,804],{"class":803},[49,1012,221],{"class":55},[49,1014,1015,1017,1019,1021],{"class":51,"line":357},[49,1016,892],{"class":211},[49,1018,215],{"class":55},[49,1020,913],{"class":211},[49,1022,221],{"class":55},[49,1024,1025],{"class":51,"line":363},[49,1026,258],{"class":55},[17,1028,1029],{},"This one fails differently. Scrollable overflow on the root includes absolutely positioned boxes. The slab isn't paint-only — it's real scroll distance. Users scroll past your footer into an empty dark region.",[127,1031,1033],{"id":1032},"what-works-scroll-driven-color","What works: scroll-driven color",[17,1035,1036],{},"Drive the body color with scroll position itself:",[40,1038,1040],{"className":193,"code":1039,"language":195,"meta":45,"style":45},"@supports (animation-timeline: scroll()) {\n  html,\n  body {\n    animation: overscroll-base linear both;\n    animation-timeline: scroll(root);\n  }\n}\n\n@keyframes overscroll-base {\n  0%,\n  92% {\n    background-color: #f2f4f3;\n  }\n\n  100% {\n    background-color: #0b1626;\n  }\n}\n\nmain {\n  background-color: #f2f4f3;\n}\n",[21,1041,1042,1061,1069,1076,1092,1104,1109,1113,1117,1128,1135,1142,1153,1157,1161,1169,1180,1185,1190,1195,1203,1214],{"__ignoreMap":45},[49,1043,1044,1047,1050,1053,1055,1058],{"class":51,"line":52},[49,1045,1046],{"class":803},"@supports",[49,1048,1049],{"class":55}," (",[49,1051,1052],{"class":211},"animation-timeline",[49,1054,215],{"class":55},[49,1056,1057],{"class":211},"scroll",[49,1059,1060],{"class":55},"()) {\n",[49,1062,1063,1066],{"class":51,"line":208},[49,1064,1065],{"class":59},"  html",[49,1067,1068],{"class":55},",\n",[49,1070,1071,1074],{"class":51,"line":224},[49,1072,1073],{"class":59},"  body",[49,1075,205],{"class":55},[49,1077,1078,1081,1084,1087,1090],{"class":51,"line":237},[49,1079,1080],{"class":211},"    animation",[49,1082,1083],{"class":55},": overscroll-base ",[49,1085,1086],{"class":211},"linear",[49,1088,1089],{"class":211}," both",[49,1091,221],{"class":55},[49,1093,1094,1097,1099,1101],{"class":51,"line":255},[49,1095,1096],{"class":211},"    animation-timeline",[49,1098,215],{"class":55},[49,1100,1057],{"class":211},[49,1102,1103],{"class":55},"(root);\n",[49,1105,1106],{"class":51,"line":357},[49,1107,1108],{"class":55},"  }\n",[49,1110,1111],{"class":51,"line":363},[49,1112,258],{"class":55},[49,1114,1115],{"class":51,"line":370},[49,1116,354],{"emptyLinePlaceholder":353},[49,1118,1119,1122,1126],{"class":51,"line":381},[49,1120,1121],{"class":803},"@keyframes",[49,1123,1125],{"class":1124},"s4XuR"," overscroll-base",[49,1127,205],{"class":55},[49,1129,1130,1133],{"class":51,"line":573},[49,1131,1132],{"class":63},"  0%",[49,1134,1068],{"class":55},[49,1136,1137,1140],{"class":51,"line":584},[49,1138,1139],{"class":63},"  92%",[49,1141,205],{"class":55},[49,1143,1144,1147,1149,1151],{"class":51,"line":589},[49,1145,1146],{"class":211},"    background-color",[49,1148,215],{"class":55},[49,1150,902],{"class":211},[49,1152,221],{"class":55},[49,1154,1155],{"class":51,"line":594},[49,1156,1108],{"class":55},[49,1158,1159],{"class":51,"line":838},[49,1160,354],{"emptyLinePlaceholder":353},[49,1162,1164,1167],{"class":51,"line":1163},15,[49,1165,1166],{"class":63},"  100%",[49,1168,205],{"class":55},[49,1170,1172,1174,1176,1178],{"class":51,"line":1171},16,[49,1173,1146],{"class":211},[49,1175,215],{"class":55},[49,1177,913],{"class":211},[49,1179,221],{"class":55},[49,1181,1183],{"class":51,"line":1182},17,[49,1184,1108],{"class":55},[49,1186,1188],{"class":51,"line":1187},18,[49,1189,258],{"class":55},[49,1191,1193],{"class":51,"line":1192},19,[49,1194,354],{"emptyLinePlaceholder":353},[49,1196,1198,1201],{"class":51,"line":1197},20,[49,1199,1200],{"class":59},"main",[49,1202,205],{"class":55},[49,1204,1206,1208,1210,1212],{"class":51,"line":1205},21,[49,1207,240],{"class":211},[49,1209,215],{"class":55},[49,1211,902],{"class":211},[49,1213,221],{"class":55},[49,1215,1217],{"class":51,"line":1216},22,[49,1218,258],{"class":55},[17,1220,1221],{},"A scroll timeline clamps at its edges during the bounce. The top rubber band always sees the 0% color. The bottom one always sees 100%.",[17,1223,1224],{},"This works because overscroll is the exception to the render-time rule: it tracks live changes to the body background. The toolbar won't follow a JavaScript color change — the rubber band will.",[17,1226,1227,1228,1230],{},"Two details carry the technique. The color holds until 92%, so the page never sits in a muddy in-between shade mid-scroll. And ",[21,1229,1200],{}," stays opaque, so the transitioning body never shows through content.",[17,1232,1233,1234,1236],{},"Browsers without ",[21,1235,1052],{}," keep the static body color. They mostly don't rubber-band anyway.",[29,1238,1240],{"id":1239},"user-controls","User Controls",[17,1242,1243],{},"Users can disable color tinting entirely:",[1245,1246,1247,1254],"ul",{},[96,1248,1249,1253],{},[1250,1251,1252],"strong",{},"macOS:"," Safari → Settings → Tabs → Appearance → \"Show color in tab bar\"",[96,1255,1256,1259],{},[1250,1257,1258],{},"iOS:"," Settings → Apps → Safari → Tabs → \"Allow Website Tinting\"",[17,1261,1262],{},"When disabled, toolbars revert to system default colors. Your design should still work in this mode.",[29,1264,1266],{"id":1265},"the-bigger-picture","The Bigger Picture",[17,1268,1269],{},"Apple is betting that automated, context-aware UI is better than explicit developer control.",[17,1271,1272],{},"For most sites, this works. The toolbar picks up reasonable colors. The interface feels cohesive.",[17,1274,1275],{},"For sites with complex designs, multiple themes, or specific brand requirements, it's a constraint.",[17,1277,1278],{},"The web has always been about negotiating control between browsers and developers. iOS 26 shifts that balance toward the browser.",[17,1280,1281],{},"Whether that's progress depends on your perspective.",[29,1283,1285],{"id":1284},"summary","Summary",[93,1287,1288,1293,1296,1299,1302,1305],{},[96,1289,1290,1292],{},[21,1291,23],{}," meta tag is ignored in Safari 26+",[96,1294,1295],{},"Safari derives toolbar colors from fixed\u002Fsticky element backgrounds, then body background",[96,1297,1298],{},"This serves Apple's Liquid Glass design philosophy — content-first, dynamic, immersive",[96,1300,1301],{},"Color sampling happens at render time — JavaScript changes don't update the toolbar",[96,1303,1304],{},"Design your fixed elements knowing they determine toolbar color",[96,1306,1307],{},"Users can disable tinting entirely",[17,1309,1310],{},"The rules changed. Adapt your designs accordingly.",[29,1312,1314],{"id":1313},"references","References",[1316,1317,1318,1324],"utilities-fields",{},[1319,1320,1321],"template",{"v-slot:title":45},[17,1322,1323],{},"Apple Newsroom",[1319,1325,1326],{"v-slot:content":45},[17,1327,1328,1335],{},[1329,1330,1334],"a",{"href":1331,"rel":1332},"https:\u002F\u002Fwww.apple.com\u002Fnewsroom\u002F2025\u002F06\u002Fapple-introduces-a-delightful-and-elegant-new-software-design\u002F",[1333],"nofollow","apple.com"," — Liquid Glass announcement",[1316,1337,1338,1343],{},[1319,1339,1340],{"v-slot:title":45},[17,1341,1342],{},"WebKit Safari 26.0 Features",[1319,1344,1345],{"v-slot:content":45},[17,1346,1347,1352],{},[1329,1348,1351],{"href":1349,"rel":1350},"https:\u002F\u002Fwebkit.org\u002Fblog\u002F17333\u002Fwebkit-features-in-safari-26-0\u002F",[1333],"webkit.org"," — Safari 26 release notes",[1316,1354,1355,1360],{},[1319,1356,1357],{"v-slot:title":45},[17,1358,1359],{},"Ben Frain Analysis",[1319,1361,1362],{"v-slot:content":45},[17,1363,1364,1369],{},[1329,1365,1368],{"href":1366,"rel":1367},"https:\u002F\u002Fbenfrain.com\u002Fios26-safari-theme-color-tab-tinting-with-fixed-position-elements\u002F",[1333],"benfrain.com"," — Deep dive on theme-color removal",[1316,1371,1372,1377],{},[1319,1373,1374],{"v-slot:title":45},[17,1375,1376],{},"WebKit Bug #301756",[1319,1378,1379],{"v-slot:content":45},[17,1380,1381,1386],{},[1329,1382,1385],{"href":1383,"rel":1384},"https:\u002F\u002Fbugs.webkit.org\u002Fshow_bug.cgi?format=multiple&id=301756",[1333],"bugs.webkit.org"," — Fixed element color tinting issues",[1316,1388,1389,1394],{},[1319,1390,1391],{"v-slot:title":45},[17,1392,1393],{},"Apple Insider",[1319,1395,1396],{"v-slot:content":45},[17,1397,1398,1403],{},[1329,1399,1402],{"href":1400,"rel":1401},"https:\u002F\u002Fappleinsider.com\u002Farticles\u002F25\u002F06\u002F18\u002Fhow-safari-in-ios-26-macos-26-puts-content-first-with-liquid-glass-ui-changes",[1333],"appleinsider.com"," — Safari Liquid Glass UI analysis",[1316,1405,1406,1411],{},[1319,1407,1408],{"v-slot:title":45},[17,1409,1410],{},"Viewport Changes Guide",[1319,1412,1413],{"v-slot:content":45},[17,1414,1415,1420],{},[1329,1416,1419],{"href":1417,"rel":1418},"https:\u002F\u002Fstripearmy.medium.com\u002Fios-26-0-be-prepared-for-viewport-changes-in-safari-e867d7eace43",[1333],"medium.com"," — iOS 26 viewport behavior changes",[1422,1423,1424],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":45,"searchDepth":208,"depth":208,"links":1426},[1427,1428,1433,1438,1443,1449,1454,1455,1456,1457],{"id":31,"depth":208,"text":32},{"id":121,"depth":208,"text":122,"children":1429},[1430,1431,1432],{"id":129,"depth":224,"text":130},{"id":145,"depth":224,"text":146},{"id":155,"depth":224,"text":156},{"id":168,"depth":208,"text":169,"children":1434},[1435,1436,1437],{"id":175,"depth":224,"text":176},{"id":267,"depth":224,"text":268},{"id":386,"depth":224,"text":387},{"id":400,"depth":208,"text":401,"children":1439},[1440,1441,1442],{"id":407,"depth":224,"text":408},{"id":488,"depth":224,"text":489},{"id":600,"depth":224,"text":601},{"id":613,"depth":208,"text":614,"children":1444},[1445,1446,1447,1448],{"id":617,"depth":224,"text":618},{"id":627,"depth":224,"text":628},{"id":735,"depth":224,"text":736},{"id":846,"depth":224,"text":847},{"id":856,"depth":208,"text":857,"children":1450},[1451,1452,1453],{"id":872,"depth":224,"text":873},{"id":944,"depth":224,"text":945},{"id":1032,"depth":224,"text":1033},{"id":1239,"depth":208,"text":1240},{"id":1265,"depth":208,"text":1266},{"id":1284,"depth":208,"text":1285},{"id":1313,"depth":208,"text":1314},null,"2026-01-15","Apple dropped theme-color meta tags. Understanding why Safari now derives toolbar colors from your CSS, and how Liquid Glass changed the rules.",false,"mdc","iOS 26 Safari Toolbar Colors","iOS 26 Toolbar Colors",{},"\u002Fblog\u002Fios26-safari-toolbar-colors",{"title":6,"description":1460},"blog\u002Fios26-safari-toolbar-colors",[1470,1471,195,1472,1473],"ios","safari","apple","design","swiss_precision","eT5AeEMyNMknaf6R9poikfWJI04HWAyHcJkQ1fItf2M",[1458,1477],{"id":1478,"title":1479,"author":7,"body":1480,"brandColor":1458,"colorBg":1458,"colorBgSecondary":1458,"colorBrand":1458,"colorFooter":1458,"colorFooterText":1458,"colorHeaders":1458,"colorInvertedText":1458,"colorText":1458,"colorTopbar":1458,"coverImage":1458,"date":1459,"description":3341,"draft":1461,"extension":1462,"galleryDark":1461,"galleryImage":1458,"gallerySize":1458,"h1":1485,"hoverVideo":1458,"label":3342,"meta":3343,"navigation":353,"order":208,"path":3344,"seo":3345,"stem":3346,"tags":3347,"theme":1474,"__hash__":3352},"blog\u002Fblog\u002Fbun-nuxt4-runtime-guide.mdc","Bun Runtime with Nuxt 4: What Works, What Breaks, What to Do - Ben Nasedkin",{"type":9,"value":1481,"toc":3287},[1482,1486,1489,1493,1496,1522,1526,1529,1532,1536,1544,1547,1550,1556,1560,1564,1567,1603,1607,1610,1650,1656,1660,1667,1724,1727,1749,1753,1764,1768,1772,1778,1781,1785,1792,1798,1801,1872,1876,1879,1882,1886,1892,1898,1902,1913,1916,1925,1929,1935,1938,1993,1997,2003,2007,2110,2114,2117,2131,2137,2141,2197,2201,2204,2208,2215,2221,2224,2233,2246,2250,2255,2275,2281,2286,2289,2338,2343,2346,2367,2371,2374,2455,2459,2462,2521,2525,2532,2559,2563,2567,2627,2631,2634,2637,2640,2644,2648,2662,2666,2680,2684,2688,2696,2722,2739,2743,2848,2852,2892,2900,2904,2908,2994,2998,3021,3025,3028,3102,3105,3107,3110,3136,3139,3141,3158,3175,3192,3209,3225,3239,3255,3269,3284],[12,1483,1485],{"id":1484},"bun-runtime-with-nuxt-4","Bun Runtime with Nuxt 4",[17,1487,1488],{},"Bun promises faster installs, native TypeScript, and better performance. Nuxt 4 supports it. But the reality is more nuanced.",[29,1490,1492],{"id":1491},"the-promise","The Promise",[17,1494,1495],{},"Bun offers significant improvements over Node.js:",[93,1497,1498,1504,1510,1516],{},[96,1499,1500,1503],{},[1250,1501,1502],{},"4x faster package installs"," — Native resolver, no intermediate steps",[96,1505,1506,1509],{},[1250,1507,1508],{},"Native TypeScript"," — No transpilation required",[96,1511,1512,1515],{},[1250,1513,1514],{},"Faster HTTP"," — Up to 2.8x more requests per second",[96,1517,1518,1521],{},[1250,1519,1520],{},"Single binary"," — Runtime, bundler, package manager in one",[29,1523,1525],{"id":1524},"current-status","Current Status",[17,1527,1528],{},"Nuxt officially supports Bun since version 3.6. Nuxt 4 continues this support through Nitro's Bun preset.",[17,1530,1531],{},"The catch: support does not mean parity. Several edge cases break.",[127,1533,1535],{"id":1534},"recommended-versions","Recommended Versions",[40,1537,1542],{"className":1538,"code":1540,"language":1541},[1539],"language-text","bun@1.3.6 with nuxt@4.2.2\n","text",[21,1543,1540],{"__ignoreMap":45},[17,1545,1546],{},"Latest stable as of January 2026. Bun joined Anthropic in December 2025 — expect tighter integration with AI tooling.",[17,1548,1549],{},"Avoid Bun 1.2.14 through 1.2.20. Socket connection errors plague these versions with Nuxt.",[17,1551,1552,1555],{},[1250,1553,1554],{},"Note:"," Nuxt 3 reaches end of maintenance at the end of January 2026. Migrate to Nuxt 4 if you haven't already.",[29,1557,1559],{"id":1558},"configuration","Configuration",[127,1561,1563],{"id":1562},"basic-setup","Basic Setup",[17,1565,1566],{},"Initialize a new project:",[40,1568,1572],{"className":1569,"code":1570,"language":1571,"meta":45,"style":45},"language-bash shiki shiki-themes github-light github-dark","bunx nuxi init my-app\ncd my-app\nbun install\n","bash",[21,1573,1574,1588,1595],{"__ignoreMap":45},[49,1575,1576,1579,1582,1585],{"class":51,"line":52},[49,1577,1578],{"class":63},"bunx",[49,1580,1581],{"class":70}," nuxi",[49,1583,1584],{"class":70}," init",[49,1586,1587],{"class":70}," my-app\n",[49,1589,1590,1593],{"class":51,"line":208},[49,1591,1592],{"class":211},"cd",[49,1594,1587],{"class":70},[49,1596,1597,1600],{"class":51,"line":224},[49,1598,1599],{"class":63},"bun",[49,1601,1602],{"class":70}," install\n",[127,1604,1606],{"id":1605},"development","Development",[17,1608,1609],{},"Two modes exist:",[40,1611,1613],{"className":1569,"code":1612,"language":1571,"meta":45,"style":45},"# Uses Node.js runtime (default)\nbun run dev\n\n# Uses Bun runtime\nbun --bun run dev\n",[21,1614,1615,1620,1630,1634,1639],{"__ignoreMap":45},[49,1616,1617],{"class":51,"line":52},[49,1618,1619],{"class":251},"# Uses Node.js runtime (default)\n",[49,1621,1622,1624,1627],{"class":51,"line":208},[49,1623,1599],{"class":63},[49,1625,1626],{"class":70}," run",[49,1628,1629],{"class":70}," dev\n",[49,1631,1632],{"class":51,"line":224},[49,1633,354],{"emptyLinePlaceholder":353},[49,1635,1636],{"class":51,"line":237},[49,1637,1638],{"class":251},"# Uses Bun runtime\n",[49,1640,1641,1643,1646,1648],{"class":51,"line":255},[49,1642,1599],{"class":63},[49,1644,1645],{"class":211}," --bun",[49,1647,1626],{"class":70},[49,1649,1629],{"class":70},[17,1651,162,1652,1655],{},[21,1653,1654],{},"--bun"," flag forces the Bun runtime. Without it, the Nuxt CLI falls back to Node.js.",[127,1657,1659],{"id":1658},"production-build","Production Build",[17,1661,1662,1663,1666],{},"Configure the Nitro preset in ",[21,1664,1665],{},"nuxt.config.ts",":",[40,1668,1672],{"className":1669,"code":1670,"language":1671,"meta":45,"style":45},"language-typescript shiki shiki-themes github-light github-dark","export default defineNuxtConfig({\n  compatibilityDate: '2025-01-14',\n\n  nitro: {\n    preset: 'bun'\n  }\n})\n","typescript",[21,1673,1674,1688,1698,1702,1707,1715,1719],{"__ignoreMap":45},[49,1675,1676,1679,1682,1685],{"class":51,"line":52},[49,1677,1678],{"class":803},"export",[49,1680,1681],{"class":803}," default",[49,1683,1684],{"class":63}," defineNuxtConfig",[49,1686,1687],{"class":55},"({\n",[49,1689,1690,1693,1696],{"class":51,"line":208},[49,1691,1692],{"class":55},"  compatibilityDate: ",[49,1694,1695],{"class":70},"'2025-01-14'",[49,1697,1068],{"class":55},[49,1699,1700],{"class":51,"line":224},[49,1701,354],{"emptyLinePlaceholder":353},[49,1703,1704],{"class":51,"line":237},[49,1705,1706],{"class":55},"  nitro: {\n",[49,1708,1709,1712],{"class":51,"line":255},[49,1710,1711],{"class":55},"    preset: ",[49,1713,1714],{"class":70},"'bun'\n",[49,1716,1717],{"class":51,"line":357},[49,1718,1108],{"class":55},[49,1720,1721],{"class":51,"line":363},[49,1722,1723],{"class":55},"})\n",[17,1725,1726],{},"Or set via environment variable:",[40,1728,1730],{"className":1569,"code":1729,"language":1571,"meta":45,"style":45},"NITRO_PRESET=bun bun run build\n",[21,1731,1732],{"__ignoreMap":45},[49,1733,1734,1737,1739,1741,1744,1746],{"class":51,"line":52},[49,1735,1736],{"class":55},"NITRO_PRESET",[49,1738,67],{"class":803},[49,1740,1599],{"class":70},[49,1742,1743],{"class":63}," bun",[49,1745,1626],{"class":70},[49,1747,1748],{"class":70}," build\n",[127,1750,1752],{"id":1751},"why-the-preset-matters","Why the Preset Matters",[17,1754,1755,1756,1759,1760,1763],{},"The default ",[21,1757,1758],{},"node-server"," preset does not bundle Bun-specific exports. If your app uses packages with Bun-specific features (like ",[21,1761,1762],{},"bun:sqlite","), production builds break without the Bun preset.",[29,1765,1767],{"id":1766},"known-issues","Known Issues",[127,1769,1771],{"id":1770},"socket-errors-on-windows","Socket Errors on Windows",[40,1773,1776],{"className":1774,"code":1775,"language":1541},[1539],"ENOENT: no such file or directory, listen '\\\\.\\pipe\\nuxt-dev-XXXX.sock'\n",[21,1777,1775],{"__ignoreMap":45},[17,1779,1780],{},"Bun 1.2.14–1.2.20 fails on Windows with Nuxt 4. The workaround: use WSL.",[127,1782,1784],{"id":1783},"hmr-breaks-with-bun-runtime","HMR Breaks with Bun Runtime",[17,1786,1787,1788,1791],{},"When using ",[21,1789,1790],{},"bun --bun run dev",", WebSocket connections fail:",[40,1793,1796],{"className":1794,"code":1795,"language":1541},[1539],"WebSocket connection to 'ws:\u002F\u002Flocalhost:24678\u002F_nuxt\u002F' failed\n[vite] server connection lost\n",[21,1797,1795],{"__ignoreMap":45},[17,1799,1800],{},"Fix by enabling polling:",[40,1802,1804],{"className":1669,"code":1803,"language":1671,"meta":45,"style":45},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  vite: {\n    server: {\n      watch: {\n        usePolling: true,\n        interval: 100\n      }\n    }\n  }\n})\n",[21,1805,1806,1811,1821,1826,1831,1836,1846,1854,1859,1864,1868],{"__ignoreMap":45},[49,1807,1808],{"class":51,"line":52},[49,1809,1810],{"class":251},"\u002F\u002F nuxt.config.ts\n",[49,1812,1813,1815,1817,1819],{"class":51,"line":208},[49,1814,1678],{"class":803},[49,1816,1681],{"class":803},[49,1818,1684],{"class":63},[49,1820,1687],{"class":55},[49,1822,1823],{"class":51,"line":224},[49,1824,1825],{"class":55},"  vite: {\n",[49,1827,1828],{"class":51,"line":237},[49,1829,1830],{"class":55},"    server: {\n",[49,1832,1833],{"class":51,"line":255},[49,1834,1835],{"class":55},"      watch: {\n",[49,1837,1838,1841,1844],{"class":51,"line":357},[49,1839,1840],{"class":55},"        usePolling: ",[49,1842,1843],{"class":211},"true",[49,1845,1068],{"class":55},[49,1847,1848,1851],{"class":51,"line":363},[49,1849,1850],{"class":55},"        interval: ",[49,1852,1853],{"class":211},"100\n",[49,1855,1856],{"class":51,"line":370},[49,1857,1858],{"class":55},"      }\n",[49,1860,1861],{"class":51,"line":381},[49,1862,1863],{"class":55},"    }\n",[49,1865,1866],{"class":51,"line":573},[49,1867,1108],{"class":55},[49,1869,1870],{"class":51,"line":584},[49,1871,1723],{"class":55},[127,1873,1875],{"id":1874},"_400-errors-on-non-get-requests","400 Errors on Non-GET Requests",[17,1877,1878],{},"All POST, PUT, DELETE requests return 400 in dev mode when using the Bun runtime or preset.",[17,1880,1881],{},"This only affects development. Production builds work correctly.",[127,1883,1885],{"id":1884},"fsevents-crashes-on-macos","fsevents Crashes on macOS",[40,1887,1890],{"className":1888,"code":1889,"language":1541},[1539],"Assertion failed: function fse_dispatch_event, file fsevents.c, line 151\n",[21,1891,1889],{"__ignoreMap":45},[17,1893,1894,1895,1897],{},"Affects macOS with Nuxt 3.16.0+ and Bun 1.2.4+. Workaround: run without the ",[21,1896,1654],{}," flag.",[127,1899,1901],{"id":1900},"memory-leak-in-dev-mode","Memory Leak in Dev Mode",[17,1903,1904,1905,1908,1909,1912],{},"When running ",[21,1906,1907],{},"nuxt dev"," with ",[21,1910,1911],{},"compatibilityVersion: 4",", memory usage climbs steadily. Starts at ~500MB, reaches 6GB after 5 minutes.",[17,1914,1915],{},"Only affects Bun runtime in development. Production builds and Node.js runtime work fine.",[17,1917,1918,1919,1924],{},"Tracked in ",[1329,1920,1923],{"href":1921,"rel":1922},"https:\u002F\u002Fgithub.com\u002Foven-sh\u002Fbun\u002Fissues\u002F16219",[1333],"GitHub Issue #16219",".",[127,1926,1928],{"id":1927},"crossws-module-error","crossws Module Error",[40,1930,1933],{"className":1931,"code":1932,"language":1541},[1539],"RollupError: This module cannot be imported in server runtime.\n[importing crossws\u002Fdist\u002Fadapters\u002Fbun.mjs]\n",[21,1934,1932],{"__ignoreMap":45},[17,1936,1937],{},"Add to your config:",[40,1939,1941],{"className":1669,"code":1940,"language":1671,"meta":45,"style":45},"export default defineNuxtConfig({\n  nitro: {\n    preset: 'bun',\n    rollupConfig: {\n      external: ['bun']\n    }\n  }\n})\n",[21,1942,1943,1953,1957,1966,1971,1981,1985,1989],{"__ignoreMap":45},[49,1944,1945,1947,1949,1951],{"class":51,"line":52},[49,1946,1678],{"class":803},[49,1948,1681],{"class":803},[49,1950,1684],{"class":63},[49,1952,1687],{"class":55},[49,1954,1955],{"class":51,"line":208},[49,1956,1706],{"class":55},[49,1958,1959,1961,1964],{"class":51,"line":224},[49,1960,1711],{"class":55},[49,1962,1963],{"class":70},"'bun'",[49,1965,1068],{"class":55},[49,1967,1968],{"class":51,"line":237},[49,1969,1970],{"class":55},"    rollupConfig: {\n",[49,1972,1973,1976,1978],{"class":51,"line":255},[49,1974,1975],{"class":55},"      external: [",[49,1977,1963],{"class":70},[49,1979,1980],{"class":55},"]\n",[49,1982,1983],{"class":51,"line":357},[49,1984,1863],{"class":55},[49,1986,1987],{"class":51,"line":363},[49,1988,1108],{"class":55},[49,1990,1991],{"class":51,"line":370},[49,1992,1723],{"class":55},[29,1994,1996],{"id":1995},"bun-sqlite","Bun SQLite",[17,1998,1999,2000,2002],{},"Bun ships with a native SQLite driver via ",[21,2001,1762],{},". Zero dependencies, fast, and built-in.",[127,2004,2006],{"id":2005},"using-bunsqlite-in-server-routes","Using bun:sqlite in Server Routes",[40,2008,2010],{"className":1669,"code":2009,"language":1671,"meta":45,"style":45},"\u002F\u002F server\u002Fapi\u002Fusers.get.ts\nimport { Database } from 'bun:sqlite'\n\nconst db = new Database('mydb.sqlite')\n\nexport default defineEventHandler(() => {\n  return db.query('SELECT * FROM users').all()\n})\n",[21,2011,2012,2017,2031,2035,2060,2064,2081,2106],{"__ignoreMap":45},[49,2013,2014],{"class":51,"line":52},[49,2015,2016],{"class":251},"\u002F\u002F server\u002Fapi\u002Fusers.get.ts\n",[49,2018,2019,2022,2025,2028],{"class":51,"line":208},[49,2020,2021],{"class":803},"import",[49,2023,2024],{"class":55}," { Database } ",[49,2026,2027],{"class":803},"from",[49,2029,2030],{"class":70}," 'bun:sqlite'\n",[49,2032,2033],{"class":51,"line":224},[49,2034,354],{"emptyLinePlaceholder":353},[49,2036,2037,2040,2043,2046,2049,2052,2054,2057],{"class":51,"line":237},[49,2038,2039],{"class":803},"const",[49,2041,2042],{"class":211}," db",[49,2044,2045],{"class":803}," =",[49,2047,2048],{"class":803}," new",[49,2050,2051],{"class":63}," Database",[49,2053,456],{"class":55},[49,2055,2056],{"class":70},"'mydb.sqlite'",[49,2058,2059],{"class":55},")\n",[49,2061,2062],{"class":51,"line":255},[49,2063,354],{"emptyLinePlaceholder":353},[49,2065,2066,2068,2070,2073,2076,2079],{"class":51,"line":357},[49,2067,1678],{"class":803},[49,2069,1681],{"class":803},[49,2071,2072],{"class":63}," defineEventHandler",[49,2074,2075],{"class":55},"(() ",[49,2077,2078],{"class":803},"=>",[49,2080,205],{"class":55},[49,2082,2083,2086,2089,2092,2094,2097,2100,2103],{"class":51,"line":363},[49,2084,2085],{"class":803},"  return",[49,2087,2088],{"class":55}," db.",[49,2090,2091],{"class":63},"query",[49,2093,456],{"class":55},[49,2095,2096],{"class":70},"'SELECT * FROM users'",[49,2098,2099],{"class":55},").",[49,2101,2102],{"class":63},"all",[49,2104,2105],{"class":55},"()\n",[49,2107,2108],{"class":51,"line":370},[49,2109,1723],{"class":55},[127,2111,2113],{"id":2112},"the-catch","The Catch",[17,2115,2116],{},"This only works when:",[93,2118,2119,2125],{},[96,2120,2121,2122,2124],{},"Running with Bun runtime (",[21,2123,1790],{}," or production with Bun preset)",[96,2126,2127,2128],{},"Building with ",[21,2129,2130],{},"nitro.preset: 'bun'",[17,2132,2133,2134,2136],{},"Without the Bun preset, production builds use Node.js and ",[21,2135,1762],{}," imports fail.",[127,2138,2140],{"id":2139},"configuration-for-bunsqlite","Configuration for bun:sqlite",[40,2142,2144],{"className":1669,"code":2143,"language":1671,"meta":45,"style":45},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'bun',\n    rollupConfig: {\n      external: ['bun:sqlite']\n    }\n  }\n})\n",[21,2145,2146,2150,2160,2164,2172,2176,2185,2189,2193],{"__ignoreMap":45},[49,2147,2148],{"class":51,"line":52},[49,2149,1810],{"class":251},[49,2151,2152,2154,2156,2158],{"class":51,"line":208},[49,2153,1678],{"class":803},[49,2155,1681],{"class":803},[49,2157,1684],{"class":63},[49,2159,1687],{"class":55},[49,2161,2162],{"class":51,"line":224},[49,2163,1706],{"class":55},[49,2165,2166,2168,2170],{"class":51,"line":237},[49,2167,1711],{"class":55},[49,2169,1963],{"class":70},[49,2171,1068],{"class":55},[49,2173,2174],{"class":51,"line":255},[49,2175,1970],{"class":55},[49,2177,2178,2180,2183],{"class":51,"line":357},[49,2179,1975],{"class":55},[49,2181,2182],{"class":70},"'bun:sqlite'",[49,2184,1980],{"class":55},[49,2186,2187],{"class":51,"line":363},[49,2188,1863],{"class":55},[49,2190,2191],{"class":51,"line":370},[49,2192,1108],{"class":55},[49,2194,2195],{"class":51,"line":381},[49,2196,1723],{"class":55},[29,2198,2200],{"id":2199},"nuxt-content-and-sqlite","Nuxt Content and SQLite",[17,2202,2203],{},"Nuxt Content v3 uses SQLite internally. This creates friction with Bun.",[127,2205,2207],{"id":2206},"the-problem","The Problem",[17,2209,2210,2211,2214],{},"Nuxt Content depends on ",[21,2212,2213],{},"better-sqlite3"," for Node.js. This native module doesn't compile for Bun — different ABI versions.",[40,2216,2219],{"className":2217,"code":2218,"language":1541},[1539],"Error: The module 'better_sqlite3' was compiled against a different Node.js ABI version\n",[21,2220,2218],{"__ignoreMap":45},[127,2222,1525],{"id":2223},"current-status-1",[17,2225,2226,2227,2229,2230,2232],{},"Nuxt Content should auto-detect Bun and use ",[21,2228,1762],{}," instead of ",[21,2231,2213],{},". In practice, detection fails in some scenarios.",[17,2234,1918,2235,2240,2241,1924],{},[1329,2236,2239],{"href":2237,"rel":2238},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fcontent\u002Fissues\u002F2936",[1333],"GitHub Issue #2936"," and ",[1329,2242,2245],{"href":2243,"rel":2244},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fcontent\u002Fissues\u002F3118",[1333],"Issue #3118",[127,2247,2249],{"id":2248},"workarounds","Workarounds",[17,2251,2252],{},[1250,2253,2254],{},"Option 1: Install with npm, run with Bun",[40,2256,2258],{"className":1569,"code":2257,"language":1571,"meta":45,"style":45},"npm install\nbun run dev\n",[21,2259,2260,2267],{"__ignoreMap":45},[49,2261,2262,2265],{"class":51,"line":52},[49,2263,2264],{"class":63},"npm",[49,2266,1602],{"class":70},[49,2268,2269,2271,2273],{"class":51,"line":208},[49,2270,1599],{"class":63},[49,2272,1626],{"class":70},[49,2274,1629],{"class":70},[17,2276,2277,2278,2280],{},"This bypasses the ",[21,2279,2213],{}," compilation issue during install.",[17,2282,2283],{},[1250,2284,2285],{},"Option 2: Use Node.js native SQLite (v22.5+)",[17,2287,2288],{},"If you're on Node.js 22.5+, enable experimental native SQLite:",[40,2290,2292],{"className":1669,"code":2291,"language":1671,"meta":45,"style":45},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  content: {\n    experimental: {\n      nativeSqlite: true\n    }\n  }\n})\n",[21,2293,2294,2298,2308,2313,2318,2326,2330,2334],{"__ignoreMap":45},[49,2295,2296],{"class":51,"line":52},[49,2297,1810],{"class":251},[49,2299,2300,2302,2304,2306],{"class":51,"line":208},[49,2301,1678],{"class":803},[49,2303,1681],{"class":803},[49,2305,1684],{"class":63},[49,2307,1687],{"class":55},[49,2309,2310],{"class":51,"line":224},[49,2311,2312],{"class":55},"  content: {\n",[49,2314,2315],{"class":51,"line":237},[49,2316,2317],{"class":55},"    experimental: {\n",[49,2319,2320,2323],{"class":51,"line":255},[49,2321,2322],{"class":55},"      nativeSqlite: ",[49,2324,2325],{"class":211},"true\n",[49,2327,2328],{"class":51,"line":357},[49,2329,1863],{"class":55},[49,2331,2332],{"class":51,"line":363},[49,2333,1108],{"class":55},[49,2335,2336],{"class":51,"line":370},[49,2337,1723],{"class":55},[17,2339,2340],{},[1250,2341,2342],{},"Option 3: Skip Nuxt Content for Bun projects",[17,2344,2345],{},"If you need full Bun runtime in production, consider alternatives:",[1245,2347,2348,2355,2364],{},[96,2349,2350,2351,2354],{},"Static markdown with ",[21,2352,2353],{},"@nuxt\u002Fcontent"," in prerender mode",[96,2356,2357,2358,183,2361],{},"Custom markdown parsing with ",[21,2359,2360],{},"marked",[21,2362,2363],{},"remark",[96,2365,2366],{},"External CMS (Strapi, Sanity, Contentful)",[127,2368,2370],{"id":2369},"production-builds","Production Builds",[17,2372,2373],{},"Nuxt Content works in production builds if you prerender content at build time. The SQLite database gets bundled into the output.",[40,2375,2377],{"className":1669,"code":2376,"language":1671,"meta":45,"style":45},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  content: {\n    database: {\n      type: 'sqlite',\n      filename: ':memory:'\n    }\n  },\n  routeRules: {\n    '\u002Fblog\u002F**': { prerender: true }\n  }\n})\n",[21,2378,2379,2383,2393,2397,2402,2412,2420,2424,2429,2434,2447,2451],{"__ignoreMap":45},[49,2380,2381],{"class":51,"line":52},[49,2382,1810],{"class":251},[49,2384,2385,2387,2389,2391],{"class":51,"line":208},[49,2386,1678],{"class":803},[49,2388,1681],{"class":803},[49,2390,1684],{"class":63},[49,2392,1687],{"class":55},[49,2394,2395],{"class":51,"line":224},[49,2396,2312],{"class":55},[49,2398,2399],{"class":51,"line":237},[49,2400,2401],{"class":55},"    database: {\n",[49,2403,2404,2407,2410],{"class":51,"line":255},[49,2405,2406],{"class":55},"      type: ",[49,2408,2409],{"class":70},"'sqlite'",[49,2411,1068],{"class":55},[49,2413,2414,2417],{"class":51,"line":357},[49,2415,2416],{"class":55},"      filename: ",[49,2418,2419],{"class":70},"':memory:'\n",[49,2421,2422],{"class":51,"line":363},[49,2423,1863],{"class":55},[49,2425,2426],{"class":51,"line":370},[49,2427,2428],{"class":55},"  },\n",[49,2430,2431],{"class":51,"line":381},[49,2432,2433],{"class":55},"  routeRules: {\n",[49,2435,2436,2439,2442,2444],{"class":51,"line":573},[49,2437,2438],{"class":70},"    '\u002Fblog\u002F**'",[49,2440,2441],{"class":55},": { prerender: ",[49,2443,1843],{"class":211},[49,2445,2446],{"class":55}," }\n",[49,2448,2449],{"class":51,"line":584},[49,2450,1108],{"class":55},[49,2452,2453],{"class":51,"line":589},[49,2454,1723],{"class":55},[29,2456,2458],{"id":2457},"module-compatibility","Module Compatibility",[17,2460,2461],{},"Some Nuxt modules have known issues with Bun:",[2463,2464,2465,2478],"table",{},[2466,2467,2468],"thead",{},[2469,2470,2471,2475],"tr",{},[2472,2473,2474],"th",{},"Module",[2472,2476,2477],{},"Issue",[2479,2480,2481,2489,2497,2505,2513],"tbody",{},[2469,2482,2483,2486],{},[2484,2485,2353],"td",{},[2484,2487,2488],{},"better-sqlite3 ABI mismatch",[2469,2490,2491,2494],{},[2484,2492,2493],{},"@prisma\u002Fnuxt",[2484,2495,2496],{},"Freezes during client generation",[2469,2498,2499,2502],{},[2484,2500,2501],{},"@nuxtjs\u002Fstorybook",[2484,2503,2504],{},"Fails to detect Bun as package manager",[2469,2506,2507,2510],{},[2484,2508,2509],{},"nuxt-modules\u002Fsupabase",[2484,2511,2512],{},"Installation errors",[2469,2514,2515,2518],{},[2484,2516,2517],{},"wrangler\u002Fnitro-cloudflare-dev",[2484,2519,2520],{},"Fails with Bun",[127,2522,2524],{"id":2523},"prisma-workaround","Prisma Workaround",[17,2526,2527,2528,2531],{},"Delete ",[21,2529,2530],{},"bun.lockb"," before first dev run:",[40,2533,2535],{"className":1569,"code":2534,"language":1571,"meta":45,"style":45},"rm bun.lockb\nbun install\nbun run dev\n",[21,2536,2537,2545,2551],{"__ignoreMap":45},[49,2538,2539,2542],{"class":51,"line":52},[49,2540,2541],{"class":63},"rm",[49,2543,2544],{"class":70}," bun.lockb\n",[49,2546,2547,2549],{"class":51,"line":208},[49,2548,1599],{"class":63},[49,2550,1602],{"class":70},[49,2552,2553,2555,2557],{"class":51,"line":224},[49,2554,1599],{"class":63},[49,2556,1626],{"class":70},[49,2558,1629],{"class":70},[29,2560,2562],{"id":2561},"performance-reality","Performance Reality",[127,2564,2566],{"id":2565},"benchmarks-look-great","Benchmarks Look Great",[2463,2568,2569,2585],{},[2466,2570,2571],{},[2469,2572,2573,2576,2579,2582],{},[2472,2574,2575],{},"Metric",[2472,2577,2578],{},"Bun",[2472,2580,2581],{},"Node.js",[2472,2583,2584],{},"Improvement",[2479,2586,2587,2601,2615],{},[2469,2588,2589,2592,2595,2598],{},[2484,2590,2591],{},"HTTP Requests\u002Fsec",[2484,2593,2594],{},"~180,000",[2484,2596,2597],{},"~65,000",[2484,2599,2600],{},"2.8x",[2469,2602,2603,2606,2609,2612],{},[2484,2604,2605],{},"Package Install",[2484,2607,2608],{},"4.2x faster",[2484,2610,2611],{},"Baseline",[2484,2613,2614],{},"4.2x",[2469,2616,2617,2620,2623,2625],{},[2484,2618,2619],{},"TypeScript Transpile",[2484,2621,2622],{},"2.8x faster",[2484,2624,2611],{},[2484,2626,2600],{},[127,2628,2630],{"id":2629},"production-reality","Production Reality",[17,2632,2633],{},"Hello-world benchmarks show dramatic improvements. Standard CRUD operations show comparable performance.",[17,2635,2636],{},"Cold-start time in serverless can be higher for Bun. Memory usage may increase in some scenarios.",[17,2638,2639],{},"Test your actual workload. Benchmarks lie.",[29,2641,2643],{"id":2642},"when-to-use-bun","When to Use Bun",[127,2645,2647],{"id":2646},"good-candidates","Good Candidates",[1245,2649,2650,2653,2656,2659],{},[96,2651,2652],{},"Greenfield projects — Native TypeScript, faster feedback",[96,2654,2655],{},"Side projects — Speed compounds when iterating",[96,2657,2658],{},"CI\u002FCD pipelines — 4x faster package installs matter",[96,2660,2661],{},"Serverless deployments — Lower cold-start latency",[127,2663,2665],{"id":2664},"stick-with-nodejs","Stick with Node.js",[1245,2667,2668,2671,2674,2677],{},[96,2669,2670],{},"Large enterprise codebases — Migration rarely pays off",[96,2672,2673],{},"Heavy native module usage — Better compatibility",[96,2675,2676],{},"Windows development — Known socket issues",[96,2678,2679],{},"Maximum stability required — Node.js has decades of battle-testing",[29,2681,2683],{"id":2682},"production-checklist","Production Checklist",[127,2685,2687],{"id":2686},"before-deployment","Before Deployment",[93,2689,2690],{},[96,2691,2692,2693,1666],{},"Lock Bun version in ",[21,2694,2695],{},"package.json",[40,2697,2701],{"className":2698,"code":2699,"language":2700,"meta":45,"style":45},"language-json shiki shiki-themes github-light github-dark","{\n  \"packageManager\": \"bun@1.3.6\"\n}\n","json",[21,2702,2703,2708,2718],{"__ignoreMap":45},[49,2704,2705],{"class":51,"line":52},[49,2706,2707],{"class":55},"{\n",[49,2709,2710,2713,2715],{"class":51,"line":208},[49,2711,2712],{"class":211},"  \"packageManager\"",[49,2714,215],{"class":55},[49,2716,2717],{"class":70},"\"bun@1.3.6\"\n",[49,2719,2720],{"class":51,"line":224},[49,2721,258],{"class":55},[93,2723,2724,2727,2733],{"start":208},[96,2725,2726],{},"Test all HTTP methods work",[96,2728,2729,2730],{},"Build locally first — ",[21,2731,2732],{},"NITRO_PRESET=bun bun run build",[96,2734,2735,2736],{},"Run the production build — ",[21,2737,2738],{},"bun run .output\u002Fserver\u002Findex.mjs",[127,2740,2742],{"id":2741},"docker-configuration","Docker Configuration",[40,2744,2748],{"className":2745,"code":2746,"language":2747,"meta":45,"style":45},"language-dockerfile shiki shiki-themes github-light github-dark","# Build Stage\nFROM oven\u002Fbun:1-alpine AS build\nWORKDIR \u002Fapp\nCOPY package.json bun.lock* .\u002F\nRUN bun install --frozen-lockfile --ignore-scripts\nCOPY . .\nENV NITRO_PRESET=bun\nRUN bun run build\n\n# Production Stage\nFROM oven\u002Fbun:1-alpine AS production\nWORKDIR \u002Fapp\nRUN addgroup --system --gid 1001 nuxt \\\n    && adduser --system --uid 1001 nuxt\nCOPY --from=build --chown=nuxt:nuxt \u002Fapp\u002F.output .\u002F.output\nUSER nuxt\nENV HOST=0.0.0.0\nENV PORT=3000\nEXPOSE 3000\nCMD [\"bun\", \"--bun\", \"run\", \".output\u002Fserver\u002Findex.mjs\"]\n","dockerfile",[21,2749,2750,2755,2760,2765,2770,2775,2780,2785,2790,2794,2799,2804,2808,2813,2818,2823,2828,2833,2838,2843],{"__ignoreMap":45},[49,2751,2752],{"class":51,"line":52},[49,2753,2754],{},"# Build Stage\n",[49,2756,2757],{"class":51,"line":208},[49,2758,2759],{},"FROM oven\u002Fbun:1-alpine AS build\n",[49,2761,2762],{"class":51,"line":224},[49,2763,2764],{},"WORKDIR \u002Fapp\n",[49,2766,2767],{"class":51,"line":237},[49,2768,2769],{},"COPY package.json bun.lock* .\u002F\n",[49,2771,2772],{"class":51,"line":255},[49,2773,2774],{},"RUN bun install --frozen-lockfile --ignore-scripts\n",[49,2776,2777],{"class":51,"line":357},[49,2778,2779],{},"COPY . .\n",[49,2781,2782],{"class":51,"line":363},[49,2783,2784],{},"ENV NITRO_PRESET=bun\n",[49,2786,2787],{"class":51,"line":370},[49,2788,2789],{},"RUN bun run build\n",[49,2791,2792],{"class":51,"line":381},[49,2793,354],{"emptyLinePlaceholder":353},[49,2795,2796],{"class":51,"line":573},[49,2797,2798],{},"# Production Stage\n",[49,2800,2801],{"class":51,"line":584},[49,2802,2803],{},"FROM oven\u002Fbun:1-alpine AS production\n",[49,2805,2806],{"class":51,"line":589},[49,2807,2764],{},[49,2809,2810],{"class":51,"line":594},[49,2811,2812],{},"RUN addgroup --system --gid 1001 nuxt \\\n",[49,2814,2815],{"class":51,"line":838},[49,2816,2817],{},"    && adduser --system --uid 1001 nuxt\n",[49,2819,2820],{"class":51,"line":1163},[49,2821,2822],{},"COPY --from=build --chown=nuxt:nuxt \u002Fapp\u002F.output .\u002F.output\n",[49,2824,2825],{"class":51,"line":1171},[49,2826,2827],{},"USER nuxt\n",[49,2829,2830],{"class":51,"line":1182},[49,2831,2832],{},"ENV HOST=0.0.0.0\n",[49,2834,2835],{"class":51,"line":1187},[49,2836,2837],{},"ENV PORT=3000\n",[49,2839,2840],{"class":51,"line":1192},[49,2841,2842],{},"EXPOSE 3000\n",[49,2844,2845],{"class":51,"line":1197},[49,2846,2847],{},"CMD [\"bun\", \"--bun\", \"run\", \".output\u002Fserver\u002Findex.mjs\"]\n",[127,2849,2851],{"id":2850},"environment-variables","Environment Variables",[2463,2853,2854,2864],{},[2466,2855,2856],{},[2469,2857,2858,2861],{},[2472,2859,2860],{},"Variable",[2472,2862,2863],{},"Description",[2479,2865,2866,2879],{},[2469,2867,2868,2876],{},[2484,2869,2870,183,2873],{},[21,2871,2872],{},"PORT",[21,2874,2875],{},"NITRO_PORT",[2484,2877,2878],{},"Server port (default: 3000)",[2469,2880,2881,2889],{},[2484,2882,2883,183,2886],{},[21,2884,2885],{},"HOST",[21,2887,2888],{},"NITRO_HOST",[2484,2890,2891],{},"Server host (default: 0.0.0.0)",[17,2893,310,2894,2896,2897,2899],{},[21,2895,2888],{}," may not work with the Bun preset. Only ",[21,2898,2875],{}," is reliable.",[29,2901,2903],{"id":2902},"testing-setup","Testing Setup",[127,2905,2907],{"id":2906},"vitest-configuration","Vitest Configuration",[40,2909,2911],{"className":1669,"code":2910,"language":1671,"meta":45,"style":45},"\u002F\u002F vitest.config.ts\nimport { defineVitestConfig } from '@nuxt\u002Ftest-utils\u002Fconfig'\n\nexport default defineVitestConfig({\n  test: {\n    environment: 'nuxt',\n    environmentOptions: {\n      nuxt: {\n        domEnvironment: 'happy-dom'\n      }\n    }\n  }\n})\n",[21,2912,2913,2918,2930,2934,2945,2950,2960,2965,2970,2978,2982,2986,2990],{"__ignoreMap":45},[49,2914,2915],{"class":51,"line":52},[49,2916,2917],{"class":251},"\u002F\u002F vitest.config.ts\n",[49,2919,2920,2922,2925,2927],{"class":51,"line":208},[49,2921,2021],{"class":803},[49,2923,2924],{"class":55}," { defineVitestConfig } ",[49,2926,2027],{"class":803},[49,2928,2929],{"class":70}," '@nuxt\u002Ftest-utils\u002Fconfig'\n",[49,2931,2932],{"class":51,"line":224},[49,2933,354],{"emptyLinePlaceholder":353},[49,2935,2936,2938,2940,2943],{"class":51,"line":237},[49,2937,1678],{"class":803},[49,2939,1681],{"class":803},[49,2941,2942],{"class":63}," defineVitestConfig",[49,2944,1687],{"class":55},[49,2946,2947],{"class":51,"line":255},[49,2948,2949],{"class":55},"  test: {\n",[49,2951,2952,2955,2958],{"class":51,"line":357},[49,2953,2954],{"class":55},"    environment: ",[49,2956,2957],{"class":70},"'nuxt'",[49,2959,1068],{"class":55},[49,2961,2962],{"class":51,"line":363},[49,2963,2964],{"class":55},"    environmentOptions: {\n",[49,2966,2967],{"class":51,"line":370},[49,2968,2969],{"class":55},"      nuxt: {\n",[49,2971,2972,2975],{"class":51,"line":381},[49,2973,2974],{"class":55},"        domEnvironment: ",[49,2976,2977],{"class":70},"'happy-dom'\n",[49,2979,2980],{"class":51,"line":573},[49,2981,1858],{"class":55},[49,2983,2984],{"class":51,"line":584},[49,2985,1863],{"class":55},[49,2987,2988],{"class":51,"line":589},[49,2989,1108],{"class":55},[49,2991,2992],{"class":51,"line":594},[49,2993,1723],{"class":55},[127,2995,2997],{"id":2996},"running-tests","Running Tests",[40,2999,3001],{"className":1569,"code":3000,"language":1571,"meta":45,"style":45},"bun run test\nbun run test:e2e\n",[21,3002,3003,3012],{"__ignoreMap":45},[49,3004,3005,3007,3009],{"class":51,"line":52},[49,3006,1599],{"class":63},[49,3008,1626],{"class":70},[49,3010,3011],{"class":70}," test\n",[49,3013,3014,3016,3018],{"class":51,"line":208},[49,3015,1599],{"class":63},[49,3017,1626],{"class":70},[49,3019,3020],{"class":70}," test:e2e\n",[29,3022,3024],{"id":3023},"practical-recommendation","Practical Recommendation",[17,3026,3027],{},"Use Bun as a package manager. Run development with Node.js. Deploy production with the Bun preset.",[40,3029,3031],{"className":1569,"code":3030,"language":1571,"meta":45,"style":45},"# Install with Bun (fast)\nbun install\n\n# Develop with Node.js (stable)\nbun run dev\n\n# Build for Bun runtime\nNITRO_PRESET=bun bun run build\n\n# Run production\nbun run .output\u002Fserver\u002Findex.mjs\n",[21,3032,3033,3038,3044,3048,3053,3061,3065,3070,3084,3088,3093],{"__ignoreMap":45},[49,3034,3035],{"class":51,"line":52},[49,3036,3037],{"class":251},"# Install with Bun (fast)\n",[49,3039,3040,3042],{"class":51,"line":208},[49,3041,1599],{"class":63},[49,3043,1602],{"class":70},[49,3045,3046],{"class":51,"line":224},[49,3047,354],{"emptyLinePlaceholder":353},[49,3049,3050],{"class":51,"line":237},[49,3051,3052],{"class":251},"# Develop with Node.js (stable)\n",[49,3054,3055,3057,3059],{"class":51,"line":255},[49,3056,1599],{"class":63},[49,3058,1626],{"class":70},[49,3060,1629],{"class":70},[49,3062,3063],{"class":51,"line":357},[49,3064,354],{"emptyLinePlaceholder":353},[49,3066,3067],{"class":51,"line":363},[49,3068,3069],{"class":251},"# Build for Bun runtime\n",[49,3071,3072,3074,3076,3078,3080,3082],{"class":51,"line":370},[49,3073,1736],{"class":55},[49,3075,67],{"class":803},[49,3077,1599],{"class":70},[49,3079,1743],{"class":63},[49,3081,1626],{"class":70},[49,3083,1748],{"class":70},[49,3085,3086],{"class":51,"line":381},[49,3087,354],{"emptyLinePlaceholder":353},[49,3089,3090],{"class":51,"line":573},[49,3091,3092],{"class":251},"# Run production\n",[49,3094,3095,3097,3099],{"class":51,"line":584},[49,3096,1599],{"class":63},[49,3098,1626],{"class":70},[49,3100,3101],{"class":70}," .output\u002Fserver\u002Findex.mjs\n",[17,3103,3104],{},"This approach gives you faster installs without the development instability.",[29,3106,1285],{"id":1284},[17,3108,3109],{},"Bun with Nuxt 4 works. It is not seamless.",[93,3111,3112,3115,3121,3127,3130,3133],{},[96,3113,3114],{},"Use Bun 1.3.6 with Nuxt 4.2.2 (latest stable)",[96,3116,3117,3118,3120],{},"Set ",[21,3119,2130],{}," for production",[96,3122,3123,3124,3126],{},"Avoid ",[21,3125,1654],{}," flag in development if you hit issues",[96,3128,3129],{},"Test all HTTP methods before deploying",[96,3131,3132],{},"Use WSL on Windows",[96,3134,3135],{},"Watch for memory leaks in long dev sessions",[17,3137,3138],{},"The performance gains are real. The edge cases are also real. Know both before committing.",[29,3140,1314],{"id":1313},[1316,3142,3143,3148],{},[1319,3144,3145],{"v-slot:title":45},[17,3146,3147],{},"Nuxt 4 Documentation",[1319,3149,3150],{"v-slot:content":45},[17,3151,3152,3157],{},[1329,3153,3156],{"href":3154,"rel":3155},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fgetting-started\u002Finstallation",[1333],"nuxt.com"," — Official installation and deployment guides",[1316,3159,3160,3165],{},[1319,3161,3162],{"v-slot:title":45},[17,3163,3164],{},"Bun + Nuxt Guide",[1319,3166,3167],{"v-slot:content":45},[17,3168,3169,3174],{},[1329,3170,3173],{"href":3171,"rel":3172},"https:\u002F\u002Fbun.com\u002Fguides\u002Fecosystem\u002Fnuxt",[1333],"bun.com"," — Official Bun documentation for Nuxt",[1316,3176,3177,3182],{},[1319,3178,3179],{"v-slot:title":45},[17,3180,3181],{},"Nitro Bun Runtime",[1319,3183,3184],{"v-slot:content":45},[17,3185,3186,3191],{},[1329,3187,3190],{"href":3188,"rel":3189},"https:\u002F\u002Fnitro.build\u002Fdeploy\u002Fruntimes\u002Fbun",[1333],"nitro.build"," — Nitro preset documentation",[1316,3193,3194,3199],{},[1319,3195,3196],{"v-slot:title":45},[17,3197,3198],{},"GitHub Issue #32875",[1319,3200,3201],{"v-slot:content":45},[17,3202,3203,3208],{},[1329,3204,3207],{"href":3205,"rel":3206},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fnuxt\u002Fissues\u002F32875",[1333],"github.com"," — Unable to run Nuxt 4 on Bun tracking issue",[1316,3210,3211,3216],{},[1319,3212,3213],{"v-slot:title":45},[17,3214,3215],{},"GitHub Issue #21762",[1319,3217,3218],{"v-slot:content":45},[17,3219,3220,3224],{},[1329,3221,3207],{"href":3222,"rel":3223},"https:\u002F\u002Fgithub.com\u002Foven-sh\u002Fbun\u002Fissues\u002F21762",[1333]," — Bun version compatibility tracking",[1316,3226,3227,3231],{},[1319,3228,3229],{"v-slot:title":45},[17,3230,1923],{},[1319,3232,3233],{"v-slot:content":45},[17,3234,3235,3238],{},[1329,3236,3207],{"href":1921,"rel":3237},[1333]," — Memory leak in dev mode",[1316,3240,3241,3246],{},[1319,3242,3243],{"v-slot:title":45},[17,3244,3245],{},"GitHub Issue #31249",[1319,3247,3248],{"v-slot:content":45},[17,3249,3250,3254],{},[1329,3251,3207],{"href":3252,"rel":3253},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fnuxt\u002Fissues\u002F31249",[1333]," — HMR breaks with Bun runtime",[1316,3256,3257,3261],{},[1319,3258,3259],{"v-slot:title":45},[17,3260,2239],{},[1319,3262,3263],{"v-slot:content":45},[17,3264,3265,3268],{},[1329,3266,3207],{"href":2237,"rel":3267},[1333]," — Nuxt Content better-sqlite3 doesn't work with Bun",[1316,3270,3271,3276],{},[1319,3272,3273],{"v-slot:title":45},[17,3274,3275],{},"GitHub Issue #3118",[1319,3277,3278],{"v-slot:content":45},[17,3279,3280,3283],{},[1329,3281,3207],{"href":2243,"rel":3282},[1333]," — bunsqlite polyfills regression",[1422,3285,3286],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .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 .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 .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}",{"title":45,"searchDepth":208,"depth":208,"links":3288},[3289,3290,3293,3299,3307,3312,3318,3321,3325,3329,3334,3338,3339,3340],{"id":1491,"depth":208,"text":1492},{"id":1524,"depth":208,"text":1525,"children":3291},[3292],{"id":1534,"depth":224,"text":1535},{"id":1558,"depth":208,"text":1559,"children":3294},[3295,3296,3297,3298],{"id":1562,"depth":224,"text":1563},{"id":1605,"depth":224,"text":1606},{"id":1658,"depth":224,"text":1659},{"id":1751,"depth":224,"text":1752},{"id":1766,"depth":208,"text":1767,"children":3300},[3301,3302,3303,3304,3305,3306],{"id":1770,"depth":224,"text":1771},{"id":1783,"depth":224,"text":1784},{"id":1874,"depth":224,"text":1875},{"id":1884,"depth":224,"text":1885},{"id":1900,"depth":224,"text":1901},{"id":1927,"depth":224,"text":1928},{"id":1995,"depth":208,"text":1996,"children":3308},[3309,3310,3311],{"id":2005,"depth":224,"text":2006},{"id":2112,"depth":224,"text":2113},{"id":2139,"depth":224,"text":2140},{"id":2199,"depth":208,"text":2200,"children":3313},[3314,3315,3316,3317],{"id":2206,"depth":224,"text":2207},{"id":2223,"depth":224,"text":1525},{"id":2248,"depth":224,"text":2249},{"id":2369,"depth":224,"text":2370},{"id":2457,"depth":208,"text":2458,"children":3319},[3320],{"id":2523,"depth":224,"text":2524},{"id":2561,"depth":208,"text":2562,"children":3322},[3323,3324],{"id":2565,"depth":224,"text":2566},{"id":2629,"depth":224,"text":2630},{"id":2642,"depth":208,"text":2643,"children":3326},[3327,3328],{"id":2646,"depth":224,"text":2647},{"id":2664,"depth":224,"text":2665},{"id":2682,"depth":208,"text":2683,"children":3330},[3331,3332,3333],{"id":2686,"depth":224,"text":2687},{"id":2741,"depth":224,"text":2742},{"id":2850,"depth":224,"text":2851},{"id":2902,"depth":208,"text":2903,"children":3335},[3336,3337],{"id":2906,"depth":224,"text":2907},{"id":2996,"depth":224,"text":2997},{"id":3023,"depth":208,"text":3024},{"id":1284,"depth":208,"text":1285},{"id":1313,"depth":208,"text":1314},"Practical guide to using Bun with Nuxt 4 in production. Configuration, known issues, performance gains, and when to stick with Node.js.","Bun + Nuxt 4 Guide",{},"\u002Fblog\u002Fbun-nuxt4-runtime-guide",{"title":1479,"description":3341},"blog\u002Fbun-nuxt4-runtime-guide",[1599,3348,3349,3350,3351],"nuxt","runtime","performance","node","Ldx54_8uQ5Ys7Zpl8QClz9AQFwF2A-0XQo4mgeyuQX8",1783866077806]