[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"github-stars":3,"guide-nav":5,"doc-\u002Fdocs\u002Fguide\u002Fssr":125},{"stars":4},4920,[6,11,15,19,23,27,31,35,39,43,47,51,55,59,63,68,72,76,80,84,89,93,97,101,105,109,113,117,121],{"path":7,"title":8,"description":9,"category":10},"\u002Fdocs\u002Fguide","Getting started","Shaders is a library of GPU effect components for Vue, React, Svelte, Solid, JavaScript and Framer, with a design editor for building with them.","code",{"path":12,"title":13,"description":14,"category":10},"\u002Fdocs\u002Fguide\u002Fquickstart","Quickstart","Install Shaders, render your first effect, and drive a prop from state.",{"path":16,"title":17,"description":18,"category":10},"\u002Fdocs\u002Fguide\u002Fcomposing-effects","Composing effects","Stack components as layers and nest them to control which layers an effect touches.",{"path":20,"title":21,"description":22,"category":10},"\u002Fdocs\u002Fguide\u002Fblending-masking","Blending and masking","Control how a layer mixes with the layers below it, and reveal one layer through another.",{"path":24,"title":25,"description":26,"category":10},"\u002Fdocs\u002Fguide\u002Fprops-reactivity","Props and reactivity","Bind props to your framework's state so effects update when it changes, and animate props with an animation library.",{"path":28,"title":29,"description":30,"category":10},"\u002Fdocs\u002Fguide\u002Fdynamic-props","Dynamic props","Drive any numeric or position prop from time, the cursor, or another layer, without writing animation code.",{"path":32,"title":33,"description":34,"category":10},"\u002Fdocs\u002Fguide\u002Flayout-positioning","Layout and positioning","Size and place a shader in your page with CSS, as a background, a fill, or an inline block.",{"path":36,"title":37,"description":38,"category":10},"\u002Fdocs\u002Fguide\u002Ftransforms","Transforms","Position, size, and rotate any layer inside the canvas with a bounding box, in % or px units.",{"path":40,"title":41,"description":42,"category":10},"\u002Fdocs\u002Fguide\u002Fshape-effects","Shape effects","Pick the 2D, 3D or custom SVG shape that Glass, Neon, Emboss and other shape effects draw inside.",{"path":44,"title":45,"description":46,"category":10},"\u002Fdocs\u002Fguide\u002Fcolor-space","Color space","Match colors to your design tool with the output color space, and keep bright layers from clipping with tone mapping.",{"path":48,"title":49,"description":50,"category":10},"\u002Fdocs\u002Fguide\u002Fhooks-events","Hooks and events","Run code when an effect is ready to show, and show a fallback when the GPU can't run it.",{"path":52,"title":53,"description":54,"category":10},"\u002Fdocs\u002Fguide\u002Fperformance","Performance","Learn what makes an effect expensive on the GPU and how to keep it inside the frame budget.",{"path":56,"title":57,"description":58,"category":10},"\u002Fdocs\u002Fguide\u002Fcustom-shaders","Custom components","Write your own component in TypeScript, use it like any component in the library, and write WGSL by hand when you need to.",{"path":60,"title":61,"description":62,"category":10},"\u002Fdocs\u002Fguide\u002Ftelemetry","Telemetry","The `\u003CShader>` component occasionally sends an anonymous performance report to help us improve the engine over time.",{"path":64,"title":65,"description":66,"category":67},"\u002Fdocs\u002Fguide\u002Fmcp","Shaders MCP","Connect your AI coding agent to Shaders so it can find, install and edit effects in your codebase.","workflows",{"path":69,"title":70,"description":71,"category":67},"\u002Fdocs\u002Fguide\u002Fcli","Shaders CLI","Install your own shaders and Pro shaders into your codebase as component files, and keep them in sync with the design editor.",{"path":73,"title":74,"description":75,"category":67},"\u002Fdocs\u002Fguide\u002Fagent-skill","Agent skill","Give your coding agent a skill that teaches it to build with Shaders components, the CLI and Pro shaders.",{"path":77,"title":78,"description":79,"category":10},"\u002Fdocs\u002Fguide\u002Fvideo-rendering","Rendering to video","Turn a shader effect into a video file, from the design editor or from a frame-by-frame pipeline such as Remotion, Hyperframes or Puppeteer.",{"path":81,"title":82,"description":83,"category":10},"\u002Fdocs\u002Fguide\u002Fssr","Server rendering","Render Shaders in Next.js, Nuxt, SvelteKit, SolidStart and other SSR apps by keeping each shader on the client.",{"path":85,"title":86,"description":87,"category":88},"\u002Fdocs\u002Fguide\u002Fquick-tour-of-the-design-editor","Quick tour of the design editor","A short walkthrough of the full Shaders workflow, from designing on the infinite canvas to exporting code.","editor",{"path":90,"title":91,"description":92,"category":88},"\u002Fdocs\u002Fguide\u002Fintro-to-the-interface","Intro to the interface","A tour of the design editor interface: the canvas, layers, the Properties panel, and the ways to share and export.",{"path":94,"title":95,"description":96,"category":88},"\u002Fdocs\u002Fguide\u002Fcomposing-your-first-shader-effect","Composing your first shader effect","Building a first shader effect in the design editor by stacking and nesting components as layers.",{"path":98,"title":99,"description":100,"category":88},"\u002Fdocs\u002Fguide\u002Fmasking-and-blending","Masking and blending","How blend modes and masks combine components in the design editor.",{"path":102,"title":103,"description":104,"category":88},"\u002Fdocs\u002Fguide\u002Fdynamic-prop-mapping","Dynamic prop mapping","Turning static props into dynamic ones in the design editor: mapping one layer's output into another's prop, following the cursor, or animating automatically.",{"path":106,"title":107,"description":108,"category":88},"\u002Fdocs\u002Fguide\u002Fcustom-media-and-transformations","Custom media and transformations","Uploading images, videos, and SVG files to the media gallery, adding them to a composition, and placing them with transformations.",{"path":110,"title":111,"description":112,"category":88},"\u002Fdocs\u002Fguide\u002Finstalling-a-shader-via-mcp","Installing a shader via MCP","Installing a shader from the design editor into a hero section with the Shaders MCP.",{"path":114,"title":115,"description":116,"category":88},"\u002Fdocs\u002Fguide\u002Fexploring-shape-effects","Exploring shape effects","Applying shape effects such as liquid glass, liquid metal, and glowing edges to built-in shapes and your own SVG.",{"path":118,"title":119,"description":120,"category":88},"\u002Fdocs\u002Fguide\u002Fglass-component-spotlight","Component spotlight: Glass","A short look at the Glass component and the liquid-glass look it creates.",{"path":122,"title":123,"description":124,"category":88},"\u002Fdocs\u002Fguide\u002Fdigital-looks-component-spotlight","Component spotlight: Digital looks","A look at the digital stylization components for glitchy, futuristic, or technical effects.",{"id":126,"title":82,"body":127,"category":10,"description":83,"extension":2573,"icon":2574,"meta":2575,"navigation":186,"path":81,"seo":2576,"stem":2577,"__hash__":2578},"guide\u002Fdocs\u002Fguide\u002F18.ssr.md",{"type":128,"value":129,"toc":2550},"minimark",[130,134,137,144,149,156,320,323,416,430,438,448,566,569,645,655,659,662,773,779,871,875,878,1070,1074,1084,1143,1146,1150,1157,1255,1258,1262,1265,1361,1370,1374,1385,1634,1638,1644,1713,1722,1729,1738,1870,1873,1877,1882,2084,2088,2091,2183,2189,2306,2318,2322,2327,2513,2517,2523,2527,2546],[131,132,82],"h1",{"id":133},"server-rendering",[135,136,83],"p",{},[135,138,139,140,143],{},"Shaders draws with WebGPU, which only exists in the browser. It can't run during server-side rendering, so every ",[10,141,142],{},"\u003CShader>"," has to start on the client. Each meta-framework has its own way to say so; find yours below.",[145,146,148],"h2",{"id":147},"using-nextjs","Using Next.js",[135,150,151,152,155],{},"In the Next.js App Router, put the shader in its own file with ",[10,153,154],{},"'use client'"," at the top:",[157,158,163],"pre",{"className":159,"code":160,"language":161,"meta":162,"style":162},"language-jsx shiki shiki-themes github-dark","\u002F\u002F components\u002FMyShader.jsx\n'use client'\n\nimport { Shader, LinearGradient, CursorTrail } from 'shaders\u002Freact'\n\nexport default function MyShader() {\n  return (\n    \u003CShader className=\"w-full h-64\">\n      \u003CLinearGradient colorA=\"#0f172a\" colorB=\"#7c3aed\" \u002F>\n      \u003CCursorTrail \u002F>\n    \u003C\u002FShader>\n  )\n}\n","jsx","",[10,164,165,174,181,188,205,210,229,238,260,288,298,308,314],{"__ignoreMap":162},[166,167,170],"span",{"class":168,"line":169},"line",1,[166,171,173],{"class":172},"sAwPA","\u002F\u002F components\u002FMyShader.jsx\n",[166,175,177],{"class":168,"line":176},2,[166,178,180],{"class":179},"sU2Wk","'use client'\n",[166,182,184],{"class":168,"line":183},3,[166,185,187],{"emptyLinePlaceholder":186},true,"\n",[166,189,191,195,199,202],{"class":168,"line":190},4,[166,192,194],{"class":193},"snl16","import",[166,196,198],{"class":197},"s95oV"," { Shader, LinearGradient, CursorTrail } ",[166,200,201],{"class":193},"from",[166,203,204],{"class":179}," 'shaders\u002Freact'\n",[166,206,208],{"class":168,"line":207},5,[166,209,187],{"emptyLinePlaceholder":186},[166,211,213,216,219,222,226],{"class":168,"line":212},6,[166,214,215],{"class":193},"export",[166,217,218],{"class":193}," default",[166,220,221],{"class":193}," function",[166,223,225],{"class":224},"svObZ"," MyShader",[166,227,228],{"class":197},"() {\n",[166,230,232,235],{"class":168,"line":231},7,[166,233,234],{"class":193},"  return",[166,236,237],{"class":197}," (\n",[166,239,241,244,248,251,254,257],{"class":168,"line":240},8,[166,242,243],{"class":197},"    \u003C",[166,245,247],{"class":246},"sDLfK","Shader",[166,249,250],{"class":224}," className",[166,252,253],{"class":193},"=",[166,255,256],{"class":179},"\"w-full h-64\"",[166,258,259],{"class":197},">\n",[166,261,263,266,269,272,274,277,280,282,285],{"class":168,"line":262},9,[166,264,265],{"class":197},"      \u003C",[166,267,268],{"class":246},"LinearGradient",[166,270,271],{"class":224}," colorA",[166,273,253],{"class":193},[166,275,276],{"class":179},"\"#0f172a\"",[166,278,279],{"class":224}," colorB",[166,281,253],{"class":193},[166,283,284],{"class":179},"\"#7c3aed\"",[166,286,287],{"class":197}," \u002F>\n",[166,289,291,293,296],{"class":168,"line":290},10,[166,292,265],{"class":197},[166,294,295],{"class":246},"CursorTrail",[166,297,287],{"class":197},[166,299,301,304,306],{"class":168,"line":300},11,[166,302,303],{"class":197},"    \u003C\u002F",[166,305,247],{"class":246},[166,307,259],{"class":197},[166,309,311],{"class":168,"line":310},12,[166,312,313],{"class":197},"  )\n",[166,315,317],{"class":168,"line":316},13,[166,318,319],{"class":197},"}\n",[135,321,322],{},"Then render it from a Server Component:",[157,324,326],{"className":159,"code":325,"language":161,"meta":162,"style":162},"\u002F\u002F app\u002Fpage.jsx (Server Component)\nimport MyShader from '@\u002Fcomponents\u002FMyShader'\n\nexport default function Page() {\n  return (\n    \u003Cmain>\n      \u003CMyShader \u002F>\n      \u003Ch1>Your content\u003C\u002Fh1>\n    \u003C\u002Fmain>\n  )\n}\n",[10,327,328,333,345,349,362,368,378,387,400,408,412],{"__ignoreMap":162},[166,329,330],{"class":168,"line":169},[166,331,332],{"class":172},"\u002F\u002F app\u002Fpage.jsx (Server Component)\n",[166,334,335,337,340,342],{"class":168,"line":176},[166,336,194],{"class":193},[166,338,339],{"class":197}," MyShader ",[166,341,201],{"class":193},[166,343,344],{"class":179}," '@\u002Fcomponents\u002FMyShader'\n",[166,346,347],{"class":168,"line":183},[166,348,187],{"emptyLinePlaceholder":186},[166,350,351,353,355,357,360],{"class":168,"line":190},[166,352,215],{"class":193},[166,354,218],{"class":193},[166,356,221],{"class":193},[166,358,359],{"class":224}," Page",[166,361,228],{"class":197},[166,363,364,366],{"class":168,"line":207},[166,365,234],{"class":193},[166,367,237],{"class":197},[166,369,370,372,376],{"class":168,"line":212},[166,371,243],{"class":197},[166,373,375],{"class":374},"s4JwU","main",[166,377,259],{"class":197},[166,379,380,382,385],{"class":168,"line":231},[166,381,265],{"class":197},[166,383,384],{"class":246},"MyShader",[166,386,287],{"class":197},[166,388,389,391,393,396,398],{"class":168,"line":240},[166,390,265],{"class":197},[166,392,131],{"class":374},[166,394,395],{"class":197},">Your content\u003C\u002F",[166,397,131],{"class":374},[166,399,259],{"class":197},[166,401,402,404,406],{"class":168,"line":262},[166,403,303],{"class":197},[166,405,375],{"class":374},[166,407,259],{"class":197},[166,409,410],{"class":168,"line":290},[166,411,313],{"class":197},[166,413,414],{"class":168,"line":300},[166,415,319],{"class":197},[135,417,418,420,421,423,424,429],{},[10,419,154],{}," makes it a Client Component: it hydrates and runs in the browser. Next.js still prerenders Client Components on the server, which ",[10,422,142],{}," handles: it renders an empty canvas there and starts WebGPU only after it mounts. If your own component touches browser APIs while it renders, use the client-only import below or a ",[425,426,428],"a",{"href":427},"#using-react-ssr-without-nextjs","mounted guard",".",[431,432,434,435],"h3",{"id":433},"turning-off-ssr-with-nextdynamic","Turning off SSR with ",[10,436,437],{},"next\u002Fdynamic",[135,439,440,441,443,444,447],{},"To skip the server render entirely, load the component with ",[10,442,437],{}," and ",[10,445,446],{},"ssr: false",". In the App Router that call has to live in a Client Component, so give it a small wrapper:",[157,449,451],{"className":159,"code":450,"language":161,"meta":162,"style":162},"\u002F\u002F components\u002FMyShaderClient.jsx\n'use client'\n\nimport dynamic from 'next\u002Fdynamic'\n\nconst MyShader = dynamic(\n  () => import('@\u002Fcomponents\u002FMyShader'),\n  { ssr: false }\n)\n\nexport default function MyShaderClient() {\n  return \u003CMyShader \u002F>\n}\n",[10,452,453,458,462,466,478,482,498,518,529,534,538,551,562],{"__ignoreMap":162},[166,454,455],{"class":168,"line":169},[166,456,457],{"class":172},"\u002F\u002F components\u002FMyShaderClient.jsx\n",[166,459,460],{"class":168,"line":176},[166,461,180],{"class":179},[166,463,464],{"class":168,"line":183},[166,465,187],{"emptyLinePlaceholder":186},[166,467,468,470,473,475],{"class":168,"line":190},[166,469,194],{"class":193},[166,471,472],{"class":197}," dynamic ",[166,474,201],{"class":193},[166,476,477],{"class":179}," 'next\u002Fdynamic'\n",[166,479,480],{"class":168,"line":207},[166,481,187],{"emptyLinePlaceholder":186},[166,483,484,487,489,492,495],{"class":168,"line":212},[166,485,486],{"class":193},"const",[166,488,225],{"class":246},[166,490,491],{"class":193}," =",[166,493,494],{"class":224}," dynamic",[166,496,497],{"class":197},"(\n",[166,499,500,503,506,509,512,515],{"class":168,"line":231},[166,501,502],{"class":197},"  () ",[166,504,505],{"class":193},"=>",[166,507,508],{"class":193}," import",[166,510,511],{"class":197},"(",[166,513,514],{"class":179},"'@\u002Fcomponents\u002FMyShader'",[166,516,517],{"class":197},"),\n",[166,519,520,523,526],{"class":168,"line":240},[166,521,522],{"class":197},"  { ssr: ",[166,524,525],{"class":246},"false",[166,527,528],{"class":197}," }\n",[166,530,531],{"class":168,"line":262},[166,532,533],{"class":197},")\n",[166,535,536],{"class":168,"line":290},[166,537,187],{"emptyLinePlaceholder":186},[166,539,540,542,544,546,549],{"class":168,"line":300},[166,541,215],{"class":193},[166,543,218],{"class":193},[166,545,221],{"class":193},[166,547,548],{"class":224}," MyShaderClient",[166,550,228],{"class":197},[166,552,553,555,558,560],{"class":168,"line":310},[166,554,234],{"class":193},[166,556,557],{"class":197}," \u003C",[166,559,384],{"class":246},[166,561,287],{"class":197},[166,563,564],{"class":168,"line":316},[166,565,319],{"class":197},[135,567,568],{},"Then render the wrapper from your page:",[157,570,572],{"className":159,"code":571,"language":161,"meta":162,"style":162},"\u002F\u002F app\u002Fpage.jsx (Server Component)\nimport MyShaderClient from '@\u002Fcomponents\u002FMyShaderClient'\n\nexport default function Page() {\n  return (\n    \u003Cmain>\n      \u003CMyShaderClient \u002F>\n    \u003C\u002Fmain>\n  )\n}\n",[10,573,574,578,590,594,606,612,620,629,637,641],{"__ignoreMap":162},[166,575,576],{"class":168,"line":169},[166,577,332],{"class":172},[166,579,580,582,585,587],{"class":168,"line":176},[166,581,194],{"class":193},[166,583,584],{"class":197}," MyShaderClient ",[166,586,201],{"class":193},[166,588,589],{"class":179}," '@\u002Fcomponents\u002FMyShaderClient'\n",[166,591,592],{"class":168,"line":183},[166,593,187],{"emptyLinePlaceholder":186},[166,595,596,598,600,602,604],{"class":168,"line":190},[166,597,215],{"class":193},[166,599,218],{"class":193},[166,601,221],{"class":193},[166,603,359],{"class":224},[166,605,228],{"class":197},[166,607,608,610],{"class":168,"line":207},[166,609,234],{"class":193},[166,611,237],{"class":197},[166,613,614,616,618],{"class":168,"line":212},[166,615,243],{"class":197},[166,617,375],{"class":374},[166,619,259],{"class":197},[166,621,622,624,627],{"class":168,"line":231},[166,623,265],{"class":197},[166,625,626],{"class":246},"MyShaderClient",[166,628,287],{"class":197},[166,630,631,633,635],{"class":168,"line":240},[166,632,303],{"class":197},[166,634,375],{"class":374},[166,636,259],{"class":197},[166,638,639],{"class":168,"line":262},[166,640,313],{"class":197},[166,642,643],{"class":168,"line":290},[166,644,319],{"class":197},[135,646,647,648,651,652,654],{},"The shader renders only in the browser, and its module never loads on the server. In the Pages Router, call ",[10,649,650],{},"dynamic"," with ",[10,653,446],{}," directly in the page.",[431,656,658],{"id":657},"adding-a-shader-to-the-root-layout","Adding a shader to the root layout",[135,660,661],{},"For a shader on every page, such as a full-page background, render a client component from the root layout:",[157,663,665],{"className":159,"code":664,"language":161,"meta":162,"style":162},"\u002F\u002F app\u002Flayout.jsx\nimport BackgroundShader from '@\u002Fcomponents\u002FBackgroundShader'\n\nexport default function RootLayout({ children }) {\n  return (\n    \u003Chtml>\n      \u003Cbody>\n        \u003CBackgroundShader \u002F>\n        {children}\n      \u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  )\n}\n",[10,666,667,672,684,688,709,715,724,733,743,748,757,765,769],{"__ignoreMap":162},[166,668,669],{"class":168,"line":169},[166,670,671],{"class":172},"\u002F\u002F app\u002Flayout.jsx\n",[166,673,674,676,679,681],{"class":168,"line":176},[166,675,194],{"class":193},[166,677,678],{"class":197}," BackgroundShader ",[166,680,201],{"class":193},[166,682,683],{"class":179}," '@\u002Fcomponents\u002FBackgroundShader'\n",[166,685,686],{"class":168,"line":183},[166,687,187],{"emptyLinePlaceholder":186},[166,689,690,692,694,696,699,702,706],{"class":168,"line":190},[166,691,215],{"class":193},[166,693,218],{"class":193},[166,695,221],{"class":193},[166,697,698],{"class":224}," RootLayout",[166,700,701],{"class":197},"({ ",[166,703,705],{"class":704},"s9osk","children",[166,707,708],{"class":197}," }) {\n",[166,710,711,713],{"class":168,"line":207},[166,712,234],{"class":193},[166,714,237],{"class":197},[166,716,717,719,722],{"class":168,"line":212},[166,718,243],{"class":197},[166,720,721],{"class":374},"html",[166,723,259],{"class":197},[166,725,726,728,731],{"class":168,"line":231},[166,727,265],{"class":197},[166,729,730],{"class":374},"body",[166,732,259],{"class":197},[166,734,735,738,741],{"class":168,"line":240},[166,736,737],{"class":197},"        \u003C",[166,739,740],{"class":246},"BackgroundShader",[166,742,287],{"class":197},[166,744,745],{"class":168,"line":262},[166,746,747],{"class":197},"        {children}\n",[166,749,750,753,755],{"class":168,"line":290},[166,751,752],{"class":197},"      \u003C\u002F",[166,754,730],{"class":374},[166,756,259],{"class":197},[166,758,759,761,763],{"class":168,"line":300},[166,760,303],{"class":197},[166,762,721],{"class":374},[166,764,259],{"class":197},[166,766,767],{"class":168,"line":310},[166,768,313],{"class":197},[166,770,771],{"class":168,"line":316},[166,772,319],{"class":197},[135,774,775,776,778],{},"The background component carries ",[10,777,154],{}," and sits behind the page:",[157,780,782],{"className":159,"code":781,"language":161,"meta":162,"style":162},"\u002F\u002F components\u002FBackgroundShader.jsx\n'use client'\n\nimport { Shader, Aurora } from 'shaders\u002Freact'\n\nexport default function BackgroundShader() {\n  return (\n    \u003CShader className=\"fixed inset-0 -z-10 pointer-events-none\">\n      \u003CAurora \u002F>\n    \u003C\u002FShader>\n  )\n}\n",[10,783,784,789,793,797,808,812,825,831,846,855,863,867],{"__ignoreMap":162},[166,785,786],{"class":168,"line":169},[166,787,788],{"class":172},"\u002F\u002F components\u002FBackgroundShader.jsx\n",[166,790,791],{"class":168,"line":176},[166,792,180],{"class":179},[166,794,795],{"class":168,"line":183},[166,796,187],{"emptyLinePlaceholder":186},[166,798,799,801,804,806],{"class":168,"line":190},[166,800,194],{"class":193},[166,802,803],{"class":197}," { Shader, Aurora } ",[166,805,201],{"class":193},[166,807,204],{"class":179},[166,809,810],{"class":168,"line":207},[166,811,187],{"emptyLinePlaceholder":186},[166,813,814,816,818,820,823],{"class":168,"line":212},[166,815,215],{"class":193},[166,817,218],{"class":193},[166,819,221],{"class":193},[166,821,822],{"class":224}," BackgroundShader",[166,824,228],{"class":197},[166,826,827,829],{"class":168,"line":231},[166,828,234],{"class":193},[166,830,237],{"class":197},[166,832,833,835,837,839,841,844],{"class":168,"line":240},[166,834,243],{"class":197},[166,836,247],{"class":246},[166,838,250],{"class":224},[166,840,253],{"class":193},[166,842,843],{"class":179},"\"fixed inset-0 -z-10 pointer-events-none\"",[166,845,259],{"class":197},[166,847,848,850,853],{"class":168,"line":262},[166,849,265],{"class":197},[166,851,852],{"class":246},"Aurora",[166,854,287],{"class":197},[166,856,857,859,861],{"class":168,"line":290},[166,858,303],{"class":197},[166,860,247],{"class":246},[166,862,259],{"class":197},[166,864,865],{"class":168,"line":300},[166,866,313],{"class":197},[166,868,869],{"class":168,"line":310},[166,870,319],{"class":197},[431,872,874],{"id":873},"using-react-ssr-without-nextjs","Using React SSR without Next.js",[135,876,877],{},"Without Next.js, render the shader only after the component has mounted:",[157,879,881],{"className":159,"code":880,"language":161,"meta":162,"style":162},"import { useState, useEffect } from 'react'\nimport { Shader, LinearGradient } from 'shaders\u002Freact'\n\nexport default function MyShader() {\n  const [mounted, setMounted] = useState(false)\n\n  useEffect(() => {\n    setMounted(true)\n  }, [])\n\n  \u002F\u002F effects don't run on the server, so SSR renders nothing here\n  if (!mounted) return null\n\n  return (\n    \u003CShader className=\"w-full h-64\">\n      \u003CLinearGradient \u002F>\n    \u003C\u002FShader>\n  )\n}\n",[10,882,883,895,906,910,922,953,957,970,982,987,991,996,1016,1020,1027,1042,1051,1060,1065],{"__ignoreMap":162},[166,884,885,887,890,892],{"class":168,"line":169},[166,886,194],{"class":193},[166,888,889],{"class":197}," { useState, useEffect } ",[166,891,201],{"class":193},[166,893,894],{"class":179}," 'react'\n",[166,896,897,899,902,904],{"class":168,"line":176},[166,898,194],{"class":193},[166,900,901],{"class":197}," { Shader, LinearGradient } ",[166,903,201],{"class":193},[166,905,204],{"class":179},[166,907,908],{"class":168,"line":183},[166,909,187],{"emptyLinePlaceholder":186},[166,911,912,914,916,918,920],{"class":168,"line":190},[166,913,215],{"class":193},[166,915,218],{"class":193},[166,917,221],{"class":193},[166,919,225],{"class":224},[166,921,228],{"class":197},[166,923,924,927,930,933,936,939,942,944,947,949,951],{"class":168,"line":207},[166,925,926],{"class":193},"  const",[166,928,929],{"class":197}," [",[166,931,932],{"class":246},"mounted",[166,934,935],{"class":197},", ",[166,937,938],{"class":246},"setMounted",[166,940,941],{"class":197},"] ",[166,943,253],{"class":193},[166,945,946],{"class":224}," useState",[166,948,511],{"class":197},[166,950,525],{"class":246},[166,952,533],{"class":197},[166,954,955],{"class":168,"line":212},[166,956,187],{"emptyLinePlaceholder":186},[166,958,959,962,965,967],{"class":168,"line":231},[166,960,961],{"class":224},"  useEffect",[166,963,964],{"class":197},"(() ",[166,966,505],{"class":193},[166,968,969],{"class":197}," {\n",[166,971,972,975,977,980],{"class":168,"line":240},[166,973,974],{"class":224},"    setMounted",[166,976,511],{"class":197},[166,978,979],{"class":246},"true",[166,981,533],{"class":197},[166,983,984],{"class":168,"line":262},[166,985,986],{"class":197},"  }, [])\n",[166,988,989],{"class":168,"line":290},[166,990,187],{"emptyLinePlaceholder":186},[166,992,993],{"class":168,"line":300},[166,994,995],{"class":172},"  \u002F\u002F effects don't run on the server, so SSR renders nothing here\n",[166,997,998,1001,1004,1007,1010,1013],{"class":168,"line":310},[166,999,1000],{"class":193},"  if",[166,1002,1003],{"class":197}," (",[166,1005,1006],{"class":193},"!",[166,1008,1009],{"class":197},"mounted) ",[166,1011,1012],{"class":193},"return",[166,1014,1015],{"class":246}," null\n",[166,1017,1018],{"class":168,"line":316},[166,1019,187],{"emptyLinePlaceholder":186},[166,1021,1023,1025],{"class":168,"line":1022},14,[166,1024,234],{"class":193},[166,1026,237],{"class":197},[166,1028,1030,1032,1034,1036,1038,1040],{"class":168,"line":1029},15,[166,1031,243],{"class":197},[166,1033,247],{"class":246},[166,1035,250],{"class":224},[166,1037,253],{"class":193},[166,1039,256],{"class":179},[166,1041,259],{"class":197},[166,1043,1045,1047,1049],{"class":168,"line":1044},16,[166,1046,265],{"class":197},[166,1048,268],{"class":246},[166,1050,287],{"class":197},[166,1052,1054,1056,1058],{"class":168,"line":1053},17,[166,1055,303],{"class":197},[166,1057,247],{"class":246},[166,1059,259],{"class":197},[166,1061,1063],{"class":168,"line":1062},18,[166,1064,313],{"class":197},[166,1066,1068],{"class":168,"line":1067},19,[166,1069,319],{"class":197},[145,1071,1073],{"id":1072},"using-nuxt","Using Nuxt",[135,1075,1076,1077,1079,1080,1083],{},"In Nuxt, wrap the ",[10,1078,142],{}," in the built-in ",[10,1081,1082],{},"\u003CClientOnly>"," component:",[157,1085,1089],{"className":1086,"code":1087,"language":1088,"meta":162,"style":162},"language-vue-html shiki shiki-themes github-dark","\u003CClientOnly>\n  \u003CShader class=\"w-full h-64\">\n    \u003CLinearGradient \u002F>\n  \u003C\u002FShader>\n\u003C\u002FClientOnly>\n","vue-html",[10,1090,1091,1101,1117,1125,1134],{"__ignoreMap":162},[166,1092,1093,1096,1099],{"class":168,"line":169},[166,1094,1095],{"class":197},"\u003C",[166,1097,1098],{"class":374},"ClientOnly",[166,1100,259],{"class":197},[166,1102,1103,1106,1108,1111,1113,1115],{"class":168,"line":176},[166,1104,1105],{"class":197},"  \u003C",[166,1107,247],{"class":374},[166,1109,1110],{"class":224}," class",[166,1112,253],{"class":197},[166,1114,256],{"class":179},[166,1116,259],{"class":197},[166,1118,1119,1121,1123],{"class":168,"line":183},[166,1120,243],{"class":197},[166,1122,268],{"class":374},[166,1124,287],{"class":197},[166,1126,1127,1130,1132],{"class":168,"line":190},[166,1128,1129],{"class":197},"  \u003C\u002F",[166,1131,247],{"class":374},[166,1133,259],{"class":197},[166,1135,1136,1139,1141],{"class":168,"line":207},[166,1137,1138],{"class":197},"\u003C\u002F",[166,1140,1098],{"class":374},[166,1142,259],{"class":197},[135,1144,1145],{},"The server renders nothing in its place, and the shader mounts on the client after hydration. A canvas has no content for Vue to compare, so it never causes a hydration mismatch warning.",[431,1147,1149],{"id":1148},"showing-a-placeholder-while-it-loads","Showing a placeholder while it loads",[135,1151,1152,1153,1156],{},"Add a ",[10,1154,1155],{},"#fallback"," slot to show something until the shader mounts:",[157,1158,1160],{"className":1086,"code":1159,"language":1088,"meta":162,"style":162},"\u003CClientOnly>\n  \u003CShader class=\"w-full h-64\">\n    \u003CLinearGradient \u002F>\n  \u003C\u002FShader>\n\n  \u003Ctemplate #fallback>\n    \u003Cdiv class=\"w-full h-64 bg-gray-900 animate-pulse rounded\" \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002FClientOnly>\n",[10,1161,1162,1170,1184,1192,1200,1204,1219,1239,1247],{"__ignoreMap":162},[166,1163,1164,1166,1168],{"class":168,"line":169},[166,1165,1095],{"class":197},[166,1167,1098],{"class":374},[166,1169,259],{"class":197},[166,1171,1172,1174,1176,1178,1180,1182],{"class":168,"line":176},[166,1173,1105],{"class":197},[166,1175,247],{"class":374},[166,1177,1110],{"class":224},[166,1179,253],{"class":197},[166,1181,256],{"class":179},[166,1183,259],{"class":197},[166,1185,1186,1188,1190],{"class":168,"line":183},[166,1187,243],{"class":197},[166,1189,268],{"class":374},[166,1191,287],{"class":197},[166,1193,1194,1196,1198],{"class":168,"line":190},[166,1195,1129],{"class":197},[166,1197,247],{"class":374},[166,1199,259],{"class":197},[166,1201,1202],{"class":168,"line":207},[166,1203,187],{"emptyLinePlaceholder":186},[166,1205,1206,1208,1211,1214,1217],{"class":168,"line":212},[166,1207,1105],{"class":197},[166,1209,1210],{"class":374},"template",[166,1212,1213],{"class":197}," #",[166,1215,1216],{"class":224},"fallback",[166,1218,259],{"class":197},[166,1220,1221,1223,1226,1228,1230,1233,1237],{"class":168,"line":231},[166,1222,243],{"class":197},[166,1224,1225],{"class":374},"div",[166,1227,1110],{"class":224},[166,1229,253],{"class":197},[166,1231,1232],{"class":179},"\"w-full h-64 bg-gray-900 animate-pulse rounded\"",[166,1234,1236],{"class":1235},"s6RL2"," \u002F",[166,1238,259],{"class":197},[166,1240,1241,1243,1245],{"class":168,"line":240},[166,1242,1129],{"class":197},[166,1244,1210],{"class":374},[166,1246,259],{"class":197},[166,1248,1249,1251,1253],{"class":168,"line":262},[166,1250,1138],{"class":197},[166,1252,1098],{"class":374},[166,1254,259],{"class":197},[135,1256,1257],{},"Give the fallback the same size as the shader to avoid layout shift.",[431,1259,1261],{"id":1260},"registering-components-in-a-client-only-plugin","Registering components in a client-only plugin",[135,1263,1264],{},"You can also register the components globally from a plugin that only runs in the browser:",[157,1266,1270],{"className":1267,"code":1268,"language":1269,"meta":162,"style":162},"language-javascript shiki shiki-themes github-dark","\u002F\u002F plugins\u002Fshaders.client.ts\nimport { defineNuxtPlugin } from '#app'\nimport { Shader, LinearGradient } from 'shaders\u002Fvue'\n\nexport default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.vueApp.component('Shader', Shader)\n  nuxtApp.vueApp.component('LinearGradient', LinearGradient)\n})\n","javascript",[10,1271,1272,1277,1289,1300,1304,1326,1342,1356],{"__ignoreMap":162},[166,1273,1274],{"class":168,"line":169},[166,1275,1276],{"class":172},"\u002F\u002F plugins\u002Fshaders.client.ts\n",[166,1278,1279,1281,1284,1286],{"class":168,"line":176},[166,1280,194],{"class":193},[166,1282,1283],{"class":197}," { defineNuxtPlugin } ",[166,1285,201],{"class":193},[166,1287,1288],{"class":179}," '#app'\n",[166,1290,1291,1293,1295,1297],{"class":168,"line":183},[166,1292,194],{"class":193},[166,1294,901],{"class":197},[166,1296,201],{"class":193},[166,1298,1299],{"class":179}," 'shaders\u002Fvue'\n",[166,1301,1302],{"class":168,"line":190},[166,1303,187],{"emptyLinePlaceholder":186},[166,1305,1306,1308,1310,1313,1316,1319,1322,1324],{"class":168,"line":207},[166,1307,215],{"class":193},[166,1309,218],{"class":193},[166,1311,1312],{"class":224}," defineNuxtPlugin",[166,1314,1315],{"class":197},"((",[166,1317,1318],{"class":704},"nuxtApp",[166,1320,1321],{"class":197},") ",[166,1323,505],{"class":193},[166,1325,969],{"class":197},[166,1327,1328,1331,1334,1336,1339],{"class":168,"line":212},[166,1329,1330],{"class":197},"  nuxtApp.vueApp.",[166,1332,1333],{"class":224},"component",[166,1335,511],{"class":197},[166,1337,1338],{"class":179},"'Shader'",[166,1340,1341],{"class":197},", Shader)\n",[166,1343,1344,1346,1348,1350,1353],{"class":168,"line":231},[166,1345,1330],{"class":197},[166,1347,1333],{"class":224},[166,1349,511],{"class":197},[166,1351,1352],{"class":179},"'LinearGradient'",[166,1354,1355],{"class":197},", LinearGradient)\n",[166,1357,1358],{"class":168,"line":240},[166,1359,1360],{"class":197},"})\n",[135,1362,1363,1364,1367,1368,429],{},"The ",[10,1365,1366],{},".client.ts"," suffix makes Nuxt run this plugin only in the browser. The server doesn't know these components, so keep them inside ",[10,1369,1082],{},[431,1371,1373],{"id":1372},"using-vue-ssr-without-nuxt","Using Vue SSR without Nuxt",[135,1375,1376,1377,1380,1381,1384],{},"Without Nuxt, render the shader with ",[10,1378,1379],{},"v-if"," on a mounted flag. To keep the Shaders bundle out of SSR too, load the components with ",[10,1382,1383],{},"defineAsyncComponent",":",[157,1386,1390],{"className":1387,"code":1388,"language":1389,"meta":162,"style":162},"language-vue shiki shiki-themes github-dark","\u003Cscript setup>\nimport { defineAsyncComponent, ref, onMounted } from 'vue'\n\n\u002F\u002F onMounted never runs on the server, so the flag stays false during SSR\nconst isMounted = ref(false)\nonMounted(() => { isMounted.value = true })\n\n\u002F\u002F fetched in the browser the first time they render\nconst Shader = defineAsyncComponent(() => import('shaders\u002Fvue').then(m => m.Shader))\nconst LinearGradient = defineAsyncComponent(() => import('shaders\u002Fvue').then(m => m.LinearGradient))\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"w-full h-64\">\n    \u003CShader v-if=\"isMounted\" class=\"w-full h-64\">\n      \u003CLinearGradient \u002F>\n    \u003C\u002FShader>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","vue",[10,1391,1392,1404,1416,1420,1425,1443,1463,1467,1472,1512,1546,1554,1558,1566,1580,1602,1610,1618,1626],{"__ignoreMap":162},[166,1393,1394,1396,1399,1402],{"class":168,"line":169},[166,1395,1095],{"class":197},[166,1397,1398],{"class":374},"script",[166,1400,1401],{"class":224}," setup",[166,1403,259],{"class":197},[166,1405,1406,1408,1411,1413],{"class":168,"line":176},[166,1407,194],{"class":193},[166,1409,1410],{"class":197}," { defineAsyncComponent, ref, onMounted } ",[166,1412,201],{"class":193},[166,1414,1415],{"class":179}," 'vue'\n",[166,1417,1418],{"class":168,"line":183},[166,1419,187],{"emptyLinePlaceholder":186},[166,1421,1422],{"class":168,"line":190},[166,1423,1424],{"class":172},"\u002F\u002F onMounted never runs on the server, so the flag stays false during SSR\n",[166,1426,1427,1429,1432,1434,1437,1439,1441],{"class":168,"line":207},[166,1428,486],{"class":193},[166,1430,1431],{"class":246}," isMounted",[166,1433,491],{"class":193},[166,1435,1436],{"class":224}," ref",[166,1438,511],{"class":197},[166,1440,525],{"class":246},[166,1442,533],{"class":197},[166,1444,1445,1448,1450,1452,1455,1457,1460],{"class":168,"line":212},[166,1446,1447],{"class":224},"onMounted",[166,1449,964],{"class":197},[166,1451,505],{"class":193},[166,1453,1454],{"class":197}," { isMounted.value ",[166,1456,253],{"class":193},[166,1458,1459],{"class":246}," true",[166,1461,1462],{"class":197}," })\n",[166,1464,1465],{"class":168,"line":231},[166,1466,187],{"emptyLinePlaceholder":186},[166,1468,1469],{"class":168,"line":240},[166,1470,1471],{"class":172},"\u002F\u002F fetched in the browser the first time they render\n",[166,1473,1474,1476,1479,1481,1484,1486,1488,1490,1492,1495,1498,1501,1503,1506,1509],{"class":168,"line":262},[166,1475,486],{"class":193},[166,1477,1478],{"class":246}," Shader",[166,1480,491],{"class":193},[166,1482,1483],{"class":224}," defineAsyncComponent",[166,1485,964],{"class":197},[166,1487,505],{"class":193},[166,1489,508],{"class":193},[166,1491,511],{"class":197},[166,1493,1494],{"class":179},"'shaders\u002Fvue'",[166,1496,1497],{"class":197},").",[166,1499,1500],{"class":224},"then",[166,1502,511],{"class":197},[166,1504,1505],{"class":704},"m",[166,1507,1508],{"class":193}," =>",[166,1510,1511],{"class":197}," m.Shader))\n",[166,1513,1514,1516,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541,1543],{"class":168,"line":290},[166,1515,486],{"class":193},[166,1517,1518],{"class":246}," LinearGradient",[166,1520,491],{"class":193},[166,1522,1483],{"class":224},[166,1524,964],{"class":197},[166,1526,505],{"class":193},[166,1528,508],{"class":193},[166,1530,511],{"class":197},[166,1532,1494],{"class":179},[166,1534,1497],{"class":197},[166,1536,1500],{"class":224},[166,1538,511],{"class":197},[166,1540,1505],{"class":704},[166,1542,1508],{"class":193},[166,1544,1545],{"class":197}," m.LinearGradient))\n",[166,1547,1548,1550,1552],{"class":168,"line":300},[166,1549,1138],{"class":197},[166,1551,1398],{"class":374},[166,1553,259],{"class":197},[166,1555,1556],{"class":168,"line":310},[166,1557,187],{"emptyLinePlaceholder":186},[166,1559,1560,1562,1564],{"class":168,"line":316},[166,1561,1095],{"class":197},[166,1563,1210],{"class":374},[166,1565,259],{"class":197},[166,1567,1568,1570,1572,1574,1576,1578],{"class":168,"line":1022},[166,1569,1105],{"class":197},[166,1571,1225],{"class":374},[166,1573,1110],{"class":224},[166,1575,253],{"class":197},[166,1577,256],{"class":179},[166,1579,259],{"class":197},[166,1581,1582,1584,1586,1589,1591,1594,1596,1598,1600],{"class":168,"line":1029},[166,1583,243],{"class":197},[166,1585,247],{"class":374},[166,1587,1588],{"class":224}," v-if",[166,1590,253],{"class":197},[166,1592,1593],{"class":179},"\"isMounted\"",[166,1595,1110],{"class":224},[166,1597,253],{"class":197},[166,1599,256],{"class":179},[166,1601,259],{"class":197},[166,1603,1604,1606,1608],{"class":168,"line":1044},[166,1605,265],{"class":197},[166,1607,268],{"class":374},[166,1609,287],{"class":197},[166,1611,1612,1614,1616],{"class":168,"line":1053},[166,1613,303],{"class":197},[166,1615,247],{"class":374},[166,1617,259],{"class":197},[166,1619,1620,1622,1624],{"class":168,"line":1062},[166,1621,1129],{"class":197},[166,1623,1225],{"class":374},[166,1625,259],{"class":197},[166,1627,1628,1630,1632],{"class":168,"line":1067},[166,1629,1138],{"class":197},[166,1631,1210],{"class":374},[166,1633,259],{"class":197},[145,1635,1637],{"id":1636},"using-sveltekit","Using SvelteKit",[135,1639,1640,1641,1643],{},"There's nothing to set up. Use ",[10,1642,142],{}," as you would on any other page:",[157,1645,1649],{"className":1646,"code":1647,"language":1648,"meta":162,"style":162},"language-svelte shiki shiki-themes github-dark","\u003Cscript>\n  import { Shader, LinearGradient } from 'shaders\u002Fsvelte'\n\u003C\u002Fscript>\n\n\u003CShader class=\"w-full h-64\">\n  \u003CLinearGradient \u002F>\n\u003C\u002FShader>\n","svelte",[10,1650,1651,1659,1671,1679,1683,1697,1705],{"__ignoreMap":162},[166,1652,1653,1655,1657],{"class":168,"line":169},[166,1654,1095],{"class":197},[166,1656,1398],{"class":374},[166,1658,259],{"class":197},[166,1660,1661,1664,1666,1668],{"class":168,"line":176},[166,1662,1663],{"class":193},"  import",[166,1665,901],{"class":197},[166,1667,201],{"class":193},[166,1669,1670],{"class":179}," 'shaders\u002Fsvelte'\n",[166,1672,1673,1675,1677],{"class":168,"line":183},[166,1674,1138],{"class":197},[166,1676,1398],{"class":374},[166,1678,259],{"class":197},[166,1680,1681],{"class":168,"line":190},[166,1682,187],{"emptyLinePlaceholder":186},[166,1684,1685,1687,1689,1691,1693,1695],{"class":168,"line":207},[166,1686,1095],{"class":197},[166,1688,247],{"class":246},[166,1690,1110],{"class":224},[166,1692,253],{"class":197},[166,1694,256],{"class":179},[166,1696,259],{"class":197},[166,1698,1699,1701,1703],{"class":168,"line":212},[166,1700,1105],{"class":197},[166,1702,268],{"class":246},[166,1704,287],{"class":197},[166,1706,1707,1709,1711],{"class":168,"line":231},[166,1708,1138],{"class":197},[166,1710,247],{"class":246},[166,1712,259],{"class":197},[135,1714,1715,1716,1718,1719,429],{},"On the server, ",[10,1717,142],{}," renders an empty wrapper with no canvas and no error. The canvas and the GPU setup are added on the client when the component mounts. Your own component script still runs on the server, so put code that touches the DOM in ",[10,1720,1721],{},"onMount",[431,1723,1725,1726],{"id":1724},"rendering-a-placeholder-with-browser","Rendering a placeholder with ",[10,1727,1728],{},"browser",[135,1730,1731,1732,1734,1735,1384],{},"To choose what the server renders, check ",[10,1733,1728],{}," from SvelteKit's ",[10,1736,1737],{},"$app\u002Fenvironment",[157,1739,1741],{"className":1646,"code":1740,"language":1648,"meta":162,"style":162},"\u003Cscript>\n  import { browser } from '$app\u002Fenvironment'\n  import { Shader, LinearGradient } from 'shaders\u002Fsvelte'\n\u003C\u002Fscript>\n\n{#if browser}\n  \u003CShader class=\"w-full h-64\">\n    \u003CLinearGradient \u002F>\n  \u003C\u002FShader>\n{:else}\n  \u003C!-- Optional server-rendered placeholder -->\n  \u003Cdiv class=\"w-full h-64 bg-gray-900 rounded\">\u003C\u002Fdiv>\n{\u002Fif}\n",[10,1742,1743,1751,1763,1773,1781,1785,1796,1810,1818,1826,1836,1841,1861],{"__ignoreMap":162},[166,1744,1745,1747,1749],{"class":168,"line":169},[166,1746,1095],{"class":197},[166,1748,1398],{"class":374},[166,1750,259],{"class":197},[166,1752,1753,1755,1758,1760],{"class":168,"line":176},[166,1754,1663],{"class":193},[166,1756,1757],{"class":197}," { browser } ",[166,1759,201],{"class":193},[166,1761,1762],{"class":179}," '$app\u002Fenvironment'\n",[166,1764,1765,1767,1769,1771],{"class":168,"line":183},[166,1766,1663],{"class":193},[166,1768,901],{"class":197},[166,1770,201],{"class":193},[166,1772,1670],{"class":179},[166,1774,1775,1777,1779],{"class":168,"line":190},[166,1776,1138],{"class":197},[166,1778,1398],{"class":374},[166,1780,259],{"class":197},[166,1782,1783],{"class":168,"line":207},[166,1784,187],{"emptyLinePlaceholder":186},[166,1786,1787,1790,1793],{"class":168,"line":212},[166,1788,1789],{"class":197},"{#",[166,1791,1792],{"class":193},"if",[166,1794,1795],{"class":197}," browser}\n",[166,1797,1798,1800,1802,1804,1806,1808],{"class":168,"line":231},[166,1799,1105],{"class":197},[166,1801,247],{"class":246},[166,1803,1110],{"class":224},[166,1805,253],{"class":197},[166,1807,256],{"class":179},[166,1809,259],{"class":197},[166,1811,1812,1814,1816],{"class":168,"line":240},[166,1813,243],{"class":197},[166,1815,268],{"class":246},[166,1817,287],{"class":197},[166,1819,1820,1822,1824],{"class":168,"line":262},[166,1821,1129],{"class":197},[166,1823,247],{"class":246},[166,1825,259],{"class":197},[166,1827,1828,1831,1834],{"class":168,"line":290},[166,1829,1830],{"class":197},"{:",[166,1832,1833],{"class":193},"else",[166,1835,319],{"class":197},[166,1837,1838],{"class":168,"line":300},[166,1839,1840],{"class":172},"  \u003C!-- Optional server-rendered placeholder -->\n",[166,1842,1843,1845,1847,1849,1851,1854,1857,1859],{"class":168,"line":310},[166,1844,1105],{"class":197},[166,1846,1225],{"class":374},[166,1848,1110],{"class":224},[166,1850,253],{"class":197},[166,1852,1853],{"class":179},"\"w-full h-64 bg-gray-900 rounded\"",[166,1855,1856],{"class":197},">\u003C\u002F",[166,1858,1225],{"class":374},[166,1860,259],{"class":197},[166,1862,1863,1866,1868],{"class":168,"line":316},[166,1864,1865],{"class":197},"{\u002F",[166,1867,1792],{"class":193},[166,1869,319],{"class":197},[135,1871,1872],{},"Give the placeholder the same size as the shader to avoid layout shift.",[431,1874,1876],{"id":1875},"lazy-loading-the-components","Lazy-loading the components",[135,1878,1879,1880,1384],{},"To keep the Shaders bundle off the server entirely, import it in ",[10,1881,1721],{},[157,1883,1885],{"className":1646,"code":1884,"language":1648,"meta":162,"style":162},"\u003Cscript>\n  import { onMount } from 'svelte'\n\n  let ShaderComponent\n  let LinearGradientComponent\n\n  onMount(async () => {\n    const { Shader, LinearGradient } = await import('shaders\u002Fsvelte')\n    ShaderComponent = Shader\n    LinearGradientComponent = LinearGradient\n  })\n\u003C\u002Fscript>\n\n{#if ShaderComponent}\n  \u003Csvelte:component this={ShaderComponent} class=\"w-full h-64\">\n    \u003Csvelte:component this={LinearGradientComponent} \u002F>\n  \u003C\u002Fsvelte:component>\n{\u002Fif}\n",[10,1886,1887,1895,1907,1911,1919,1926,1930,1947,1978,1988,1998,2003,2011,2015,2024,2049,2064,2076],{"__ignoreMap":162},[166,1888,1889,1891,1893],{"class":168,"line":169},[166,1890,1095],{"class":197},[166,1892,1398],{"class":374},[166,1894,259],{"class":197},[166,1896,1897,1899,1902,1904],{"class":168,"line":176},[166,1898,1663],{"class":193},[166,1900,1901],{"class":197}," { onMount } ",[166,1903,201],{"class":193},[166,1905,1906],{"class":179}," 'svelte'\n",[166,1908,1909],{"class":168,"line":183},[166,1910,187],{"emptyLinePlaceholder":186},[166,1912,1913,1916],{"class":168,"line":190},[166,1914,1915],{"class":193},"  let",[166,1917,1918],{"class":197}," ShaderComponent\n",[166,1920,1921,1923],{"class":168,"line":207},[166,1922,1915],{"class":193},[166,1924,1925],{"class":197}," LinearGradientComponent\n",[166,1927,1928],{"class":168,"line":212},[166,1929,187],{"emptyLinePlaceholder":186},[166,1931,1932,1935,1937,1940,1943,1945],{"class":168,"line":231},[166,1933,1934],{"class":224},"  onMount",[166,1936,511],{"class":197},[166,1938,1939],{"class":193},"async",[166,1941,1942],{"class":197}," () ",[166,1944,505],{"class":193},[166,1946,969],{"class":197},[166,1948,1949,1952,1955,1957,1959,1961,1964,1966,1969,1971,1973,1976],{"class":168,"line":240},[166,1950,1951],{"class":193},"    const",[166,1953,1954],{"class":197}," { ",[166,1956,247],{"class":246},[166,1958,935],{"class":197},[166,1960,268],{"class":246},[166,1962,1963],{"class":197}," } ",[166,1965,253],{"class":193},[166,1967,1968],{"class":193}," await",[166,1970,508],{"class":193},[166,1972,511],{"class":197},[166,1974,1975],{"class":179},"'shaders\u002Fsvelte'",[166,1977,533],{"class":197},[166,1979,1980,1983,1985],{"class":168,"line":262},[166,1981,1982],{"class":197},"    ShaderComponent ",[166,1984,253],{"class":193},[166,1986,1987],{"class":197}," Shader\n",[166,1989,1990,1993,1995],{"class":168,"line":290},[166,1991,1992],{"class":197},"    LinearGradientComponent ",[166,1994,253],{"class":193},[166,1996,1997],{"class":197}," LinearGradient\n",[166,1999,2000],{"class":168,"line":300},[166,2001,2002],{"class":197},"  })\n",[166,2004,2005,2007,2009],{"class":168,"line":310},[166,2006,1138],{"class":197},[166,2008,1398],{"class":374},[166,2010,259],{"class":197},[166,2012,2013],{"class":168,"line":316},[166,2014,187],{"emptyLinePlaceholder":186},[166,2016,2017,2019,2021],{"class":168,"line":1022},[166,2018,1789],{"class":197},[166,2020,1792],{"class":193},[166,2022,2023],{"class":197}," ShaderComponent}\n",[166,2025,2026,2028,2030,2032,2034,2037,2040,2043,2045,2047],{"class":168,"line":1029},[166,2027,1105],{"class":197},[166,2029,1648],{"class":193},[166,2031,1384],{"class":197},[166,2033,1333],{"class":374},[166,2035,2036],{"class":224}," this",[166,2038,2039],{"class":197},"={ShaderComponent} ",[166,2041,2042],{"class":224},"class",[166,2044,253],{"class":197},[166,2046,256],{"class":179},[166,2048,259],{"class":197},[166,2050,2051,2053,2055,2057,2059,2061],{"class":168,"line":1044},[166,2052,243],{"class":197},[166,2054,1648],{"class":193},[166,2056,1384],{"class":197},[166,2058,1333],{"class":374},[166,2060,2036],{"class":224},[166,2062,2063],{"class":197},"={LinearGradientComponent} \u002F>\n",[166,2065,2066,2068,2070,2072,2074],{"class":168,"line":1053},[166,2067,1129],{"class":197},[166,2069,1648],{"class":193},[166,2071,1384],{"class":197},[166,2073,1333],{"class":374},[166,2075,259],{"class":197},[166,2077,2078,2080,2082],{"class":168,"line":1062},[166,2079,1865],{"class":197},[166,2081,1792],{"class":193},[166,2083,319],{"class":197},[145,2085,2087],{"id":2086},"using-solidstart","Using SolidStart",[135,2089,2090],{},"In SolidStart, put the shader in its own component:",[157,2092,2094],{"className":159,"code":2093,"language":161,"meta":162,"style":162},"\u002F\u002F components\u002FMyShader.jsx\nimport { Shader, LinearGradient } from 'shaders\u002Fsolid'\n\nexport default function MyShader() {\n  return (\n    \u003CShader class=\"w-full h-64\">\n      \u003CLinearGradient colorA=\"#0f172a\" colorB=\"#7c3aed\" \u002F>\n    \u003C\u002FShader>\n  )\n}\n",[10,2095,2096,2100,2111,2115,2127,2133,2147,2167,2175,2179],{"__ignoreMap":162},[166,2097,2098],{"class":168,"line":169},[166,2099,173],{"class":172},[166,2101,2102,2104,2106,2108],{"class":168,"line":176},[166,2103,194],{"class":193},[166,2105,901],{"class":197},[166,2107,201],{"class":193},[166,2109,2110],{"class":179}," 'shaders\u002Fsolid'\n",[166,2112,2113],{"class":168,"line":183},[166,2114,187],{"emptyLinePlaceholder":186},[166,2116,2117,2119,2121,2123,2125],{"class":168,"line":190},[166,2118,215],{"class":193},[166,2120,218],{"class":193},[166,2122,221],{"class":193},[166,2124,225],{"class":224},[166,2126,228],{"class":197},[166,2128,2129,2131],{"class":168,"line":207},[166,2130,234],{"class":193},[166,2132,237],{"class":197},[166,2134,2135,2137,2139,2141,2143,2145],{"class":168,"line":212},[166,2136,243],{"class":197},[166,2138,247],{"class":246},[166,2140,1110],{"class":224},[166,2142,253],{"class":193},[166,2144,256],{"class":179},[166,2146,259],{"class":197},[166,2148,2149,2151,2153,2155,2157,2159,2161,2163,2165],{"class":168,"line":231},[166,2150,265],{"class":197},[166,2152,268],{"class":246},[166,2154,271],{"class":224},[166,2156,253],{"class":193},[166,2158,276],{"class":179},[166,2160,279],{"class":224},[166,2162,253],{"class":193},[166,2164,284],{"class":179},[166,2166,287],{"class":197},[166,2168,2169,2171,2173],{"class":168,"line":240},[166,2170,303],{"class":197},[166,2172,247],{"class":246},[166,2174,259],{"class":197},[166,2176,2177],{"class":168,"line":262},[166,2178,313],{"class":197},[166,2180,2181],{"class":168,"line":290},[166,2182,319],{"class":197},[135,2184,2185,2186,1384],{},"Then load it with SolidStart's ",[10,2187,2188],{},"clientOnly",[157,2190,2192],{"className":159,"code":2191,"language":161,"meta":162,"style":162},"\u002F\u002F routes\u002Findex.jsx\nimport { clientOnly } from '@solidjs\u002Fstart'\n\nconst MyShader = clientOnly(() => import('..\u002Fcomponents\u002FMyShader'))\n\nexport default function Page() {\n  return (\n    \u003Cmain>\n      \u003CMyShader \u002F>\n      \u003Ch1>Your content\u003C\u002Fh1>\n    \u003C\u002Fmain>\n  )\n}\n",[10,2193,2194,2199,2211,2215,2240,2244,2256,2262,2270,2278,2290,2298,2302],{"__ignoreMap":162},[166,2195,2196],{"class":168,"line":169},[166,2197,2198],{"class":172},"\u002F\u002F routes\u002Findex.jsx\n",[166,2200,2201,2203,2206,2208],{"class":168,"line":176},[166,2202,194],{"class":193},[166,2204,2205],{"class":197}," { clientOnly } ",[166,2207,201],{"class":193},[166,2209,2210],{"class":179}," '@solidjs\u002Fstart'\n",[166,2212,2213],{"class":168,"line":183},[166,2214,187],{"emptyLinePlaceholder":186},[166,2216,2217,2219,2221,2223,2226,2228,2230,2232,2234,2237],{"class":168,"line":190},[166,2218,486],{"class":193},[166,2220,225],{"class":246},[166,2222,491],{"class":193},[166,2224,2225],{"class":224}," clientOnly",[166,2227,964],{"class":197},[166,2229,505],{"class":193},[166,2231,508],{"class":193},[166,2233,511],{"class":197},[166,2235,2236],{"class":179},"'..\u002Fcomponents\u002FMyShader'",[166,2238,2239],{"class":197},"))\n",[166,2241,2242],{"class":168,"line":207},[166,2243,187],{"emptyLinePlaceholder":186},[166,2245,2246,2248,2250,2252,2254],{"class":168,"line":212},[166,2247,215],{"class":193},[166,2249,218],{"class":193},[166,2251,221],{"class":193},[166,2253,359],{"class":224},[166,2255,228],{"class":197},[166,2257,2258,2260],{"class":168,"line":231},[166,2259,234],{"class":193},[166,2261,237],{"class":197},[166,2263,2264,2266,2268],{"class":168,"line":240},[166,2265,243],{"class":197},[166,2267,375],{"class":374},[166,2269,259],{"class":197},[166,2271,2272,2274,2276],{"class":168,"line":262},[166,2273,265],{"class":197},[166,2275,384],{"class":246},[166,2277,287],{"class":197},[166,2279,2280,2282,2284,2286,2288],{"class":168,"line":290},[166,2281,265],{"class":197},[166,2283,131],{"class":374},[166,2285,395],{"class":197},[166,2287,131],{"class":374},[166,2289,259],{"class":197},[166,2291,2292,2294,2296],{"class":168,"line":300},[166,2293,303],{"class":197},[166,2295,375],{"class":374},[166,2297,259],{"class":197},[166,2299,2300],{"class":168,"line":310},[166,2301,313],{"class":197},[166,2303,2304],{"class":168,"line":316},[166,2305,319],{"class":197},[135,2307,2308,2310,2311,2314,2315,429],{},[10,2309,2188],{}," wraps the component in a ",[10,2312,2313],{},"Suspense"," boundary and renders it only in the browser. During SSR it returns ",[10,2316,2317],{},"null",[431,2319,2321],{"id":2320},"using-solid-ssr-without-solidstart","Using Solid SSR without SolidStart",[135,2323,2324,2325,1384],{},"Without SolidStart, render the shader only after the component mounts, by setting a signal in ",[10,2326,1721],{},[157,2328,2330],{"className":159,"code":2329,"language":161,"meta":162,"style":162},"import { createSignal, onMount } from 'solid-js'\nimport { Shader, LinearGradient } from 'shaders\u002Fsolid'\n\nexport default function MyShader() {\n  const [mounted, setMounted] = createSignal(false)\n\n  \u002F\u002F onMount never runs on the server, so the signal stays false during SSR\n  onMount(() => setMounted(true))\n\n  return (\n    \u003Cdiv class=\"w-full h-64\">\n      {mounted() && (\n        \u003CShader class=\"w-full h-64\">\n          \u003CLinearGradient \u002F>\n        \u003C\u002FShader>\n      )}\n    \u003C\u002Fdiv>\n  )\n}\n",[10,2331,2332,2344,2354,2358,2370,2395,2399,2404,2421,2425,2431,2445,2460,2474,2483,2492,2497,2505,2509],{"__ignoreMap":162},[166,2333,2334,2336,2339,2341],{"class":168,"line":169},[166,2335,194],{"class":193},[166,2337,2338],{"class":197}," { createSignal, onMount } ",[166,2340,201],{"class":193},[166,2342,2343],{"class":179}," 'solid-js'\n",[166,2345,2346,2348,2350,2352],{"class":168,"line":176},[166,2347,194],{"class":193},[166,2349,901],{"class":197},[166,2351,201],{"class":193},[166,2353,2110],{"class":179},[166,2355,2356],{"class":168,"line":183},[166,2357,187],{"emptyLinePlaceholder":186},[166,2359,2360,2362,2364,2366,2368],{"class":168,"line":190},[166,2361,215],{"class":193},[166,2363,218],{"class":193},[166,2365,221],{"class":193},[166,2367,225],{"class":224},[166,2369,228],{"class":197},[166,2371,2372,2374,2376,2378,2380,2382,2384,2386,2389,2391,2393],{"class":168,"line":207},[166,2373,926],{"class":193},[166,2375,929],{"class":197},[166,2377,932],{"class":246},[166,2379,935],{"class":197},[166,2381,938],{"class":246},[166,2383,941],{"class":197},[166,2385,253],{"class":193},[166,2387,2388],{"class":224}," createSignal",[166,2390,511],{"class":197},[166,2392,525],{"class":246},[166,2394,533],{"class":197},[166,2396,2397],{"class":168,"line":212},[166,2398,187],{"emptyLinePlaceholder":186},[166,2400,2401],{"class":168,"line":231},[166,2402,2403],{"class":172},"  \u002F\u002F onMount never runs on the server, so the signal stays false during SSR\n",[166,2405,2406,2408,2410,2412,2415,2417,2419],{"class":168,"line":240},[166,2407,1934],{"class":224},[166,2409,964],{"class":197},[166,2411,505],{"class":193},[166,2413,2414],{"class":224}," setMounted",[166,2416,511],{"class":197},[166,2418,979],{"class":246},[166,2420,2239],{"class":197},[166,2422,2423],{"class":168,"line":262},[166,2424,187],{"emptyLinePlaceholder":186},[166,2426,2427,2429],{"class":168,"line":290},[166,2428,234],{"class":193},[166,2430,237],{"class":197},[166,2432,2433,2435,2437,2439,2441,2443],{"class":168,"line":300},[166,2434,243],{"class":197},[166,2436,1225],{"class":374},[166,2438,1110],{"class":224},[166,2440,253],{"class":193},[166,2442,256],{"class":179},[166,2444,259],{"class":197},[166,2446,2447,2450,2452,2455,2458],{"class":168,"line":310},[166,2448,2449],{"class":197},"      {",[166,2451,932],{"class":224},[166,2453,2454],{"class":197},"() ",[166,2456,2457],{"class":193},"&&",[166,2459,237],{"class":197},[166,2461,2462,2464,2466,2468,2470,2472],{"class":168,"line":316},[166,2463,737],{"class":197},[166,2465,247],{"class":246},[166,2467,1110],{"class":224},[166,2469,253],{"class":193},[166,2471,256],{"class":179},[166,2473,259],{"class":197},[166,2475,2476,2479,2481],{"class":168,"line":1022},[166,2477,2478],{"class":197},"          \u003C",[166,2480,268],{"class":246},[166,2482,287],{"class":197},[166,2484,2485,2488,2490],{"class":168,"line":1029},[166,2486,2487],{"class":197},"        \u003C\u002F",[166,2489,247],{"class":246},[166,2491,259],{"class":197},[166,2493,2494],{"class":168,"line":1044},[166,2495,2496],{"class":197},"      )}\n",[166,2498,2499,2501,2503],{"class":168,"line":1053},[166,2500,303],{"class":197},[166,2502,1225],{"class":374},[166,2504,259],{"class":197},[166,2506,2507],{"class":168,"line":1062},[166,2508,313],{"class":197},[166,2510,2511],{"class":168,"line":1067},[166,2512,319],{"class":197},[145,2514,2516],{"id":2515},"using-plain-javascript","Using plain JavaScript",[135,2518,2519,2522],{},[10,2520,2521],{},"createShader"," only runs where you call it, so there's nothing to turn off. Call it from code that runs in the browser, such as a script on the page or your framework's client-side hook, and the server never touches the GPU.",[145,2524,2526],{"id":2525},"next-steps","Next steps",[2528,2529,2530,2536,2541],"ul",{},[2531,2532,2533,2535],"li",{},[425,2534,13],{"href":12},": install the package and render your first effect.",[2531,2537,2538,2540],{},[425,2539,33],{"href":32},": place the canvas behind or around your UI.",[2531,2542,2543,2545],{},[425,2544,53],{"href":52},": what each layer costs and how to keep effects fast.",[2547,2548,2549],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .s6RL2, html code.shiki .s6RL2{--shiki-default:#FDAEB7;--shiki-default-font-style:italic}",{"title":162,"searchDepth":176,"depth":176,"links":2551},[2552,2558,2563,2568,2571,2572],{"id":147,"depth":176,"text":148,"children":2553},[2554,2556,2557],{"id":433,"depth":183,"text":2555},"Turning off SSR with next\u002Fdynamic",{"id":657,"depth":183,"text":658},{"id":873,"depth":183,"text":874},{"id":1072,"depth":176,"text":1073,"children":2559},[2560,2561,2562],{"id":1148,"depth":183,"text":1149},{"id":1260,"depth":183,"text":1261},{"id":1372,"depth":183,"text":1373},{"id":1636,"depth":176,"text":1637,"children":2564},[2565,2567],{"id":1724,"depth":183,"text":2566},"Rendering a placeholder with browser",{"id":1875,"depth":183,"text":1876},{"id":2086,"depth":176,"text":2087,"children":2569},[2570],{"id":2320,"depth":183,"text":2321},{"id":2515,"depth":176,"text":2516},{"id":2525,"depth":176,"text":2526},"md","server",{},{"title":82,"description":83},"docs\u002Fguide\u002F18.ssr","IbNx64VDe4L1Hcbqd7feY4nIW09N_Mz0lojFY5nlB_c"]