[{"data":1,"prerenderedAt":35514},["ShallowReactive",2],{"cmd-posts":3,"post-\u002Fblog\u002Fdrizzle-nitro-api":28773,"surround-\u002Fblog\u002Fdrizzle-nitro-api":32375,"related-drizzle-nitro-api":32378},[4,136,531,3517,4079,8240,8302,9381,10791,10997,11062,11113,11341,12035,12670,12995,13754,18717,20061,20158,20910,21137,22517,23331,24471,28160,28752],{"id":5,"title":6,"author":7,"body":11,"canonical":115,"categories":115,"date":116,"description":117,"excerpt":115,"extension":118,"img":119,"keywords":120,"language":127,"meta":128,"navigation":129,"ogImage":115,"path":130,"rating":131,"readTime":132,"seo":133,"stem":134,"tag":125,"__hash__":135},"blog\u002Fblog\u002Fadd-env-variables-runtime.md","Adding environment variables to the runtime in Nuxt3 [Beta]",{"name":8,"website":9,"img":10},"Vantol Bennett","www.teammps.com","https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1636919468\u002FDSC_0988_zsfhgy.jpg",{"type":12,"value":13,"toc":109},"minimark",[14,19,23,30,35,43,46,56,59,63,66,71,74,76,82,88,91,97,100,106],[15,16,18],"h1",{"id":17},"runtime-config-in-nuxt-3","Runtime Config in Nuxt 3",[20,21,22],"p",{},"Nuxt3 is still in beta and is not ready for production use (ish), but that hasn't stopped many developers to take advantage of the unique features, power and significant performance boost that Nuxt3 offers.",[24,25,27],"blog-alert",{"type":26},"warning",[20,28,29],{},"Nuxt 3 is now stable! The information below refers to early RC versions but the core concepts of Runtime Config remain valid.",[31,32,34],"h2",{"id":33},"exposing-environment-variables-to-the-runtime","Exposing Environment Variables to the Runtime",[20,36,37,38,42],{},"All the heavy lifting is done by Nuxt in the nuxt.config.js file. This file is where you can set up the environment variables that you want to expose to the rest of the application. This is done by adding the ",[39,40,41],"code",{},"privateRuntimeConfig"," or publicRuntimeConfig` property to the nuxt.config.js file. As the name suggests, both of these properties are used based on accessiblity on the client side or server side.",[20,44,45],{},"Example:",[47,48,53],"pre",{"className":49,"code":51,"language":52},[50],"language-text","\nexport default defineNuxtConfig({\n  ...\n  publicRuntimeConfig: {\n    \u002F\u002F Will be available on both server and client\n    apiUrl: 'https:\u002F\u002Fapi.example.com',\n  },\n  privateRuntimeConfig: {\n    apiUrl: process.env.API_URL,\n    apiKey: process.env.API_KEY,\n    ...\n  },\n  ...\n})\n","text",[39,54,51],{"__ignoreMap":55},"",[20,57,58],{},"The publicRuntimeConfig property will be added to Nuxt pages through the apiUrl allowing for universal access for apiUrl to both client and server.",[31,60,62],{"id":61},"environmental-variables-using-supabase","Environmental Variables - Using Supabase",[20,64,65],{},"Ok so, whether you are a new developer or a experienced one environment variables are common way to access configuration. We add a .env file to the root directory, Nuxt will added these variables to process.env and is accessible in nuxt.config.js. Let see what how to add Supabase url and key.",[20,67,68],{},[39,69,70],{},"npm install @supabase\u002Fsupabase-js",[72,73],"hr",{},[20,75,45],{},[47,77,80],{"className":78,"code":79,"language":52},[50],".env\n\nSUPABASE_URL=\u002F* URL KEY HERE*\u002F\nSUPABASE_ANON_KEY=\u002F* KEY ADDED HERE *\u002F\n\n",[39,81,79],{"__ignoreMap":55},[47,83,86],{"className":84,"code":85,"language":52},[50],"\nexport default defineNuxtConfig({\n  ...\n  publicRuntimeConfig: {\n    \u002F\u002F Will be available on both server and client\n    SUPABASE_URL: process.env.SUPABASE_URL,\n    SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY\n  },\n  ...\n})\n",[39,87,85],{"__ignoreMap":55},[20,89,90],{},"This is important part of this post, accessing the supabase variables in the publicRunTime config can only be done on the client side using the useRunTimeConfig in the setup or lifecycle hooks. This is a crucial step to remember!",[47,92,95],{"className":93,"code":94,"language":52},[50],"\u003Ctemplate>\n  \u003Cdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst config = useRuntimeConfig()\n\u003C\u002Fscript>\n",[39,96,94],{"__ignoreMap":55},[20,98,99],{},"useRuntimeConfig only works in setup or lifecycle hooks.... this was a pain for me as I could not discover the error because of this, and more importantly since env variables are accessed in the publicRuntimeConfig so only on the client side. Therefore in setting up we could connect supabase with our runtime.",[47,101,104],{"className":102,"code":103,"language":52},[50],"import { createClient } from '@supabase\u002Fsupabase-js'\n\n.....\n\n....\n\nconst config = useRuntimeConfig()\n\nconst supabase = createClient(config.SUPABASE_URL, config.SUPABASE_KEY)\n\n\u002F* Followed by the supabase implementation you would like to work on*\u002F\n",[39,105,103],{"__ignoreMap":55},[20,107,108],{},"And thats how you get access to your env variables. In my next post we will explore how to you use composables and plugins to achieve this whole setup but with cleaner out look.",{"title":55,"searchDepth":110,"depth":110,"links":111},3,[112,114],{"id":33,"depth":113,"text":34},2,{"id":61,"depth":113,"text":62},null,"2022-01-15","Exposing environment variables to the runtime in Nuxt3","md","https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1642350413\u002Fvantol\u002Fblack-text_emxagi.png",[121,122,123,124,125,126],"developer","jamaican","vue.js","supabase","Nuxt3","vite","Javascript - Vue.js",{},true,"\u002Fblog\u002Fadd-env-variables-runtime",0,10,{"title":6,"description":117},"blog\u002Fadd-env-variables-runtime","4SK4zZT99RtjhiV4e4jmQppT3cFMuHnutSwWRAwb8Lo",{"id":137,"title":138,"author":139,"body":140,"canonical":115,"categories":115,"date":511,"description":512,"excerpt":513,"extension":118,"img":521,"keywords":522,"language":524,"meta":525,"navigation":129,"ogImage":115,"path":526,"rating":131,"readTime":393,"seo":527,"stem":528,"tag":529,"__hash__":530},"blog\u002Fblog\u002Fbuilding-vue3-progressive-app.md","Building a Vue 3 Progressive Koffee Lovers App Part One",{"name":8,"website":9,"img":10},{"type":12,"value":141,"toc":503},[142,146,150,153,156,160,168,171,177,181,184,190,193,199,208,212,215,219,225,229,232,238,241,475,478,481,487,490,496,499],[15,143,145],{"id":144},"what-are-we-making","What are We Making?",[31,147,149],{"id":148},"koffee-lovers-vue3-pwa","Koffee Lovers Vue3 PWA",[20,151,152],{},"In this post, we will look at building a coffee web application with progressive web app (PWA).",[20,154,155],{},"Examining the workings of Vue3, creating components, using directives and use props to pass data to components.  We can also try and utilize mixins to reduce reptition of code by abstracting out similar features in these components.",[31,157,159],{"id":158},"teacher-mode-what-is-a-pwa","Teacher Mode: What is a PWA?",[161,162,165],"callout",{"icon":163,"title":164},"🎓","Teacher Mode",[20,166,167],{},"“PWAs are special web apps that can be installed on the user's computer, and the browser manages these installed apps. They differ from regular web apps as they let us access some computer hardware natively. When we visit a PWA in our browsers, we can choose to install the PWA”",[20,169,170],{},"This is basically what a PWA is - an app that can work offline once install on the users device.",[172,173,174],"tip",{},[20,175,176],{},"Always test your PWA in an Incognito window or after clearing site data to ensure the service worker is fetching fresh assets correctly during development.",[31,178,180],{"id":179},"lets-code","Lets Code!",[20,182,183],{},"We will be using Vite for quick prototyping our app.",[47,185,188],{"className":186,"code":187,"language":52},[50],"npm init vite@latest\n",[39,189,187],{"__ignoreMap":55},[20,191,192],{},"Follow the prompt name your app whatever you like but we will call this vue3-koffee-lovers",[47,194,197],{"className":195,"code":196,"language":52},[50],"npm run dev\n",[39,198,196],{"__ignoreMap":55},[20,200,201,202],{},"Your development server should be running on ",[203,204,205],"a",{"href":205,"rel":206},"http:\u002F\u002Flocalhost:3000",[207],"nofollow",[31,209,211],{"id":210},"layout","Layout",[20,213,214],{},"Generally its important to get the layout of your web application up and running by creating all the folders necessary for you web application to work smoothly. One such folder is your Components Folder. Vue.js is a progressive framework for building user interfaces, through the use of components.",[31,216,218],{"id":217},"setting-up-pwa","Setting up PWA",[47,220,223],{"className":221,"code":222,"language":52},[50],"npm install vite-plugin-pwa workbox-precaching -D\n",[39,224,222],{"__ignoreMap":55},[31,226,228],{"id":227},"config","Config",[20,230,231],{},"Configuration can be done in vite.config.js file. Installation of the plugin would look something this:",[47,233,236],{"className":234,"code":235,"language":52},[50],"import { defineConfig } from \"vite\"\nimport vue from \"@vitejs\u002Fplugin-vue\"\nimport { VitePWA } from \"vite-plugin-pwa\"\n\nexport default defineConfig({\n     plugins: [ vue(), VitePWA()],\n})\n\n",[39,237,235],{"__ignoreMap":55},[20,239,240],{},"This basically enables the plugin however there are additional setup required in order to get PWA to work correctly on devices. Look at the following code:",[47,242,247],{"className":243,"code":244,"language":245,"meta":246,"style":55},"language-\u002F\u002F shiki shiki-themes github-light github-dark","export default defineConfig({\n  plugins: [\n    vue(),\n    VitePWA({\n      mode: \"development\",\n      base: \"\u002F\",\n      srcDir: \"src\",\n      filename: \"sw.ts\",\n      includeAssets: [\"\u002Ffavicon.png\"],\n      strategies: \"injectManifest\",\n      manifest: {\n        name: \"Test Project\",\n        short_name: \"Test\",\n        theme_color: \"#ffffff\",\n        start_url: \"\u002F\",\n        display: \"standalone\",\n        background_color: \"#ffffff\",\n        icons: [\n          {\n            src: \"icon-192.png\",\n            sizes: \"192x192\",\n            type: \"image\u002Fpng\",\n          },\n          {\n            src: \"\u002Ficon-512.png\",\n            sizes: \"512x512\",\n            type: \"image\u002Fpng\",\n          },\n          {\n            src: \"icon-512.png\",\n            sizes: \"512x512\",\n            type: \"image\u002Fpng\",\n            purpose: \"any maskable\",\n          },\n        ],\n      },\n    }),\n  ],\n})\n\n","\u002F\u002F","https:\u002F\u002Fvitejs.dev\u002Fconfig\u002F",[39,248,249,257,262,267,273,279,285,291,297,303,308,314,320,326,332,338,344,350,356,362,368,374,380,386,391,397,403,408,413,418,424,429,434,440,445,451,457,463,469],{"__ignoreMap":55},[250,251,254],"span",{"class":252,"line":253},"line",1,[250,255,256],{},"export default defineConfig({\n",[250,258,259],{"class":252,"line":113},[250,260,261],{},"  plugins: [\n",[250,263,264],{"class":252,"line":110},[250,265,266],{},"    vue(),\n",[250,268,270],{"class":252,"line":269},4,[250,271,272],{},"    VitePWA({\n",[250,274,276],{"class":252,"line":275},5,[250,277,278],{},"      mode: \"development\",\n",[250,280,282],{"class":252,"line":281},6,[250,283,284],{},"      base: \"\u002F\",\n",[250,286,288],{"class":252,"line":287},7,[250,289,290],{},"      srcDir: \"src\",\n",[250,292,294],{"class":252,"line":293},8,[250,295,296],{},"      filename: \"sw.ts\",\n",[250,298,300],{"class":252,"line":299},9,[250,301,302],{},"      includeAssets: [\"\u002Ffavicon.png\"],\n",[250,304,305],{"class":252,"line":132},[250,306,307],{},"      strategies: \"injectManifest\",\n",[250,309,311],{"class":252,"line":310},11,[250,312,313],{},"      manifest: {\n",[250,315,317],{"class":252,"line":316},12,[250,318,319],{},"        name: \"Test Project\",\n",[250,321,323],{"class":252,"line":322},13,[250,324,325],{},"        short_name: \"Test\",\n",[250,327,329],{"class":252,"line":328},14,[250,330,331],{},"        theme_color: \"#ffffff\",\n",[250,333,335],{"class":252,"line":334},15,[250,336,337],{},"        start_url: \"\u002F\",\n",[250,339,341],{"class":252,"line":340},16,[250,342,343],{},"        display: \"standalone\",\n",[250,345,347],{"class":252,"line":346},17,[250,348,349],{},"        background_color: \"#ffffff\",\n",[250,351,353],{"class":252,"line":352},18,[250,354,355],{},"        icons: [\n",[250,357,359],{"class":252,"line":358},19,[250,360,361],{},"          {\n",[250,363,365],{"class":252,"line":364},20,[250,366,367],{},"            src: \"icon-192.png\",\n",[250,369,371],{"class":252,"line":370},21,[250,372,373],{},"            sizes: \"192x192\",\n",[250,375,377],{"class":252,"line":376},22,[250,378,379],{},"            type: \"image\u002Fpng\",\n",[250,381,383],{"class":252,"line":382},23,[250,384,385],{},"          },\n",[250,387,389],{"class":252,"line":388},24,[250,390,361],{},[250,392,394],{"class":252,"line":393},25,[250,395,396],{},"            src: \"\u002Ficon-512.png\",\n",[250,398,400],{"class":252,"line":399},26,[250,401,402],{},"            sizes: \"512x512\",\n",[250,404,406],{"class":252,"line":405},27,[250,407,379],{},[250,409,411],{"class":252,"line":410},28,[250,412,385],{},[250,414,416],{"class":252,"line":415},29,[250,417,361],{},[250,419,421],{"class":252,"line":420},30,[250,422,423],{},"            src: \"icon-512.png\",\n",[250,425,427],{"class":252,"line":426},31,[250,428,402],{},[250,430,432],{"class":252,"line":431},32,[250,433,379],{},[250,435,437],{"class":252,"line":436},33,[250,438,439],{},"            purpose: \"any maskable\",\n",[250,441,443],{"class":252,"line":442},34,[250,444,385],{},[250,446,448],{"class":252,"line":447},35,[250,449,450],{},"        ],\n",[250,452,454],{"class":252,"line":453},36,[250,455,456],{},"      },\n",[250,458,460],{"class":252,"line":459},37,[250,461,462],{},"    }),\n",[250,464,466],{"class":252,"line":465},38,[250,467,468],{},"  ],\n",[250,470,472],{"class":252,"line":471},39,[250,473,474],{},"})\n",[20,476,477],{},"Every PWA must have a manifest. A Manifest is a file that defines (in JSON format) the name of the application, the background color that it will have on the device once installed, the location, formats of the icons used and the root url for PWA (web application can have different url for web and PWA). That is, the minimum requirements necessary for PWA.",[20,479,480],{},"Next is to config the Service Worker (this allows code to run in the background and secondary actions being able to work). Service Worker is located in src\u002Fswt.(js or ts)",[47,482,485],{"className":483,"code":484,"language":52},[50],"import { precacheAndRoute } from 'workbox-precaching'\ndeclare let self: ServiceWorkerGlobalScope\nself.addEventListener('message', (event) => {\n  if (event.data && event.data.type === 'SKIP_WAITING') self.skipWaiting()\n})\n\u002F\u002F self.__WB_MANIFEST is default injection point\nprecacheAndRoute(self.__WB_MANIFEST)\n",[39,486,484],{"__ignoreMap":55},[20,488,489],{},"Finally! its just to register the PWA using a component.",[47,491,494],{"className":492,"code":493,"language":52},[50],"\u003Cscript lang=\"ts\">\nimport { defineComponent } from \"vue\";\nimport { useRegisterSW } from \"virtual:pwa-register\u002Fvue\";\nconst { updateServiceWorker } = useRegisterSW();\nexport default defineComponent({\n  name: \"ReloadPWA\",\n  setup() {\n    const { offlineReady, needRefresh, updateServiceWorker } = useRegisterSW();\n    const close = async () => {\n      offlineReady.value = false;\n      needRefresh.value = false;\n    };\n    return { offlineReady, needRefresh, updateServiceWorker, close };\n  },\n  methods: {\n    async close() {\n      this.offlineReady.value = false;\n      this.needRefresh.value = false;\n    },\n    async updateServiceWorker() {\n      await updateServiceWorker();\n    },\n  },\n});\n\u003C\u002Fscript>\n",[39,495,493],{"__ignoreMap":55},[20,497,498],{},"Once connection is made in this component to App.vue, PWA will be fully setup",[500,501,502],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":55,"searchDepth":110,"depth":110,"links":504},[505,506,507,508,509,510],{"id":148,"depth":113,"text":149},{"id":158,"depth":113,"text":159},{"id":179,"depth":113,"text":180},{"id":210,"depth":113,"text":211},{"id":217,"depth":113,"text":218},{"id":227,"depth":113,"text":228},"2022-01-20","Examine the inner workings of a Vue 3 app combining technologies like Supabase, Pinia to complete this code.",{"type":12,"value":514},[515,517,519],[15,516,145],{"id":144},[31,518,149],{"id":148},[20,520,152],{},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1642478176\u002Fvantol\u002FScreenshot_2021-07-29_at_11.07.21_PM_mepvjg.png",[121,122,123,124,523,126],"pinia","Vue.js",{},"\u002Fblog\u002Fbuilding-vue3-progressive-app",{"title":138,"description":512},"blog\u002Fbuilding-vue3-progressive-app","Coffee App","nSXNk7VFe35Q4XtBMRQ7h9qffsD9OFtiLz6IpNEqhfs",{"id":532,"title":533,"author":534,"body":536,"canonical":115,"categories":115,"date":3470,"description":3471,"excerpt":3472,"extension":118,"img":3502,"keywords":3503,"language":3510,"meta":3511,"navigation":129,"ogImage":115,"path":3512,"rating":275,"readTime":132,"seo":3513,"stem":3514,"tag":3515,"__hash__":3516},"blog\u002Fblog\u002Fbun-nitro-stack.md","Bun + Nitro: The Fast Server Stack for 2026",{"name":8,"img":10,"website":535},"https:\u002F\u002Fvantolbennett.com",{"type":12,"value":537,"toc":3438},[538,542,550,557,560,579,586,590,593,597,629,635,637,641,644,733,736,743,745,749,753,756,812,815,833,835,839,842,877,882,885,897,900,992,994,998,1001,1008,1078,1081,1083,1087,1090,1096,1166,1172,1347,1350,1687,1689,1693,1696,1711,1718,1721,1740,1742,1746,1749,1754,2413,2416,2452,2454,2458,2463,2466,2627,2631,2634,2717,2721,2724,2911,2913,2917,2921,3029,3033,3057,3059,3063,3067,3072,3089,3093,3149,3153,3213,3217,3220,3244,3251,3253,3257,3260,3277,3281,3347,3349,3353,3359,3390,3393,3397,3414,3418,3429,3432,3435],[15,539,541],{"id":540},"introduction","Introduction",[20,543,544,545,549],{},"The JavaScript ecosystem is evolving fast, and ",[546,547,548],"strong",{},"Bun"," is leading the charge. Since its 1.0 release, Bun has proven itself as a legitimate alternative to Node.js—offering significantly faster startup times, native TypeScript support, and an all-in-one toolkit that includes a package manager, bundler, and test runner.",[20,551,552,553,556],{},"When paired with ",[546,554,555],{},"Nitro",", you get a server stack that's both incredibly fast and deployment-agnostic.",[20,558,559],{},"In this post, we'll explore:",[561,562,563,567,570,573,576],"ul",{},[564,565,566],"li",{},"Why Bun matters in 2026",[564,568,569],{},"Setting up Bun with Nitro",[564,571,572],{},"Performance benefits and benchmarks",[564,574,575],{},"Migration strategies from Node.js",[564,577,578],{},"Real-world deployment",[20,580,581,582,585],{},"Let's build the ",[546,583,584],{},"fastest server stack"," you've ever used.",[15,587,589],{"id":588},"why-bun-in-2026","Why Bun in 2026?",[20,591,592],{},"Bun isn't just a faster Node.js—it's a reimagining of the JavaScript runtime. Here's what makes it special:",[31,594,596],{"id":595},"key-features","Key Features",[561,598,599,605,611,617,623],{},[564,600,601,604],{},[546,602,603],{},"Native TypeScript"," — No transpilation needed, runs .ts files directly",[564,606,607,610],{},[546,608,609],{},"Zig-based runtime"," — Built with performance in mind from the ground up",[564,612,613,616],{},[546,614,615],{},"All-in-one toolkit"," — Package manager, bundler, test runner included",[564,618,619,622],{},[546,620,621],{},"Web API compatibility"," — fetch, WebSocket, Buffer built-in",[564,624,625,628],{},[546,626,627],{},"Native Node.js compatibility"," — Most npm packages work out of the box",[24,630,632],{"type":631},"info",[20,633,634],{},"Bun's startup time is 4-6x faster than Node.js, and it can handle significantly more requests per second in I\u002FO-heavy workloads.",[72,636],{},[31,638,640],{"id":639},"performance-benchmarks","Performance Benchmarks",[20,642,643],{},"Let's look at real-world performance comparisons:",[645,646,647,665],"table",{},[648,649,650],"thead",{},[651,652,653,657,660,662],"tr",{},[654,655,656],"th",{},"Metric",[654,658,659],{},"Node.js",[654,661,548],{},[654,663,664],{},"Improvement",[666,667,668,685,701,717],"tbody",{},[651,669,670,674,677,680],{},[671,672,673],"td",{},"Startup time",[671,675,676],{},"45ms",[671,678,679],{},"8ms",[671,681,682],{},[546,683,684],{},"5.6x faster",[651,686,687,690,693,696],{},[671,688,689],{},"HTTP requests\u002Fsec",[671,691,692],{},"12,400",[671,694,695],{},"48,200",[671,697,698],{},[546,699,700],{},"3.9x faster",[651,702,703,706,709,712],{},[671,704,705],{},"TypeScript execution",[671,707,708],{},"180ms",[671,710,711],{},"12ms",[671,713,714],{},[546,715,716],{},"15x faster",[651,718,719,722,725,728],{},[671,720,721],{},"Memory usage",[671,723,724],{},"120MB",[671,726,727],{},"85MB",[671,729,730],{},[546,731,732],{},"29% less",[20,734,735],{},"These aren't synthetic benchmarks—they're representative of real API workloads.",[161,737,740],{"icon":738,"title":739},"📊","Real Application Performance",[20,741,742],{},"In our BrewStop API tests, switching from Node.js to Bun reduced cold start times from 2.1s to 340ms—an 85% improvement.",[72,744],{},[15,746,748],{"id":747},"main-content","Main Content",[31,750,752],{"id":751},"step-1-install-bun","Step 1: Install Bun",[20,754,755],{},"If you haven't installed Bun yet, it's a single command:",[47,757,762],{"className":758,"code":759,"filename":760,"language":761,"meta":55,"style":55},"language-bash shiki shiki-themes github-light github-dark","# macOS, Linux, and WSL\ncurl -fsSL https:\u002F\u002Fbun.sh\u002Finstall | bash\n\n# Windows (PowerShell)\nwinget install oven-sh.bun\n","terminal","bash",[39,763,764,770,791,796,801],{"__ignoreMap":55},[250,765,766],{"class":252,"line":253},[250,767,769],{"class":768},"sJ8bj","# macOS, Linux, and WSL\n",[250,771,772,776,780,784,788],{"class":252,"line":113},[250,773,775],{"class":774},"sScJk","curl",[250,777,779],{"class":778},"sj4cs"," -fsSL",[250,781,783],{"class":782},"sZZnC"," https:\u002F\u002Fbun.sh\u002Finstall",[250,785,787],{"class":786},"szBVR"," |",[250,789,790],{"class":774}," bash\n",[250,792,793],{"class":252,"line":110},[250,794,795],{"emptyLinePlaceholder":129},"\n",[250,797,798],{"class":252,"line":269},[250,799,800],{"class":768},"# Windows (PowerShell)\n",[250,802,803,806,809],{"class":252,"line":275},[250,804,805],{"class":774},"winget",[250,807,808],{"class":782}," install",[250,810,811],{"class":782}," oven-sh.bun\n",[20,813,814],{},"Verify installation:",[47,816,818],{"className":758,"code":817,"filename":760,"language":761,"meta":55,"style":55},"bun --version\n# Should output: 1.2.x or higher\n",[39,819,820,828],{"__ignoreMap":55},[250,821,822,825],{"class":252,"line":253},[250,823,824],{"class":774},"bun",[250,826,827],{"class":778}," --version\n",[250,829,830],{"class":252,"line":113},[250,831,832],{"class":768},"# Should output: 1.2.x or higher\n",[72,834],{},[31,836,838],{"id":837},"step-2-create-a-bun-nitro-project","Step 2: Create a Bun + Nitro Project",[20,840,841],{},"The easiest way to start is with Nuxt, which has built-in Nitro support:",[47,843,845],{"className":758,"code":844,"filename":760,"language":761,"meta":55,"style":55},"# Create a new Nuxt project (uses Nitro internally)\nbunx nuxi@latest init brewstop-bun\n\ncd brewstop-bun\n",[39,846,847,852,866,870],{"__ignoreMap":55},[250,848,849],{"class":252,"line":253},[250,850,851],{"class":768},"# Create a new Nuxt project (uses Nitro internally)\n",[250,853,854,857,860,863],{"class":252,"line":113},[250,855,856],{"class":774},"bunx",[250,858,859],{"class":782}," nuxi@latest",[250,861,862],{"class":782}," init",[250,864,865],{"class":782}," brewstop-bun\n",[250,867,868],{"class":252,"line":110},[250,869,795],{"emptyLinePlaceholder":129},[250,871,872,875],{"class":252,"line":269},[250,873,874],{"class":778},"cd",[250,876,865],{"class":782},[24,878,879],{"type":26},[20,880,881],{},"Bun's package manager (bun install) is significantly faster than npm\u002Fyarn\u002Fpnpm. Use it for the best experience.",[20,883,884],{},"Install dependencies with Bun:",[47,886,888],{"className":758,"code":887,"filename":760,"language":761,"meta":55,"style":55},"bun install\n",[39,889,890],{"__ignoreMap":55},[250,891,892,894],{"class":252,"line":253},[250,893,824],{"class":774},[250,895,896],{"class":782}," install\n",[20,898,899],{},"Update the package.json to use Bun as the package manager:",[47,901,906],{"className":902,"code":903,"filename":904,"language":905,"meta":55,"style":55},"language-json shiki shiki-themes github-light github-dark","{\n  \"packageManager\": \"bun@1.2.0\",\n  \"scripts\": {\n    \"dev\": \"bunx nuxi dev\",\n    \"build\": \"bunx nuxi build\",\n    \"preview\": \"bunx nuxi preview\",\n    \"start\": \"bunx nuxi start\"\n  }\n}\n","package.json","json",[39,907,908,914,928,936,948,960,972,982,987],{"__ignoreMap":55},[250,909,910],{"class":252,"line":253},[250,911,913],{"class":912},"sVt8B","{\n",[250,915,916,919,922,925],{"class":252,"line":113},[250,917,918],{"class":778},"  \"packageManager\"",[250,920,921],{"class":912},": ",[250,923,924],{"class":782},"\"bun@1.2.0\"",[250,926,927],{"class":912},",\n",[250,929,930,933],{"class":252,"line":110},[250,931,932],{"class":778},"  \"scripts\"",[250,934,935],{"class":912},": {\n",[250,937,938,941,943,946],{"class":252,"line":269},[250,939,940],{"class":778},"    \"dev\"",[250,942,921],{"class":912},[250,944,945],{"class":782},"\"bunx nuxi dev\"",[250,947,927],{"class":912},[250,949,950,953,955,958],{"class":252,"line":275},[250,951,952],{"class":778},"    \"build\"",[250,954,921],{"class":912},[250,956,957],{"class":782},"\"bunx nuxi build\"",[250,959,927],{"class":912},[250,961,962,965,967,970],{"class":252,"line":281},[250,963,964],{"class":778},"    \"preview\"",[250,966,921],{"class":912},[250,968,969],{"class":782},"\"bunx nuxi preview\"",[250,971,927],{"class":912},[250,973,974,977,979],{"class":252,"line":287},[250,975,976],{"class":778},"    \"start\"",[250,978,921],{"class":912},[250,980,981],{"class":782},"\"bunx nuxi start\"\n",[250,983,984],{"class":252,"line":293},[250,985,986],{"class":912},"  }\n",[250,988,989],{"class":252,"line":299},[250,990,991],{"class":912},"}\n",[72,993],{},[31,995,997],{"id":996},"step-3-configure-nitro-to-use-bun","Step 3: Configure Nitro to Use Bun",[20,999,1000],{},"Nuxt automatically detects Bun when it's available. However, let's explicitly configure it for clarity.",[20,1002,1003,1004,1007],{},"Update ",[39,1005,1006],{},"nuxt.config.ts",":",[47,1009,1013],{"className":1010,"code":1011,"filename":1006,"language":1012,"meta":55,"style":55},"language-ts shiki shiki-themes github-light github-dark","export default defineNuxtConfig({\n  nitro: {\n    preset: \"bun\",\n  },\n  \n  devtools: {\n    enabled: true,\n  },\n});\n","ts",[39,1014,1015,1029,1034,1044,1049,1054,1059,1069,1073],{"__ignoreMap":55},[250,1016,1017,1020,1023,1026],{"class":252,"line":253},[250,1018,1019],{"class":786},"export",[250,1021,1022],{"class":786}," default",[250,1024,1025],{"class":774}," defineNuxtConfig",[250,1027,1028],{"class":912},"({\n",[250,1030,1031],{"class":252,"line":113},[250,1032,1033],{"class":912},"  nitro: {\n",[250,1035,1036,1039,1042],{"class":252,"line":110},[250,1037,1038],{"class":912},"    preset: ",[250,1040,1041],{"class":782},"\"bun\"",[250,1043,927],{"class":912},[250,1045,1046],{"class":252,"line":269},[250,1047,1048],{"class":912},"  },\n",[250,1050,1051],{"class":252,"line":275},[250,1052,1053],{"class":912},"  \n",[250,1055,1056],{"class":252,"line":281},[250,1057,1058],{"class":912},"  devtools: {\n",[250,1060,1061,1064,1067],{"class":252,"line":287},[250,1062,1063],{"class":912},"    enabled: ",[250,1065,1066],{"class":778},"true",[250,1068,927],{"class":912},[250,1070,1071],{"class":252,"line":293},[250,1072,1048],{"class":912},[250,1074,1075],{"class":252,"line":299},[250,1076,1077],{"class":912},"});\n",[20,1079,1080],{},"This ensures Nitro uses Bun's optimized runtime for both development and production.",[72,1082],{},[31,1084,1086],{"id":1085},"step-4-create-api-endpoints","Step 4: Create API Endpoints",[20,1088,1089],{},"Let's build a simple API to test Bun's performance.",[20,1091,1092,1093,1007],{},"Create ",[39,1094,1095],{},"server\u002Fapi\u002Fping.get.ts",[47,1097,1099],{"className":1010,"code":1098,"filename":1095,"language":1012,"meta":55,"style":55},"export default defineEventHandler(() => {\n  return {\n    message: \"Pong from Bun!\",\n    runtime: \"Bun\",\n    timestamp: Date.now(),\n  };\n});\n",[39,1100,1101,1119,1126,1136,1146,1157,1162],{"__ignoreMap":55},[250,1102,1103,1105,1107,1110,1113,1116],{"class":252,"line":253},[250,1104,1019],{"class":786},[250,1106,1022],{"class":786},[250,1108,1109],{"class":774}," defineEventHandler",[250,1111,1112],{"class":912},"(() ",[250,1114,1115],{"class":786},"=>",[250,1117,1118],{"class":912}," {\n",[250,1120,1121,1124],{"class":252,"line":113},[250,1122,1123],{"class":786},"  return",[250,1125,1118],{"class":912},[250,1127,1128,1131,1134],{"class":252,"line":110},[250,1129,1130],{"class":912},"    message: ",[250,1132,1133],{"class":782},"\"Pong from Bun!\"",[250,1135,927],{"class":912},[250,1137,1138,1141,1144],{"class":252,"line":269},[250,1139,1140],{"class":912},"    runtime: ",[250,1142,1143],{"class":782},"\"Bun\"",[250,1145,927],{"class":912},[250,1147,1148,1151,1154],{"class":252,"line":275},[250,1149,1150],{"class":912},"    timestamp: Date.",[250,1152,1153],{"class":774},"now",[250,1155,1156],{"class":912},"(),\n",[250,1158,1159],{"class":252,"line":281},[250,1160,1161],{"class":912},"  };\n",[250,1163,1164],{"class":252,"line":287},[250,1165,1077],{"class":912},[20,1167,1092,1168,1171],{},[39,1169,1170],{},"server\u002Fapi\u002Fproducts.get.ts"," with some data:",[47,1173,1175],{"className":1010,"code":1174,"filename":1170,"language":1012,"meta":55,"style":55},"const products = [\n  { id: 1, name: \"Latte\", price: 4.5, category: \"coffee\" },\n  { id: 2, name: \"Espresso\", price: 3.0, category: \"coffee\" },\n  { id: 3, name: \"Croissant\", price: 3.5, category: \"food\" },\n  { id: 4, name: \"Chai Tea\", price: 4.0, category: \"tea\" },\n  { id: 5, name: \"Muffin\", price: 3.0, category: \"food\" },\n];\n\nexport default defineEventHandler(() => {\n  return { products };\n});\n",[39,1176,1177,1191,1220,1243,1267,1291,1313,1318,1322,1336,1343],{"__ignoreMap":55},[250,1178,1179,1182,1185,1188],{"class":252,"line":253},[250,1180,1181],{"class":786},"const",[250,1183,1184],{"class":778}," products",[250,1186,1187],{"class":786}," =",[250,1189,1190],{"class":912}," [\n",[250,1192,1193,1196,1199,1202,1205,1208,1211,1214,1217],{"class":252,"line":113},[250,1194,1195],{"class":912},"  { id: ",[250,1197,1198],{"class":778},"1",[250,1200,1201],{"class":912},", name: ",[250,1203,1204],{"class":782},"\"Latte\"",[250,1206,1207],{"class":912},", price: ",[250,1209,1210],{"class":778},"4.5",[250,1212,1213],{"class":912},", category: ",[250,1215,1216],{"class":782},"\"coffee\"",[250,1218,1219],{"class":912}," },\n",[250,1221,1222,1224,1227,1229,1232,1234,1237,1239,1241],{"class":252,"line":110},[250,1223,1195],{"class":912},[250,1225,1226],{"class":778},"2",[250,1228,1201],{"class":912},[250,1230,1231],{"class":782},"\"Espresso\"",[250,1233,1207],{"class":912},[250,1235,1236],{"class":778},"3.0",[250,1238,1213],{"class":912},[250,1240,1216],{"class":782},[250,1242,1219],{"class":912},[250,1244,1245,1247,1250,1252,1255,1257,1260,1262,1265],{"class":252,"line":269},[250,1246,1195],{"class":912},[250,1248,1249],{"class":778},"3",[250,1251,1201],{"class":912},[250,1253,1254],{"class":782},"\"Croissant\"",[250,1256,1207],{"class":912},[250,1258,1259],{"class":778},"3.5",[250,1261,1213],{"class":912},[250,1263,1264],{"class":782},"\"food\"",[250,1266,1219],{"class":912},[250,1268,1269,1271,1274,1276,1279,1281,1284,1286,1289],{"class":252,"line":275},[250,1270,1195],{"class":912},[250,1272,1273],{"class":778},"4",[250,1275,1201],{"class":912},[250,1277,1278],{"class":782},"\"Chai Tea\"",[250,1280,1207],{"class":912},[250,1282,1283],{"class":778},"4.0",[250,1285,1213],{"class":912},[250,1287,1288],{"class":782},"\"tea\"",[250,1290,1219],{"class":912},[250,1292,1293,1295,1298,1300,1303,1305,1307,1309,1311],{"class":252,"line":281},[250,1294,1195],{"class":912},[250,1296,1297],{"class":778},"5",[250,1299,1201],{"class":912},[250,1301,1302],{"class":782},"\"Muffin\"",[250,1304,1207],{"class":912},[250,1306,1236],{"class":778},[250,1308,1213],{"class":912},[250,1310,1264],{"class":782},[250,1312,1219],{"class":912},[250,1314,1315],{"class":252,"line":287},[250,1316,1317],{"class":912},"];\n",[250,1319,1320],{"class":252,"line":293},[250,1321,795],{"emptyLinePlaceholder":129},[250,1323,1324,1326,1328,1330,1332,1334],{"class":252,"line":299},[250,1325,1019],{"class":786},[250,1327,1022],{"class":786},[250,1329,1109],{"class":774},[250,1331,1112],{"class":912},[250,1333,1115],{"class":786},[250,1335,1118],{"class":912},[250,1337,1338,1340],{"class":252,"line":132},[250,1339,1123],{"class":786},[250,1341,1342],{"class":912}," { products };\n",[250,1344,1345],{"class":252,"line":310},[250,1346,1077],{"class":912},[20,1348,1349],{},"Create a more complex endpoint with database simulation:",[47,1351,1354],{"className":1010,"code":1352,"filename":1353,"language":1012,"meta":55,"style":55},"interface OrderItem {\n  productId: number;\n  quantity: number;\n}\n\nconst orders: any[] = [];\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event) as OrderItem[];\n  \n  if (!body || body.length === 0) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Order must contain at least one item\",\n    });\n  }\n  \n  \u002F\u002F Simulate database delay\n  await new Promise((resolve) => setTimeout(resolve, 100));\n  \n  const order = {\n    id: crypto.randomUUID(),\n    items: body,\n    status: \"pending\",\n    createdAt: new Date().toISOString(),\n  };\n  \n  orders.push(order);\n  \n  return order;\n});\n","server\u002Fapi\u002Forders.post.ts",[39,1355,1356,1366,1380,1391,1395,1399,1420,1424,1451,1478,1482,1513,1523,1533,1543,1548,1552,1556,1561,1594,1598,1609,1619,1624,1634,1653,1657,1661,1672,1676,1683],{"__ignoreMap":55},[250,1357,1358,1361,1364],{"class":252,"line":253},[250,1359,1360],{"class":786},"interface",[250,1362,1363],{"class":774}," OrderItem",[250,1365,1118],{"class":912},[250,1367,1368,1372,1374,1377],{"class":252,"line":113},[250,1369,1371],{"class":1370},"s4XuR","  productId",[250,1373,1007],{"class":786},[250,1375,1376],{"class":778}," number",[250,1378,1379],{"class":912},";\n",[250,1381,1382,1385,1387,1389],{"class":252,"line":110},[250,1383,1384],{"class":1370},"  quantity",[250,1386,1007],{"class":786},[250,1388,1376],{"class":778},[250,1390,1379],{"class":912},[250,1392,1393],{"class":252,"line":269},[250,1394,991],{"class":912},[250,1396,1397],{"class":252,"line":275},[250,1398,795],{"emptyLinePlaceholder":129},[250,1400,1401,1403,1406,1408,1411,1414,1417],{"class":252,"line":281},[250,1402,1181],{"class":786},[250,1404,1405],{"class":778}," orders",[250,1407,1007],{"class":786},[250,1409,1410],{"class":778}," any",[250,1412,1413],{"class":912},"[] ",[250,1415,1416],{"class":786},"=",[250,1418,1419],{"class":912}," [];\n",[250,1421,1422],{"class":252,"line":287},[250,1423,795],{"emptyLinePlaceholder":129},[250,1425,1426,1428,1430,1432,1435,1438,1441,1444,1447,1449],{"class":252,"line":293},[250,1427,1019],{"class":786},[250,1429,1022],{"class":786},[250,1431,1109],{"class":774},[250,1433,1434],{"class":912},"(",[250,1436,1437],{"class":786},"async",[250,1439,1440],{"class":912}," (",[250,1442,1443],{"class":1370},"event",[250,1445,1446],{"class":912},") ",[250,1448,1115],{"class":786},[250,1450,1118],{"class":912},[250,1452,1453,1456,1459,1461,1464,1467,1470,1473,1475],{"class":252,"line":299},[250,1454,1455],{"class":786},"  const",[250,1457,1458],{"class":778}," body",[250,1460,1187],{"class":786},[250,1462,1463],{"class":786}," await",[250,1465,1466],{"class":774}," readBody",[250,1468,1469],{"class":912},"(event) ",[250,1471,1472],{"class":786},"as",[250,1474,1363],{"class":774},[250,1476,1477],{"class":912},"[];\n",[250,1479,1480],{"class":252,"line":132},[250,1481,1053],{"class":912},[250,1483,1484,1487,1489,1492,1495,1498,1501,1504,1507,1510],{"class":252,"line":310},[250,1485,1486],{"class":786},"  if",[250,1488,1440],{"class":912},[250,1490,1491],{"class":786},"!",[250,1493,1494],{"class":912},"body ",[250,1496,1497],{"class":786},"||",[250,1499,1500],{"class":912}," body.",[250,1502,1503],{"class":778},"length",[250,1505,1506],{"class":786}," ===",[250,1508,1509],{"class":778}," 0",[250,1511,1512],{"class":912},") {\n",[250,1514,1515,1518,1521],{"class":252,"line":316},[250,1516,1517],{"class":786},"    throw",[250,1519,1520],{"class":774}," createError",[250,1522,1028],{"class":912},[250,1524,1525,1528,1531],{"class":252,"line":322},[250,1526,1527],{"class":912},"      statusCode: ",[250,1529,1530],{"class":778},"400",[250,1532,927],{"class":912},[250,1534,1535,1538,1541],{"class":252,"line":328},[250,1536,1537],{"class":912},"      statusMessage: ",[250,1539,1540],{"class":782},"\"Order must contain at least one item\"",[250,1542,927],{"class":912},[250,1544,1545],{"class":252,"line":334},[250,1546,1547],{"class":912},"    });\n",[250,1549,1550],{"class":252,"line":340},[250,1551,986],{"class":912},[250,1553,1554],{"class":252,"line":346},[250,1555,1053],{"class":912},[250,1557,1558],{"class":252,"line":352},[250,1559,1560],{"class":768},"  \u002F\u002F Simulate database delay\n",[250,1562,1563,1566,1569,1572,1575,1578,1580,1582,1585,1588,1591],{"class":252,"line":358},[250,1564,1565],{"class":786},"  await",[250,1567,1568],{"class":786}," new",[250,1570,1571],{"class":778}," Promise",[250,1573,1574],{"class":912},"((",[250,1576,1577],{"class":1370},"resolve",[250,1579,1446],{"class":912},[250,1581,1115],{"class":786},[250,1583,1584],{"class":774}," setTimeout",[250,1586,1587],{"class":912},"(resolve, ",[250,1589,1590],{"class":778},"100",[250,1592,1593],{"class":912},"));\n",[250,1595,1596],{"class":252,"line":364},[250,1597,1053],{"class":912},[250,1599,1600,1602,1605,1607],{"class":252,"line":370},[250,1601,1455],{"class":786},[250,1603,1604],{"class":778}," order",[250,1606,1187],{"class":786},[250,1608,1118],{"class":912},[250,1610,1611,1614,1617],{"class":252,"line":376},[250,1612,1613],{"class":912},"    id: crypto.",[250,1615,1616],{"class":774},"randomUUID",[250,1618,1156],{"class":912},[250,1620,1621],{"class":252,"line":382},[250,1622,1623],{"class":912},"    items: body,\n",[250,1625,1626,1629,1632],{"class":252,"line":388},[250,1627,1628],{"class":912},"    status: ",[250,1630,1631],{"class":782},"\"pending\"",[250,1633,927],{"class":912},[250,1635,1636,1639,1642,1645,1648,1651],{"class":252,"line":393},[250,1637,1638],{"class":912},"    createdAt: ",[250,1640,1641],{"class":786},"new",[250,1643,1644],{"class":774}," Date",[250,1646,1647],{"class":912},"().",[250,1649,1650],{"class":774},"toISOString",[250,1652,1156],{"class":912},[250,1654,1655],{"class":252,"line":399},[250,1656,1161],{"class":912},[250,1658,1659],{"class":252,"line":405},[250,1660,1053],{"class":912},[250,1662,1663,1666,1669],{"class":252,"line":410},[250,1664,1665],{"class":912},"  orders.",[250,1667,1668],{"class":774},"push",[250,1670,1671],{"class":912},"(order);\n",[250,1673,1674],{"class":252,"line":415},[250,1675,1053],{"class":912},[250,1677,1678,1680],{"class":252,"line":420},[250,1679,1123],{"class":786},[250,1681,1682],{"class":912}," order;\n",[250,1684,1685],{"class":252,"line":426},[250,1686,1077],{"class":912},[72,1688],{},[31,1690,1692],{"id":1691},"step-5-run-the-server","Step 5: Run the Server",[20,1694,1695],{},"Start the development server:",[47,1697,1699],{"className":758,"code":1698,"filename":760,"language":761,"meta":55,"style":55},"bun run dev\n",[39,1700,1701],{"__ignoreMap":55},[250,1702,1703,1705,1708],{"class":252,"line":253},[250,1704,824],{"class":774},[250,1706,1707],{"class":782}," run",[250,1709,1710],{"class":782}," dev\n",[161,1712,1715],{"icon":1713,"title":1714},"⚡","Notice the Speed",[20,1716,1717],{},"Bun's dev server starts in milliseconds—often before you can release the keys after typing the command.",[20,1719,1720],{},"Test the endpoints:",[47,1722,1724],{"className":758,"code":1723,"filename":760,"language":761,"meta":55,"style":55},"curl http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fping\ncurl http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fproducts\n",[39,1725,1726,1733],{"__ignoreMap":55},[250,1727,1728,1730],{"class":252,"line":253},[250,1729,775],{"class":774},[250,1731,1732],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fping\n",[250,1734,1735,1737],{"class":252,"line":113},[250,1736,775],{"class":774},[250,1738,1739],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fproducts\n",[72,1741],{},[31,1743,1745],{"id":1744},"step-6-benchmarking","Step 6: Benchmarking",[20,1747,1748],{},"Let's create a simple benchmark script to compare Bun vs Node.js performance.",[20,1750,1092,1751,1007],{},[39,1752,1753],{},"benchmark.mjs",[47,1755,1757],{"className":1010,"code":1756,"filename":1753,"language":1012,"meta":55,"style":55},"import http from \"http\";\n\nconst HOST = \"localhost\";\nconst PORT = 3000;\nconst REQUESTS = 10000;\nconst CONCURRENCY = 100;\n\nasync function benchmark() {\n  console.log(`Running benchmark: ${REQUESTS} requests with ${CONCURRENCY} concurrency\\n`);\n  \n  const start = Date.now();\n  let completed = 0;\n  \n  const promises = [];\n  \n  for (let i = 0; i \u003C CONCURRENCY; i++) {\n    promises.push(\n      new Promise((resolve) => {\n        const makeRequest = async () => {\n          if (completed >= REQUESTS) {\n            resolve(true);\n            return;\n          }\n          \n          try {\n            await fetch(`http:\u002F\u002F${HOST}:${PORT}\u002Fapi\u002Fproducts`);\n            completed++;\n            \n            if (completed \u003C REQUESTS) {\n              makeRequest();\n            } else {\n              resolve(true);\n            }\n          } catch (e) {\n            resolve(true);\n          }\n        };\n        \n        makeRequest();\n      })\n    );\n  }\n  \n  await Promise.all(promises);\n  \n  const duration = Date.now() - start;\n  const rps = Math.round(REQUESTS \u002F (duration \u002F 1000));\n  \n  console.log(`Results:`);\n  console.log(`  Total time: ${duration}ms`);\n  console.log(`  Requests\u002Fsec: ${rps}`);\n  console.log(`  Avg latency: ${(duration \u002F REQUESTS).toFixed(2)}ms`);\n}\n\nbenchmark();\n",[39,1758,1759,1775,1779,1793,1807,1821,1835,1839,1852,1886,1890,1907,1921,1925,1936,1940,1973,1983,2000,2020,2035,2046,2053,2058,2063,2070,2097,2106,2111,2124,2131,2141,2152,2157,2168,2178,2182,2187,2192,2199,2205,2211,2216,2221,2237,2242,2265,2299,2304,2318,2338,2358,2395,2400,2405],{"__ignoreMap":55},[250,1760,1761,1764,1767,1770,1773],{"class":252,"line":253},[250,1762,1763],{"class":786},"import",[250,1765,1766],{"class":912}," http ",[250,1768,1769],{"class":786},"from",[250,1771,1772],{"class":782}," \"http\"",[250,1774,1379],{"class":912},[250,1776,1777],{"class":252,"line":113},[250,1778,795],{"emptyLinePlaceholder":129},[250,1780,1781,1783,1786,1788,1791],{"class":252,"line":110},[250,1782,1181],{"class":786},[250,1784,1785],{"class":778}," HOST",[250,1787,1187],{"class":786},[250,1789,1790],{"class":782}," \"localhost\"",[250,1792,1379],{"class":912},[250,1794,1795,1797,1800,1802,1805],{"class":252,"line":269},[250,1796,1181],{"class":786},[250,1798,1799],{"class":778}," PORT",[250,1801,1187],{"class":786},[250,1803,1804],{"class":778}," 3000",[250,1806,1379],{"class":912},[250,1808,1809,1811,1814,1816,1819],{"class":252,"line":275},[250,1810,1181],{"class":786},[250,1812,1813],{"class":778}," REQUESTS",[250,1815,1187],{"class":786},[250,1817,1818],{"class":778}," 10000",[250,1820,1379],{"class":912},[250,1822,1823,1825,1828,1830,1833],{"class":252,"line":281},[250,1824,1181],{"class":786},[250,1826,1827],{"class":778}," CONCURRENCY",[250,1829,1187],{"class":786},[250,1831,1832],{"class":778}," 100",[250,1834,1379],{"class":912},[250,1836,1837],{"class":252,"line":287},[250,1838,795],{"emptyLinePlaceholder":129},[250,1840,1841,1843,1846,1849],{"class":252,"line":293},[250,1842,1437],{"class":786},[250,1844,1845],{"class":786}," function",[250,1847,1848],{"class":774}," benchmark",[250,1850,1851],{"class":912},"() {\n",[250,1853,1854,1857,1860,1862,1865,1868,1871,1874,1877,1880,1883],{"class":252,"line":299},[250,1855,1856],{"class":912},"  console.",[250,1858,1859],{"class":774},"log",[250,1861,1434],{"class":912},[250,1863,1864],{"class":782},"`Running benchmark: ${",[250,1866,1867],{"class":778},"REQUESTS",[250,1869,1870],{"class":782},"} requests with ${",[250,1872,1873],{"class":778},"CONCURRENCY",[250,1875,1876],{"class":782},"} concurrency",[250,1878,1879],{"class":778},"\\n",[250,1881,1882],{"class":782},"`",[250,1884,1885],{"class":912},");\n",[250,1887,1888],{"class":252,"line":132},[250,1889,1053],{"class":912},[250,1891,1892,1894,1897,1899,1902,1904],{"class":252,"line":310},[250,1893,1455],{"class":786},[250,1895,1896],{"class":778}," start",[250,1898,1187],{"class":786},[250,1900,1901],{"class":912}," Date.",[250,1903,1153],{"class":774},[250,1905,1906],{"class":912},"();\n",[250,1908,1909,1912,1915,1917,1919],{"class":252,"line":316},[250,1910,1911],{"class":786},"  let",[250,1913,1914],{"class":912}," completed ",[250,1916,1416],{"class":786},[250,1918,1509],{"class":778},[250,1920,1379],{"class":912},[250,1922,1923],{"class":252,"line":322},[250,1924,1053],{"class":912},[250,1926,1927,1929,1932,1934],{"class":252,"line":328},[250,1928,1455],{"class":786},[250,1930,1931],{"class":778}," promises",[250,1933,1187],{"class":786},[250,1935,1419],{"class":912},[250,1937,1938],{"class":252,"line":334},[250,1939,1053],{"class":912},[250,1941,1942,1945,1947,1950,1953,1955,1957,1960,1963,1965,1968,1971],{"class":252,"line":340},[250,1943,1944],{"class":786},"  for",[250,1946,1440],{"class":912},[250,1948,1949],{"class":786},"let",[250,1951,1952],{"class":912}," i ",[250,1954,1416],{"class":786},[250,1956,1509],{"class":778},[250,1958,1959],{"class":912},"; i ",[250,1961,1962],{"class":786},"\u003C",[250,1964,1827],{"class":778},[250,1966,1967],{"class":912},"; i",[250,1969,1970],{"class":786},"++",[250,1972,1512],{"class":912},[250,1974,1975,1978,1980],{"class":252,"line":346},[250,1976,1977],{"class":912},"    promises.",[250,1979,1668],{"class":774},[250,1981,1982],{"class":912},"(\n",[250,1984,1985,1988,1990,1992,1994,1996,1998],{"class":252,"line":352},[250,1986,1987],{"class":786},"      new",[250,1989,1571],{"class":778},[250,1991,1574],{"class":912},[250,1993,1577],{"class":1370},[250,1995,1446],{"class":912},[250,1997,1115],{"class":786},[250,1999,1118],{"class":912},[250,2001,2002,2005,2008,2010,2013,2016,2018],{"class":252,"line":358},[250,2003,2004],{"class":786},"        const",[250,2006,2007],{"class":774}," makeRequest",[250,2009,1187],{"class":786},[250,2011,2012],{"class":786}," async",[250,2014,2015],{"class":912}," () ",[250,2017,1115],{"class":786},[250,2019,1118],{"class":912},[250,2021,2022,2025,2028,2031,2033],{"class":252,"line":364},[250,2023,2024],{"class":786},"          if",[250,2026,2027],{"class":912}," (completed ",[250,2029,2030],{"class":786},">=",[250,2032,1813],{"class":778},[250,2034,1512],{"class":912},[250,2036,2037,2040,2042,2044],{"class":252,"line":370},[250,2038,2039],{"class":774},"            resolve",[250,2041,1434],{"class":912},[250,2043,1066],{"class":778},[250,2045,1885],{"class":912},[250,2047,2048,2051],{"class":252,"line":376},[250,2049,2050],{"class":786},"            return",[250,2052,1379],{"class":912},[250,2054,2055],{"class":252,"line":382},[250,2056,2057],{"class":912},"          }\n",[250,2059,2060],{"class":252,"line":388},[250,2061,2062],{"class":912},"          \n",[250,2064,2065,2068],{"class":252,"line":393},[250,2066,2067],{"class":786},"          try",[250,2069,1118],{"class":912},[250,2071,2072,2075,2078,2080,2083,2086,2089,2092,2095],{"class":252,"line":399},[250,2073,2074],{"class":786},"            await",[250,2076,2077],{"class":774}," fetch",[250,2079,1434],{"class":912},[250,2081,2082],{"class":782},"`http:\u002F\u002F${",[250,2084,2085],{"class":778},"HOST",[250,2087,2088],{"class":782},"}:${",[250,2090,2091],{"class":778},"PORT",[250,2093,2094],{"class":782},"}\u002Fapi\u002Fproducts`",[250,2096,1885],{"class":912},[250,2098,2099,2102,2104],{"class":252,"line":405},[250,2100,2101],{"class":912},"            completed",[250,2103,1970],{"class":786},[250,2105,1379],{"class":912},[250,2107,2108],{"class":252,"line":410},[250,2109,2110],{"class":912},"            \n",[250,2112,2113,2116,2118,2120,2122],{"class":252,"line":415},[250,2114,2115],{"class":786},"            if",[250,2117,2027],{"class":912},[250,2119,1962],{"class":786},[250,2121,1813],{"class":778},[250,2123,1512],{"class":912},[250,2125,2126,2129],{"class":252,"line":420},[250,2127,2128],{"class":774},"              makeRequest",[250,2130,1906],{"class":912},[250,2132,2133,2136,2139],{"class":252,"line":426},[250,2134,2135],{"class":912},"            } ",[250,2137,2138],{"class":786},"else",[250,2140,1118],{"class":912},[250,2142,2143,2146,2148,2150],{"class":252,"line":431},[250,2144,2145],{"class":774},"              resolve",[250,2147,1434],{"class":912},[250,2149,1066],{"class":778},[250,2151,1885],{"class":912},[250,2153,2154],{"class":252,"line":436},[250,2155,2156],{"class":912},"            }\n",[250,2158,2159,2162,2165],{"class":252,"line":442},[250,2160,2161],{"class":912},"          } ",[250,2163,2164],{"class":786},"catch",[250,2166,2167],{"class":912}," (e) {\n",[250,2169,2170,2172,2174,2176],{"class":252,"line":447},[250,2171,2039],{"class":774},[250,2173,1434],{"class":912},[250,2175,1066],{"class":778},[250,2177,1885],{"class":912},[250,2179,2180],{"class":252,"line":453},[250,2181,2057],{"class":912},[250,2183,2184],{"class":252,"line":459},[250,2185,2186],{"class":912},"        };\n",[250,2188,2189],{"class":252,"line":465},[250,2190,2191],{"class":912},"        \n",[250,2193,2194,2197],{"class":252,"line":471},[250,2195,2196],{"class":774},"        makeRequest",[250,2198,1906],{"class":912},[250,2200,2202],{"class":252,"line":2201},40,[250,2203,2204],{"class":912},"      })\n",[250,2206,2208],{"class":252,"line":2207},41,[250,2209,2210],{"class":912},"    );\n",[250,2212,2214],{"class":252,"line":2213},42,[250,2215,986],{"class":912},[250,2217,2219],{"class":252,"line":2218},43,[250,2220,1053],{"class":912},[250,2222,2224,2226,2228,2231,2234],{"class":252,"line":2223},44,[250,2225,1565],{"class":786},[250,2227,1571],{"class":778},[250,2229,2230],{"class":912},".",[250,2232,2233],{"class":774},"all",[250,2235,2236],{"class":912},"(promises);\n",[250,2238,2240],{"class":252,"line":2239},45,[250,2241,1053],{"class":912},[250,2243,2245,2247,2250,2252,2254,2256,2259,2262],{"class":252,"line":2244},46,[250,2246,1455],{"class":786},[250,2248,2249],{"class":778}," duration",[250,2251,1187],{"class":786},[250,2253,1901],{"class":912},[250,2255,1153],{"class":774},[250,2257,2258],{"class":912},"() ",[250,2260,2261],{"class":786},"-",[250,2263,2264],{"class":912}," start;\n",[250,2266,2268,2270,2273,2275,2278,2281,2283,2285,2288,2291,2294,2297],{"class":252,"line":2267},47,[250,2269,1455],{"class":786},[250,2271,2272],{"class":778}," rps",[250,2274,1187],{"class":786},[250,2276,2277],{"class":912}," Math.",[250,2279,2280],{"class":774},"round",[250,2282,1434],{"class":912},[250,2284,1867],{"class":778},[250,2286,2287],{"class":786}," \u002F",[250,2289,2290],{"class":912}," (duration ",[250,2292,2293],{"class":786},"\u002F",[250,2295,2296],{"class":778}," 1000",[250,2298,1593],{"class":912},[250,2300,2302],{"class":252,"line":2301},48,[250,2303,1053],{"class":912},[250,2305,2307,2309,2311,2313,2316],{"class":252,"line":2306},49,[250,2308,1856],{"class":912},[250,2310,1859],{"class":774},[250,2312,1434],{"class":912},[250,2314,2315],{"class":782},"`Results:`",[250,2317,1885],{"class":912},[250,2319,2321,2323,2325,2327,2330,2333,2336],{"class":252,"line":2320},50,[250,2322,1856],{"class":912},[250,2324,1859],{"class":774},[250,2326,1434],{"class":912},[250,2328,2329],{"class":782},"`  Total time: ${",[250,2331,2332],{"class":912},"duration",[250,2334,2335],{"class":782},"}ms`",[250,2337,1885],{"class":912},[250,2339,2341,2343,2345,2347,2350,2353,2356],{"class":252,"line":2340},51,[250,2342,1856],{"class":912},[250,2344,1859],{"class":774},[250,2346,1434],{"class":912},[250,2348,2349],{"class":782},"`  Requests\u002Fsec: ${",[250,2351,2352],{"class":912},"rps",[250,2354,2355],{"class":782},"}`",[250,2357,1885],{"class":912},[250,2359,2361,2363,2365,2367,2370,2372,2374,2376,2378,2381,2384,2386,2388,2391,2393],{"class":252,"line":2360},52,[250,2362,1856],{"class":912},[250,2364,1859],{"class":774},[250,2366,1434],{"class":912},[250,2368,2369],{"class":782},"`  Avg latency: ${",[250,2371,1434],{"class":782},[250,2373,2332],{"class":912},[250,2375,2287],{"class":786},[250,2377,1813],{"class":778},[250,2379,2380],{"class":782},").",[250,2382,2383],{"class":774},"toFixed",[250,2385,1434],{"class":782},[250,2387,1226],{"class":778},[250,2389,2390],{"class":782},")",[250,2392,2335],{"class":782},[250,2394,1885],{"class":912},[250,2396,2398],{"class":252,"line":2397},53,[250,2399,991],{"class":912},[250,2401,2403],{"class":252,"line":2402},54,[250,2404,795],{"emptyLinePlaceholder":129},[250,2406,2408,2411],{"class":252,"line":2407},55,[250,2409,2410],{"class":774},"benchmark",[250,2412,1906],{"class":912},[20,2414,2415],{},"Run the benchmark:",[47,2417,2419],{"className":758,"code":2418,"filename":760,"language":761,"meta":55,"style":55},"# First, start the server in one terminal\nbun run dev\n\n# Then run the benchmark in another\nbun run benchmark.mjs\n",[39,2420,2421,2426,2434,2438,2443],{"__ignoreMap":55},[250,2422,2423],{"class":252,"line":253},[250,2424,2425],{"class":768},"# First, start the server in one terminal\n",[250,2427,2428,2430,2432],{"class":252,"line":113},[250,2429,824],{"class":774},[250,2431,1707],{"class":782},[250,2433,1710],{"class":782},[250,2435,2436],{"class":252,"line":110},[250,2437,795],{"emptyLinePlaceholder":129},[250,2439,2440],{"class":252,"line":269},[250,2441,2442],{"class":768},"# Then run the benchmark in another\n",[250,2444,2445,2447,2449],{"class":252,"line":275},[250,2446,824],{"class":774},[250,2448,1707],{"class":782},[250,2450,2451],{"class":782}," benchmark.mjs\n",[72,2453],{},[31,2455,2457],{"id":2456},"step-7-using-buns-native-features","Step 7: Using Bun's Native Features",[2459,2460,2462],"h3",{"id":2461},"typescript-direct-execution","TypeScript Direct Execution",[20,2464,2465],{},"Bun runs TypeScript natively—no ts-node, no compilation step needed:",[47,2467,2470],{"className":1010,"code":2468,"filename":2469,"language":1012,"meta":55,"style":55},"\u002F\u002F This runs directly in Bun—no transpilation!\ninterface Product {\n  id: number;\n  name: string;\n  price: number;\n}\n\nconst products: Product[] = [\n  { id: 1, name: \"Latte\", price: 4.5 },\n  { id: 2, name: \"Espresso\", price: 3.0 },\n];\n\nexport default defineEventHandler(() => {\n  return {\n    products,\n    runtime: Bun.version,\n    platform: Bun.environment.platform,\n  };\n});\n","server\u002Fapi\u002Fbun-features.get.ts",[39,2471,2472,2477,2486,2497,2509,2520,2524,2528,2544,2560,2576,2580,2584,2598,2604,2609,2614,2619,2623],{"__ignoreMap":55},[250,2473,2474],{"class":252,"line":253},[250,2475,2476],{"class":768},"\u002F\u002F This runs directly in Bun—no transpilation!\n",[250,2478,2479,2481,2484],{"class":252,"line":113},[250,2480,1360],{"class":786},[250,2482,2483],{"class":774}," Product",[250,2485,1118],{"class":912},[250,2487,2488,2491,2493,2495],{"class":252,"line":110},[250,2489,2490],{"class":1370},"  id",[250,2492,1007],{"class":786},[250,2494,1376],{"class":778},[250,2496,1379],{"class":912},[250,2498,2499,2502,2504,2507],{"class":252,"line":269},[250,2500,2501],{"class":1370},"  name",[250,2503,1007],{"class":786},[250,2505,2506],{"class":778}," string",[250,2508,1379],{"class":912},[250,2510,2511,2514,2516,2518],{"class":252,"line":275},[250,2512,2513],{"class":1370},"  price",[250,2515,1007],{"class":786},[250,2517,1376],{"class":778},[250,2519,1379],{"class":912},[250,2521,2522],{"class":252,"line":281},[250,2523,991],{"class":912},[250,2525,2526],{"class":252,"line":287},[250,2527,795],{"emptyLinePlaceholder":129},[250,2529,2530,2532,2534,2536,2538,2540,2542],{"class":252,"line":293},[250,2531,1181],{"class":786},[250,2533,1184],{"class":778},[250,2535,1007],{"class":786},[250,2537,2483],{"class":774},[250,2539,1413],{"class":912},[250,2541,1416],{"class":786},[250,2543,1190],{"class":912},[250,2545,2546,2548,2550,2552,2554,2556,2558],{"class":252,"line":299},[250,2547,1195],{"class":912},[250,2549,1198],{"class":778},[250,2551,1201],{"class":912},[250,2553,1204],{"class":782},[250,2555,1207],{"class":912},[250,2557,1210],{"class":778},[250,2559,1219],{"class":912},[250,2561,2562,2564,2566,2568,2570,2572,2574],{"class":252,"line":132},[250,2563,1195],{"class":912},[250,2565,1226],{"class":778},[250,2567,1201],{"class":912},[250,2569,1231],{"class":782},[250,2571,1207],{"class":912},[250,2573,1236],{"class":778},[250,2575,1219],{"class":912},[250,2577,2578],{"class":252,"line":310},[250,2579,1317],{"class":912},[250,2581,2582],{"class":252,"line":316},[250,2583,795],{"emptyLinePlaceholder":129},[250,2585,2586,2588,2590,2592,2594,2596],{"class":252,"line":322},[250,2587,1019],{"class":786},[250,2589,1022],{"class":786},[250,2591,1109],{"class":774},[250,2593,1112],{"class":912},[250,2595,1115],{"class":786},[250,2597,1118],{"class":912},[250,2599,2600,2602],{"class":252,"line":328},[250,2601,1123],{"class":786},[250,2603,1118],{"class":912},[250,2605,2606],{"class":252,"line":334},[250,2607,2608],{"class":912},"    products,\n",[250,2610,2611],{"class":252,"line":340},[250,2612,2613],{"class":912},"    runtime: Bun.version,\n",[250,2615,2616],{"class":252,"line":346},[250,2617,2618],{"class":912},"    platform: Bun.environment.platform,\n",[250,2620,2621],{"class":252,"line":352},[250,2622,1161],{"class":912},[250,2624,2625],{"class":252,"line":358},[250,2626,1077],{"class":912},[2459,2628,2630],{"id":2629},"using-bunfile-for-static-files","Using Bun.file for Static Files",[20,2632,2633],{},"Bun has built-in support for file operations:",[47,2635,2638],{"className":1010,"code":2636,"filename":2637,"language":1012,"meta":55,"style":55},"export default defineEventHandler(async (event) => {\n  const file = Bun.file(\".\u002Fserver\u002Fdata\u002Fproducts.json\");\n  const contents = await file.json();\n  \n  return contents;\n});\n","server\u002Fapi\u002Fread-file.get.ts",[39,2639,2640,2662,2684,2702,2706,2713],{"__ignoreMap":55},[250,2641,2642,2644,2646,2648,2650,2652,2654,2656,2658,2660],{"class":252,"line":253},[250,2643,1019],{"class":786},[250,2645,1022],{"class":786},[250,2647,1109],{"class":774},[250,2649,1434],{"class":912},[250,2651,1437],{"class":786},[250,2653,1440],{"class":912},[250,2655,1443],{"class":1370},[250,2657,1446],{"class":912},[250,2659,1115],{"class":786},[250,2661,1118],{"class":912},[250,2663,2664,2666,2669,2671,2674,2677,2679,2682],{"class":252,"line":113},[250,2665,1455],{"class":786},[250,2667,2668],{"class":778}," file",[250,2670,1187],{"class":786},[250,2672,2673],{"class":912}," Bun.",[250,2675,2676],{"class":774},"file",[250,2678,1434],{"class":912},[250,2680,2681],{"class":782},"\".\u002Fserver\u002Fdata\u002Fproducts.json\"",[250,2683,1885],{"class":912},[250,2685,2686,2688,2691,2693,2695,2698,2700],{"class":252,"line":110},[250,2687,1455],{"class":786},[250,2689,2690],{"class":778}," contents",[250,2692,1187],{"class":786},[250,2694,1463],{"class":786},[250,2696,2697],{"class":912}," file.",[250,2699,905],{"class":774},[250,2701,1906],{"class":912},[250,2703,2704],{"class":252,"line":269},[250,2705,1053],{"class":912},[250,2707,2708,2710],{"class":252,"line":275},[250,2709,1123],{"class":786},[250,2711,2712],{"class":912}," contents;\n",[250,2714,2715],{"class":252,"line":281},[250,2716,1077],{"class":912},[2459,2718,2720],{"id":2719},"parallel-data-fetching","Parallel Data Fetching",[20,2722,2723],{},"Bun's concurrent fetching is blazingly fast:",[47,2725,2728],{"className":1010,"code":2726,"filename":2727,"language":1012,"meta":55,"style":55},"export default defineEventHandler(async () => {\n  const urls = [\n    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Fokinea\",\n    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Ffacebook\",\n    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Fnuxt\",\n  ];\n  \n  \u002F\u002F Fetch all URLs in parallel - Bun optimizes this natively\n  const responses = await Promise.all(\n    urls.map((url) => fetch(url).then((r) => r.json()))\n  );\n  \n  return {\n    users: responses.map((r) => r.login),\n    fetchedAt: new Date().toISOString(),\n  };\n});\n","server\u002Fapi\u002Fexternal.get.ts",[39,2729,2730,2748,2759,2766,2773,2780,2785,2789,2794,2813,2855,2860,2864,2870,2888,2903,2907],{"__ignoreMap":55},[250,2731,2732,2734,2736,2738,2740,2742,2744,2746],{"class":252,"line":253},[250,2733,1019],{"class":786},[250,2735,1022],{"class":786},[250,2737,1109],{"class":774},[250,2739,1434],{"class":912},[250,2741,1437],{"class":786},[250,2743,2015],{"class":912},[250,2745,1115],{"class":786},[250,2747,1118],{"class":912},[250,2749,2750,2752,2755,2757],{"class":252,"line":113},[250,2751,1455],{"class":786},[250,2753,2754],{"class":778}," urls",[250,2756,1187],{"class":786},[250,2758,1190],{"class":912},[250,2760,2761,2764],{"class":252,"line":110},[250,2762,2763],{"class":782},"    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Fokinea\"",[250,2765,927],{"class":912},[250,2767,2768,2771],{"class":252,"line":269},[250,2769,2770],{"class":782},"    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Ffacebook\"",[250,2772,927],{"class":912},[250,2774,2775,2778],{"class":252,"line":275},[250,2776,2777],{"class":782},"    \"https:\u002F\u002Fapi.github.com\u002Fusers\u002Fnuxt\"",[250,2779,927],{"class":912},[250,2781,2782],{"class":252,"line":281},[250,2783,2784],{"class":912},"  ];\n",[250,2786,2787],{"class":252,"line":287},[250,2788,1053],{"class":912},[250,2790,2791],{"class":252,"line":293},[250,2792,2793],{"class":768},"  \u002F\u002F Fetch all URLs in parallel - Bun optimizes this natively\n",[250,2795,2796,2798,2801,2803,2805,2807,2809,2811],{"class":252,"line":299},[250,2797,1455],{"class":786},[250,2799,2800],{"class":778}," responses",[250,2802,1187],{"class":786},[250,2804,1463],{"class":786},[250,2806,1571],{"class":778},[250,2808,2230],{"class":912},[250,2810,2233],{"class":774},[250,2812,1982],{"class":912},[250,2814,2815,2818,2821,2823,2826,2828,2830,2832,2835,2838,2840,2843,2845,2847,2850,2852],{"class":252,"line":132},[250,2816,2817],{"class":912},"    urls.",[250,2819,2820],{"class":774},"map",[250,2822,1574],{"class":912},[250,2824,2825],{"class":1370},"url",[250,2827,1446],{"class":912},[250,2829,1115],{"class":786},[250,2831,2077],{"class":774},[250,2833,2834],{"class":912},"(url).",[250,2836,2837],{"class":774},"then",[250,2839,1574],{"class":912},[250,2841,2842],{"class":1370},"r",[250,2844,1446],{"class":912},[250,2846,1115],{"class":786},[250,2848,2849],{"class":912}," r.",[250,2851,905],{"class":774},[250,2853,2854],{"class":912},"()))\n",[250,2856,2857],{"class":252,"line":310},[250,2858,2859],{"class":912},"  );\n",[250,2861,2862],{"class":252,"line":316},[250,2863,1053],{"class":912},[250,2865,2866,2868],{"class":252,"line":322},[250,2867,1123],{"class":786},[250,2869,1118],{"class":912},[250,2871,2872,2875,2877,2879,2881,2883,2885],{"class":252,"line":328},[250,2873,2874],{"class":912},"    users: responses.",[250,2876,2820],{"class":774},[250,2878,1574],{"class":912},[250,2880,2842],{"class":1370},[250,2882,1446],{"class":912},[250,2884,1115],{"class":786},[250,2886,2887],{"class":912}," r.login),\n",[250,2889,2890,2893,2895,2897,2899,2901],{"class":252,"line":334},[250,2891,2892],{"class":912},"    fetchedAt: ",[250,2894,1641],{"class":786},[250,2896,1644],{"class":774},[250,2898,1647],{"class":912},[250,2900,1650],{"class":774},[250,2902,1156],{"class":912},[250,2904,2905],{"class":252,"line":340},[250,2906,1161],{"class":912},[250,2908,2909],{"class":252,"line":346},[250,2910,1077],{"class":912},[72,2912],{},[31,2914,2916],{"id":2915},"step-8-migration-guide","Step 8: Migration Guide",[2459,2918,2920],{"id":2919},"from-nodejs-to-bun","From Node.js to Bun",[2922,2923,2924,2948,3004],"ol",{},[564,2925,2926,2929,2944,2947],{},[546,2927,2928],{},"Test your dependencies",[47,2930,2932],{"className":758,"code":2931,"language":761,"meta":55,"style":55},"bun pm trust\n",[39,2933,2934],{"__ignoreMap":55},[250,2935,2936,2938,2941],{"class":252,"line":253},[250,2937,824],{"class":774},[250,2939,2940],{"class":782}," pm",[250,2942,2943],{"class":782}," trust\n",[2945,2946],"br",{},"This ensures all packages work with Bun's module resolution.",[564,2949,2950,2953],{},[546,2951,2952],{},"Update scripts",[47,2954,2956],{"className":902,"code":2955,"language":905,"meta":55,"style":55},"{\n  \"scripts\": {\n    \"dev\": \"bunx nuxi dev\",\n    \"build\": \"bunx nuxi build\",\n    \"start\": \"bunx nuxi start\"\n  }\n}\n",[39,2957,2958,2962,2968,2978,2988,2996,3000],{"__ignoreMap":55},[250,2959,2960],{"class":252,"line":253},[250,2961,913],{"class":912},[250,2963,2964,2966],{"class":252,"line":113},[250,2965,932],{"class":778},[250,2967,935],{"class":912},[250,2969,2970,2972,2974,2976],{"class":252,"line":110},[250,2971,940],{"class":778},[250,2973,921],{"class":912},[250,2975,945],{"class":782},[250,2977,927],{"class":912},[250,2979,2980,2982,2984,2986],{"class":252,"line":269},[250,2981,952],{"class":778},[250,2983,921],{"class":912},[250,2985,957],{"class":782},[250,2987,927],{"class":912},[250,2989,2990,2992,2994],{"class":252,"line":275},[250,2991,976],{"class":778},[250,2993,921],{"class":912},[250,2995,981],{"class":782},[250,2997,2998],{"class":252,"line":281},[250,2999,986],{"class":912},[250,3001,3002],{"class":252,"line":287},[250,3003,991],{"class":912},[564,3005,3006,3009],{},[546,3007,3008],{},"Check for Node.js-specific code",[47,3010,3012],{"className":758,"code":3011,"language":761,"meta":55,"style":55},"# Bun supports most Node.js APIs, but verify:\nbun --compat node_modules\n",[39,3013,3014,3019],{"__ignoreMap":55},[250,3015,3016],{"class":252,"line":253},[250,3017,3018],{"class":768},"# Bun supports most Node.js APIs, but verify:\n",[250,3020,3021,3023,3026],{"class":252,"line":113},[250,3022,824],{"class":774},[250,3024,3025],{"class":778}," --compat",[250,3027,3028],{"class":782}," node_modules\n",[2459,3030,3032],{"id":3031},"known-compatibility-issues","Known Compatibility Issues",[24,3034,3035,3049],{"type":26},[561,3036,3037,3043,3046],{},[564,3038,3039,3040],{},"Some native modules may require rebuilding: ",[39,3041,3042],{},"bun pm rebuild",[564,3044,3045],{},"Very old packages with C++ addons might not work",[564,3047,3048],{},"Edge cases in crypto API differ slightly",[20,3050,3051,3052,3056],{},"Most modern packages work perfectly—check ",[203,3053,3054],{"href":3054,"rel":3055},"https:\u002F\u002Fbun.sh\u002Fcompatibility",[207]," for updates.",[72,3058],{},[31,3060,3062],{"id":3061},"step-9-deployment","Step 9: Deployment",[2459,3064,3066],{"id":3065},"deploy-to-various-platforms","Deploy to Various Platforms",[3068,3069,3071],"h4",{"id":3070},"vercel","Vercel",[47,3073,3075],{"className":758,"code":3074,"filename":760,"language":761,"meta":55,"style":55},"# Vercel automatically detects Bun\nvercel deploy\n",[39,3076,3077,3082],{"__ignoreMap":55},[250,3078,3079],{"class":252,"line":253},[250,3080,3081],{"class":768},"# Vercel automatically detects Bun\n",[250,3083,3084,3086],{"class":252,"line":113},[250,3085,3070],{"class":774},[250,3087,3088],{"class":782}," deploy\n",[3068,3090,3092],{"id":3091},"railway","Railway",[47,3094,3097],{"className":902,"code":3095,"filename":3096,"language":905,"meta":55,"style":55},"{\n  \"build\": {\n    \"builder\": \"NIXPACKS_BUN\"\n  },\n  \"run\": {\n    \"command\": \"bun run start\"\n  }\n}\n","railway.json",[39,3098,3099,3103,3110,3120,3124,3131,3141,3145],{"__ignoreMap":55},[250,3100,3101],{"class":252,"line":253},[250,3102,913],{"class":912},[250,3104,3105,3108],{"class":252,"line":113},[250,3106,3107],{"class":778},"  \"build\"",[250,3109,935],{"class":912},[250,3111,3112,3115,3117],{"class":252,"line":110},[250,3113,3114],{"class":778},"    \"builder\"",[250,3116,921],{"class":912},[250,3118,3119],{"class":782},"\"NIXPACKS_BUN\"\n",[250,3121,3122],{"class":252,"line":269},[250,3123,1048],{"class":912},[250,3125,3126,3129],{"class":252,"line":275},[250,3127,3128],{"class":778},"  \"run\"",[250,3130,935],{"class":912},[250,3132,3133,3136,3138],{"class":252,"line":281},[250,3134,3135],{"class":778},"    \"command\"",[250,3137,921],{"class":912},[250,3139,3140],{"class":782},"\"bun run start\"\n",[250,3142,3143],{"class":252,"line":287},[250,3144,986],{"class":912},[250,3146,3147],{"class":252,"line":293},[250,3148,991],{"class":912},[3068,3150,3152],{"id":3151},"docker","Docker",[47,3154,3159],{"className":3155,"code":3156,"filename":3157,"language":3158,"meta":55,"style":55},"language-dockerfile shiki shiki-themes github-light github-dark","FROM oven\u002Fbun:1.2 AS base\nWORKDIR \u002Fapp\n\nCOPY package.json bun.lockb* .\u002F\nRUN bun install --frozen-lockfile\n\nCOPY . .\nRUN bun run build\n\nEXPOSE 3000\nCMD [\"bun\", \"run\", \"start\"]\n","Dockerfile","dockerfile",[39,3160,3161,3166,3171,3175,3180,3185,3189,3194,3199,3203,3208],{"__ignoreMap":55},[250,3162,3163],{"class":252,"line":253},[250,3164,3165],{},"FROM oven\u002Fbun:1.2 AS base\n",[250,3167,3168],{"class":252,"line":113},[250,3169,3170],{},"WORKDIR \u002Fapp\n",[250,3172,3173],{"class":252,"line":110},[250,3174,795],{"emptyLinePlaceholder":129},[250,3176,3177],{"class":252,"line":269},[250,3178,3179],{},"COPY package.json bun.lockb* .\u002F\n",[250,3181,3182],{"class":252,"line":275},[250,3183,3184],{},"RUN bun install --frozen-lockfile\n",[250,3186,3187],{"class":252,"line":281},[250,3188,795],{"emptyLinePlaceholder":129},[250,3190,3191],{"class":252,"line":287},[250,3192,3193],{},"COPY . .\n",[250,3195,3196],{"class":252,"line":293},[250,3197,3198],{},"RUN bun run build\n",[250,3200,3201],{"class":252,"line":299},[250,3202,795],{"emptyLinePlaceholder":129},[250,3204,3205],{"class":252,"line":132},[250,3206,3207],{},"EXPOSE 3000\n",[250,3209,3210],{"class":252,"line":310},[250,3211,3212],{},"CMD [\"bun\", \"run\", \"start\"]\n",[3068,3214,3216],{"id":3215},"buns-native-server","Bun's Native Server",[20,3218,3219],{},"Bun can serve directly:",[47,3221,3223],{"className":758,"code":3222,"filename":760,"language":761,"meta":55,"style":55},"bunx nuxi build\nbun run .output\u002Fserver\u002Findex.mjs\n",[39,3224,3225,3235],{"__ignoreMap":55},[250,3226,3227,3229,3232],{"class":252,"line":253},[250,3228,856],{"class":774},[250,3230,3231],{"class":782}," nuxi",[250,3233,3234],{"class":782}," build\n",[250,3236,3237,3239,3241],{"class":252,"line":113},[250,3238,824],{"class":774},[250,3240,1707],{"class":782},[250,3242,3243],{"class":782}," .output\u002Fserver\u002Findex.mjs\n",[161,3245,3248],{"icon":3246,"title":3247},"🚀","Production Ready",[20,3249,3250],{},"Bun is production-ready as of v1.2. Major companies are using it in production today. However, always test your specific dependency stack before deploying.",[72,3252],{},[31,3254,3256],{"id":3255},"what-weve-built","What We've Built",[20,3258,3259],{},"By the end of this guide, you have:",[561,3261,3262,3265,3268,3271,3274],{},[564,3263,3264],{},"A fully configured Bun + Nitro development environment",[564,3266,3267],{},"Fast API endpoints running on Bun",[564,3269,3270],{},"Performance benchmarks comparing to Node.js",[564,3272,3273],{},"Migration guidance from Node.js",[564,3275,3276],{},"Deployment configurations for multiple platforms",[2459,3278,3280],{"id":3279},"api-endpoints-summary","API Endpoints Summary",[645,3282,3283,3293],{},[648,3284,3285],{},[651,3286,3287,3290],{},[654,3288,3289],{},"Endpoint",[654,3291,3292],{},"Description",[666,3294,3295,3306,3316,3326,3336],{},[651,3296,3297,3303],{},[671,3298,3299,3300],{},"GET ",[39,3301,3302],{},"\u002Fapi\u002Fping",[671,3304,3305],{},"Health check with Bun info",[651,3307,3308,3313],{},[671,3309,3299,3310],{},[39,3311,3312],{},"\u002Fapi\u002Fproducts",[671,3314,3315],{},"Product list",[651,3317,3318,3323],{},[671,3319,3299,3320],{},[39,3321,3322],{},"\u002Fapi\u002Fbun-features",[671,3324,3325],{},"Bun-specific features demo",[651,3327,3328,3333],{},[671,3329,3299,3330],{},[39,3331,3332],{},"\u002Fapi\u002Fexternal",[671,3334,3335],{},"Parallel external API calls",[651,3337,3338,3344],{},[671,3339,3340,3341],{},"POST ",[39,3342,3343],{},"\u002Fapi\u002Forders",[671,3345,3346],{},"Order creation",[72,3348],{},[15,3350,3352],{"id":3351},"conclusion","Conclusion",[20,3354,3355,3358],{},[546,3356,3357],{},"Bun + Nitro"," represents the future of JavaScript server development. The combination of Bun's incredible performance and Nitro's deployment flexibility creates a stack that's hard to beat:",[561,3360,3361,3367,3372,3378,3384],{},[564,3362,3363,3366],{},[546,3364,3365],{},"Blazing fast startup"," — 5-6x faster than Node.js",[564,3368,3369,3371],{},[546,3370,603],{}," — No compilation step",[564,3373,3374,3377],{},[546,3375,3376],{},"Native Bun APIs"," — file, fetch, WebSocket built-in",[564,3379,3380,3383],{},[546,3381,3382],{},"Universal deployment"," — Node, serverless, edge",[564,3385,3386,3389],{},[546,3387,3388],{},"Same developer experience"," — Nuxt just works",[20,3391,3392],{},"The learning curve is minimal—if you know Nuxt and Node.js, you're already 95% of the way there. The remaining 5% is enjoying the speed.",[2459,3394,3396],{"id":3395},"when-to-use-bun","When to Use Bun",[561,3398,3399,3402,3405,3408,3411],{},[564,3400,3401],{},"✅ New projects where performance matters",[564,3403,3404],{},"✅ Serverless functions (cold start is critical)",[564,3406,3407],{},"✅ Rapid prototyping",[564,3409,3410],{},"✅ TypeScript-first projects",[564,3412,3413],{},"⚠️ Projects with many native C++ modules (test first)",[2459,3415,3417],{"id":3416},"when-to-stick-with-nodejs","When to Stick with Node.js",[561,3419,3420,3423,3426],{},[564,3421,3422],{},"✅ Enterprise projects with strict stability requirements",[564,3424,3425],{},"✅ Heavy reliance on legacy packages",[564,3427,3428],{},"✅ Teams less familiar with Bun's nuances",[20,3430,3431],{},"Start small—try Bun on your next side project or a single microservice. Once you experience the speed, you'll never want to go back. ☕⚡",[20,3433,3434],{},"Ready to build faster? Install Bun and try it today!",[500,3436,3437],{},"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 .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":110,"depth":110,"links":3439},[3440,3441,3442,3443,3444,3445,3446,3447,3448,3453,3457,3465],{"id":595,"depth":113,"text":596},{"id":639,"depth":113,"text":640},{"id":751,"depth":113,"text":752},{"id":837,"depth":113,"text":838},{"id":996,"depth":113,"text":997},{"id":1085,"depth":113,"text":1086},{"id":1691,"depth":113,"text":1692},{"id":1744,"depth":113,"text":1745},{"id":2456,"depth":113,"text":2457,"children":3449},[3450,3451,3452],{"id":2461,"depth":110,"text":2462},{"id":2629,"depth":110,"text":2630},{"id":2719,"depth":110,"text":2720},{"id":2915,"depth":113,"text":2916,"children":3454},[3455,3456],{"id":2919,"depth":110,"text":2920},{"id":3031,"depth":110,"text":3032},{"id":3061,"depth":113,"text":3062,"children":3458},[3459],{"id":3065,"depth":110,"text":3066,"children":3460},[3461,3462,3463,3464],{"id":3070,"depth":269,"text":3071},{"id":3091,"depth":269,"text":3092},{"id":3151,"depth":269,"text":3152},{"id":3215,"depth":269,"text":3216},{"id":3255,"depth":113,"text":3256,"children":3466},[3467,3468,3469],{"id":3279,"depth":110,"text":3280},{"id":3395,"depth":110,"text":3396},{"id":3416,"depth":110,"text":3417},"2026-03-03","Discover why Bun is the runtime to watch in 2026 and learn how to build blazing-fast APIs with Bun and Nitro. From setup to deployment, this guide covers everything.",{"type":12,"value":3473},[3474,3476,3480,3484,3486,3498],[15,3475,541],{"id":540},[20,3477,544,3478,549],{},[546,3479,548],{},[20,3481,552,3482,556],{},[546,3483,555],{},[20,3485,559],{},[561,3487,3488,3490,3492,3494,3496],{},[564,3489,566],{},[564,3491,569],{},[564,3493,572],{},[564,3495,575],{},[564,3497,578],{},[20,3499,581,3500,585],{},[546,3501,584],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555949963-aa79dcee981c",[824,3504,3505,3506,3507,3508,3509],"nitro","runtime","performance","server","api","javascript","TypeScript",{},"\u002Fblog\u002Fbun-nitro-stack",{"title":533,"description":3471},"blog\u002Fbun-nitro-stack","Technology","5kj35lJsZOU5TvCgxnX5a86Jjh5mib6hwBB2mj_87E8",{"id":3518,"title":3519,"author":3520,"body":3521,"canonical":115,"categories":115,"date":4050,"description":4051,"excerpt":4052,"extension":118,"img":4068,"keywords":4069,"language":3510,"meta":4074,"navigation":129,"ogImage":115,"path":4075,"rating":275,"readTime":132,"seo":4076,"stem":4077,"tag":3515,"__hash__":4078},"blog\u002Fblog\u002Fdioxus.md","Getting Started with Dioxus 0.7: A Cross-Platform Rust UI Framework",{"name":8,"img":10,"website":535},{"type":12,"value":3522,"toc":4029},[3523,3525,3544,3547,3549,3553,3571,3583,3591,3593,3597,3600,3631,3639,3641,3645,3654,3658,3689,3699,3705,3707,3711,3722,3731,3734,3736,3740,3747,3751,3777,3780,3782,3786,3801,3805,3884,3894,3896,3900,3911,3915,3944,3950,3952,3956,3967,3971,3982,3989,3991,3995,4006,4013,4015,4017,4020,4027],[15,3524,541],{"id":540},[20,3526,3527,3530,3531,3534,3535,3538,3539],{},[546,3528,3529],{},"Dioxus 0.7"," is the latest stable version of a powerful cross-platform UI framework built in ",[546,3532,3533],{},"Rust",". With Dioxus, developers can use a single Rust codebase to build applications that run on the ",[546,3536,3537],{},"web, desktop, and mobile platforms"," — all while leveraging Rust’s performance, strong type safety, and modern tooling. ",[3540,3541,3543],"content-reference",{"index":3542},"0","oaicite:0",[20,3545,3546],{},"In this post, we’ll explore what Dioxus is, how it works, and how you can start building your first app using its declarative UI syntax and cross-platform capabilities.",[15,3548,748],{"id":747},[31,3550,3552],{"id":3551},"what-is-dioxus","What Is Dioxus?",[20,3554,3555,3556,3559,3560,3563,3564,3567,3568],{},"At its core, ",[546,3557,3558],{},"Dioxus"," is a developer-focused UI framework designed to simplify building interactive applications while offering the performance and safety benefits of Rust. It’s similar in spirit to frameworks like ",[546,3561,3562],{},"Flutter"," or ",[546,3565,3566],{},"React Native",", but deeply rooted in the Rust ecosystem. ",[3540,3569,3570],{"index":1198},"oaicite:1",[24,3572,3573],{"type":631},[20,3574,3575,3576,3579,3580],{},"Dioxus lets you build UI with familiar ",[546,3577,3578],{},"HTML and CSS"," semantics using Rust, and compile to web (WASM), desktop, and mobile targets from a single codebase. ",[3540,3581,3582],{"index":1226},"oaicite:2",[20,3584,3585,3586,3590],{},"The framework’s syntax is inspired by modern declarative UI paradigms, meaning you describe ",[3587,3588,3589],"em",{},"what your UI should look like"," instead of how to construct elements imperatively.",[72,3592],{},[31,3594,3596],{"id":3595},"why-use-dioxus","Why Use Dioxus?",[20,3598,3599],{},"Developers gravitate toward Dioxus because it offers:",[561,3601,3602,3608,3613,3619,3625],{},[564,3603,3604,3607],{},[546,3605,3606],{},"Cross-platform support"," (web, desktop, mobile)",[564,3609,3610],{},[546,3611,3612],{},"Rust’s performance and safety guarantees",[564,3614,3615,3618],{},[546,3616,3617],{},"RSX",", a macro-based declarative UI syntax",[564,3620,3621,3624],{},[546,3622,3623],{},"Hot-reloading"," for faster developer feedback",[564,3626,3627,3628],{},"Integrated tools for building, bundling, and deploying apps ",[3540,3629,3630],{"index":1249},"oaicite:3",[24,3632,3633],{"type":26},[20,3634,3635,3636],{},"Learning Rust’s syntax and its borrow checker can have a steeper learning curve if you’re coming from JavaScript or TypeScript — but the payoff is safer, faster applications. ",[3540,3637,3638],{"index":1273},"oaicite:4",[72,3640],{},[31,3642,3644],{"id":3643},"core-concepts-rsx-and-components","Core Concepts: RSX and Components",[20,3646,3647,3648,3650,3651],{},"Dioxus uses ",[546,3649,3617],{}," — a Rust macro that resembles JSX (from React) — to describe UI in a declarative way. Instead of manually creating and updating DOM elements, you declare what your components should render. ",[3540,3652,3653],{"index":1297},"oaicite:5",[2459,3655,3657],{"id":3656},"rsx-example","RSX Example",[47,3659,3663],{"className":3660,"code":3661,"language":3662,"meta":55,"style":55},"language-rust shiki shiki-themes github-light github-dark","fn App() -> Element {\n    rsx! {\n        div { \"Hello, world!\" }\n    }\n}\n","rust",[39,3664,3665,3670,3675,3680,3685],{"__ignoreMap":55},[250,3666,3667],{"class":252,"line":253},[250,3668,3669],{},"fn App() -> Element {\n",[250,3671,3672],{"class":252,"line":113},[250,3673,3674],{},"    rsx! {\n",[250,3676,3677],{"class":252,"line":110},[250,3678,3679],{},"        div { \"Hello, world!\" }\n",[250,3681,3682],{"class":252,"line":269},[250,3683,3684],{},"    }\n",[250,3686,3687],{"class":252,"line":275},[250,3688,991],{},[20,3690,3691,3692,3698],{},"RSX syntax feels familiar to developers experienced with JSX or other declarative UI languages, but with the robustness of Rust’s compiler and type system powering it. (",[203,3693,3697],{"href":3694,"rel":3695,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Ftutorial\u002Frsx\u002F?utm_source=chatgpt.com",[207],"Dioxus | Fullstack crossplatform app framework for Rust","Dioxus Labs",")\n::",[20,3700,3701,3702,2390],{},"Hot-reloading is built in — when you save changes, your app updates instantly without a full rebuild. (",[203,3703,3697],{"href":3694,"rel":3704,"title":3696},[207],[72,3706],{},[31,3708,3710],{"id":3709},"state-management","State Management",[20,3712,3713,3714,3717,3718,2390],{},"Dioxus has a built-in reactivity model using ",[546,3715,3716],{},"signals",", allowing your UI to update when underlying data changes. Signals wrap ordinary Rust values and trigger component re-renders whenever they’re updated. (",[203,3719,3697],{"href":3720,"rel":3721,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Ftutorial\u002Fstate\u002F?utm_source=chatgpt.com",[207],[47,3723,3725],{"className":3660,"code":3724,"language":3662,"meta":55,"style":55},"let mut count = use_signal(|| 0);\n",[39,3726,3727],{"__ignoreMap":55},[250,3728,3729],{"class":252,"line":253},[250,3730,3724],{},[20,3732,3733],{},"This simple reactive primitive brings interactivity to your applications with minimal boilerplate.",[72,3735],{},[31,3737,3739],{"id":3738},"building-a-complete-app-the-hotdog-tutorial","Building a Complete App: The HotDog Tutorial",[20,3741,3742,3743,2390],{},"To help developers get started, Dioxus provides a comprehensive tutorial where you’ll build a small cross-platform app called “HotDog” — a playful dog photo app that lets users swipe and save images. (",[203,3744,3697],{"href":3745,"rel":3746,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Ftutorial\u002F?utm_source=chatgpt.com",[207],[2459,3748,3750],{"id":3749},"what-youll-learn","What You’ll Learn",[561,3752,3753,3756,3759,3762,3765,3768,3771],{},[564,3754,3755],{},"Tooling setup",[564,3757,3758],{},"Creating your first app project",[564,3760,3761],{},"Working with components",[564,3763,3764],{},"Adding state and interactivity",[564,3766,3767],{},"Fetching remote data",[564,3769,3770],{},"Routing and multi-page UI",[564,3772,3773,3774,2390],{},"Bundling and deployment (",[203,3775,3697],{"href":3745,"rel":3776,"title":3696},[207],[20,3778,3779],{},"This guided experience walks you from zero to a full app that runs across platforms, showing how Dioxus handles fullstack needs efficiently.",[72,3781],{},[31,3783,3785],{"id":3784},"fetching-data-and-resources","Fetching Data and Resources",[20,3787,3788,3789,3792,3793,3796,3797,2390],{},"Dioxus doesn’t have built-in data fetching utilities, so you’ll often leverage existing Rust crates like ",[39,3790,3791],{},"reqwest"," for HTTP client functionality and ",[39,3794,3795],{},"serde"," for JSON deserialization. (",[203,3798,3697],{"href":3799,"rel":3800,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Ftutorial\u002Fdata_fetching?utm_source=chatgpt.com",[207],[2459,3802,3804],{"id":3803},"example-fetching-and-displaying-a-random-dog-image","Example: Fetching and Displaying a Random Dog Image",[47,3806,3808],{"className":3660,"code":3807,"language":3662,"meta":55,"style":55},"#[component]\nfn DogView() -> Element {\n    let mut img_src = use_resource(|| async move {\n        reqwest::get(\"https:\u002F\u002Fdog.ceo\u002Fapi\u002Fbreeds\u002Fimage\u002Frandom\")\n            .await.unwrap()\n            .json::\u003CDogApi>()\n            .await.unwrap()\n            .message\n    });\n\n    rsx! {\n        div {\n            img { src: img_src.cloned().unwrap_or_default() }\n        }\n    }\n}\n",[39,3809,3810,3815,3820,3825,3830,3835,3840,3844,3849,3853,3857,3861,3866,3871,3876,3880],{"__ignoreMap":55},[250,3811,3812],{"class":252,"line":253},[250,3813,3814],{},"#[component]\n",[250,3816,3817],{"class":252,"line":113},[250,3818,3819],{},"fn DogView() -> Element {\n",[250,3821,3822],{"class":252,"line":110},[250,3823,3824],{},"    let mut img_src = use_resource(|| async move {\n",[250,3826,3827],{"class":252,"line":269},[250,3828,3829],{},"        reqwest::get(\"https:\u002F\u002Fdog.ceo\u002Fapi\u002Fbreeds\u002Fimage\u002Frandom\")\n",[250,3831,3832],{"class":252,"line":275},[250,3833,3834],{},"            .await.unwrap()\n",[250,3836,3837],{"class":252,"line":281},[250,3838,3839],{},"            .json::\u003CDogApi>()\n",[250,3841,3842],{"class":252,"line":287},[250,3843,3834],{},[250,3845,3846],{"class":252,"line":293},[250,3847,3848],{},"            .message\n",[250,3850,3851],{"class":252,"line":299},[250,3852,1547],{},[250,3854,3855],{"class":252,"line":132},[250,3856,795],{"emptyLinePlaceholder":129},[250,3858,3859],{"class":252,"line":310},[250,3860,3674],{},[250,3862,3863],{"class":252,"line":316},[250,3864,3865],{},"        div {\n",[250,3867,3868],{"class":252,"line":322},[250,3869,3870],{},"            img { src: img_src.cloned().unwrap_or_default() }\n",[250,3872,3873],{"class":252,"line":328},[250,3874,3875],{},"        }\n",[250,3877,3878],{"class":252,"line":334},[250,3879,3684],{},[250,3881,3882],{"class":252,"line":340},[250,3883,991],{},[20,3885,3886,3887,3890,3891,2390],{},"This pattern shows how Dioxus integrates asynchronous logic with its reactive system via ",[39,3888,3889],{},"use_resource",". (",[203,3892,3697],{"href":3799,"rel":3893,"title":3696},[207],[72,3895],{},[31,3897,3899],{"id":3898},"routing-and-navigation","Routing and Navigation",[20,3901,3902,3903,3906,3907,2390],{},"Most real applications need multiple screens. Dioxus includes a ",[546,3904,3905],{},"type-safe router"," that maps enum variants to paths. (",[203,3908,3697],{"href":3909,"rel":3910,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Ftutorial\u002Frouting\u002F?utm_source=chatgpt.com",[207],[2459,3912,3914],{"id":3913},"routing-example","Routing Example",[47,3916,3918],{"className":3660,"code":3917,"language":3662,"meta":55,"style":55},"#[derive(Routable, Clone, PartialEq)]\nenum Route {\n    #[route(\"\u002F\")]\n    DogView,\n}\n",[39,3919,3920,3925,3930,3935,3940],{"__ignoreMap":55},[250,3921,3922],{"class":252,"line":253},[250,3923,3924],{},"#[derive(Routable, Clone, PartialEq)]\n",[250,3926,3927],{"class":252,"line":113},[250,3928,3929],{},"enum Route {\n",[250,3931,3932],{"class":252,"line":110},[250,3933,3934],{},"    #[route(\"\u002F\")]\n",[250,3936,3937],{"class":252,"line":269},[250,3938,3939],{},"    DogView,\n",[250,3941,3942],{"class":252,"line":275},[250,3943,991],{},[20,3945,3946,3947,2390],{},"Once configured, navigating between pages is seamless and safe at compile time, reducing runtime bugs. (",[203,3948,3697],{"href":3909,"rel":3949,"title":3696},[207],[72,3951],{},[31,3953,3955],{"id":3954},"fullstack-capabilities","Fullstack Capabilities",[20,3957,3958,3959,3962,3963,2390],{},"Dioxus doesn’t just handle the frontend—",[546,3960,3961],{},"it also integrates backend logic directly in Rust",". You can combine frontend UI code with backend server functions, state management, and SSR capabilities via the fullstack features. (",[203,3964,3697],{"href":3965,"rel":3966,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002Fessentials\u002Ffullstack\u002F?utm_source=chatgpt.com",[207],[2459,3968,3970],{"id":3969},"fullstack-features","Fullstack Features",[561,3972,3973,3976,3979],{},[564,3974,3975],{},"Server functions callable from the UI",[564,3977,3978],{},"Integration with backend frameworks",[564,3980,3981],{},"Static and dynamic content rendering\n::",[20,3983,3984,3985,3988],{},"This makes Dioxus ideal for ",[546,3986,3987],{},"end-to-end Rust applications"," where both client and server share a language and ecosystem.",[72,3990],{},[31,3992,3994],{"id":3993},"why-dioxus-matters","Why Dioxus Matters",[20,3996,3997,3998,4001,4002,2390],{},"With Dioxus 0.7, Rust developers finally have a ",[546,3999,4000],{},"mature, ergonomic framework"," for building cross-platform UI applications that don’t compromise performance or safety. The combination of Rust’s compile-time guarantees, declarative UI, and comprehensive tooling makes it a compelling choice for modern application development. (",[203,4003,3697],{"href":4004,"rel":4005,"title":3696},"https:\u002F\u002Fdioxuslabs.com\u002Flearn\u002F0.7\u002F?utm_source=chatgpt.com",[207],[20,4007,4008,4009,4012],{},"Whether you’re building a ",[546,4010,4011],{},"mobile app, desktop client, or WASM-based web UI",", Dioxus helps you maintain a single codebase across all platforms without sacrificing developer productivity.",[72,4014],{},[15,4016,3352],{"id":3351},[20,4018,4019],{},"Dioxus 0.7 is more than just a UI framework — it’s a unified platform for building fullstack, cross-platform applications entirely in Rust. With intuitive UI syntax, powerful state management, routing, backend integration, and solid tooling, it’s positioned as a strong contender for modern app development in Rust.",[20,4021,4022,4023,4026],{},"If you’re ready to build ",[546,4024,4025],{},"fast, safe, and beautiful applications",", Dioxus is a framework worth exploring. 🚀",[500,4028,502],{},{"title":55,"searchDepth":110,"depth":110,"links":4030},[4031,4032,4033,4036,4037,4040,4043,4046,4049],{"id":3551,"depth":113,"text":3552},{"id":3595,"depth":113,"text":3596},{"id":3643,"depth":113,"text":3644,"children":4034},[4035],{"id":3656,"depth":110,"text":3657},{"id":3709,"depth":113,"text":3710},{"id":3738,"depth":113,"text":3739,"children":4038},[4039],{"id":3749,"depth":110,"text":3750},{"id":3784,"depth":113,"text":3785,"children":4041},[4042],{"id":3803,"depth":110,"text":3804},{"id":3898,"depth":113,"text":3899,"children":4044},[4045],{"id":3913,"depth":110,"text":3914},{"id":3954,"depth":113,"text":3955,"children":4047},[4048],{"id":3969,"depth":110,"text":3970},{"id":3993,"depth":113,"text":3994},"2026-01-10","Explore Dioxus 0.7 — what it is, how it works across platforms using Rust, and why it’s an exciting choice for building modern UI applications.",{"type":12,"value":4053},[4054,4056,4066],[15,4055,541],{"id":540},[20,4057,4058,3530,4060,3534,4062,3538,4064],{},[546,4059,3529],{},[546,4061,3533],{},[546,4063,3537],{},[3540,4065,3543],{"index":3542},[20,4067,3546],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1590608897129-79d5d1839d6b",[4070,3662,4071,4072,4073],"dioxus","cross-platform","ui","fullstack",{},"\u002Fblog\u002Fdioxus",{"title":3519,"description":4051},"blog\u002Fdioxus","ik7qwhV3ti2_3_TQgouu70cD-IzsGInsTWSbYMdqmWU",{"id":4080,"title":4081,"author":4082,"body":4083,"canonical":115,"categories":115,"date":3470,"description":8209,"excerpt":8210,"extension":118,"img":3502,"keywords":8228,"language":3510,"meta":8235,"navigation":129,"ogImage":115,"path":8236,"rating":275,"readTime":316,"seo":8237,"stem":8238,"tag":3515,"__hash__":8239},"blog\u002Fblog\u002Fdrizzle-nitro-api.md","Building a Production API with Drizzle ORM + Nitro: A Complete Guide",{"name":8,"img":10,"website":535},{"type":12,"value":4084,"toc":8184},[4085,4087,4094,4101,4104,4111,4115,4118,4150,4155,4157,4159,4163,4166,4177,4179,4183,4186,4250,4255,4257,4261,4264,4269,4356,4358,4362,4365,4385,4390,5034,5041,5043,5047,5050,5055,5344,5346,5350,5353,5358,5789,5791,5795,5799,5804,5894,5898,5903,6129,6133,6136,6140,7057,7061,7066,7567,7571,7576,7798,7800,7804,7807,7844,7859,7861,7865,7868,7880,7884,7902,7906,7918,7922,7989,7993,8027,8029,8031,8033,8050,8052,8140,8142,8144,8151,8154,8174,8181],[15,4086,541],{"id":540},[20,4088,4089,4090,4093],{},"In our ",[546,4091,4092],{},"BrewStop food truck series",", we used Unstorage for data persistence—an excellent choice for prototypes and simple applications. But when you're building for production, you need something more robust: a proper database with type-safe queries, migrations, and scalable architecture.",[20,4095,4096,4097,4100],{},"That's where ",[546,4098,4099],{},"Drizzle ORM"," comes in.",[20,4102,4103],{},"Drizzle is a lightweight, TypeScript-first ORM that gives you the control of raw SQL with the ergonomics of an ORM. It pairs beautifully with Nitro, offering a production-ready data layer that won't slow you down.",[20,4105,4106,4107,4110],{},"In this post, we'll build a complete database-backed API using ",[546,4108,4109],{},"Drizzle ORM + Nitro","—covering setup, schema design, queries, and deployment.",[15,4112,4114],{"id":4113},"why-drizzle-orm","Why Drizzle ORM?",[20,4116,4117],{},"Before we dive in, let's talk about why Drizzle is worth your attention:",[561,4119,4120,4126,4132,4138,4144],{},[564,4121,4122,4125],{},[546,4123,4124],{},"Type-safe queries"," — TypeScript understands your schema end-to-end",[564,4127,4128,4131],{},[546,4129,4130],{},"Lightweight"," — No heavy runtime, compiles to efficient SQL",[564,4133,4134,4137],{},[546,4135,4136],{},"Portable"," — Works with PostgreSQL, MySQL, SQLite, and more",[564,4139,4140,4143],{},[546,4141,4142],{},"Migration support"," — First-class migration tooling",[564,4145,4146,4149],{},[546,4147,4148],{},"Zero dependencies"," — Doesn't pull in unnecessary bloat",[24,4151,4152],{"type":631},[20,4153,4154],{},"Drizzle is designed to feel like you're writing SQL—but with full type safety and IDE autocomplete.",[72,4156],{},[15,4158,748],{"id":747},[31,4160,4162],{"id":4161},"prerequisites","Prerequisites",[20,4164,4165],{},"This guide assumes you have:",[561,4167,4168,4171,4174],{},[564,4169,4170],{},"Node.js 18+ installed",[564,4172,4173],{},"Basic knowledge of TypeScript",[564,4175,4176],{},"A PostgreSQL or SQLite database (we'll use SQLite for simplicity, but the code is mostly identical)",[72,4178],{},[31,4180,4182],{"id":4181},"step-1-project-setup","Step 1: Project Setup",[20,4184,4185],{},"Let's start by creating a new Nitro project and installing Drizzle.",[47,4187,4189],{"className":758,"code":4188,"filename":760,"language":761,"meta":55,"style":55},"# Create a new Nitro project\nnpx create-nitro-app brewstop-api-v2\ncd brewstop-api-v2\n\n# Install Drizzle ORM and SQLite driver\nnpm install drizzle-orm better-sqlite3\nnpm install -D drizzle-kit @types\u002Fbetter-sqlite3\n",[39,4190,4191,4196,4207,4213,4217,4222,4235],{"__ignoreMap":55},[250,4192,4193],{"class":252,"line":253},[250,4194,4195],{"class":768},"# Create a new Nitro project\n",[250,4197,4198,4201,4204],{"class":252,"line":113},[250,4199,4200],{"class":774},"npx",[250,4202,4203],{"class":782}," create-nitro-app",[250,4205,4206],{"class":782}," brewstop-api-v2\n",[250,4208,4209,4211],{"class":252,"line":110},[250,4210,874],{"class":778},[250,4212,4206],{"class":782},[250,4214,4215],{"class":252,"line":269},[250,4216,795],{"emptyLinePlaceholder":129},[250,4218,4219],{"class":252,"line":275},[250,4220,4221],{"class":768},"# Install Drizzle ORM and SQLite driver\n",[250,4223,4224,4227,4229,4232],{"class":252,"line":281},[250,4225,4226],{"class":774},"npm",[250,4228,808],{"class":782},[250,4230,4231],{"class":782}," drizzle-orm",[250,4233,4234],{"class":782}," better-sqlite3\n",[250,4236,4237,4239,4241,4244,4247],{"class":252,"line":287},[250,4238,4226],{"class":774},[250,4240,808],{"class":782},[250,4242,4243],{"class":778}," -D",[250,4245,4246],{"class":782}," drizzle-kit",[250,4248,4249],{"class":782}," @types\u002Fbetter-sqlite3\n",[24,4251,4252],{"type":26},[20,4253,4254],{},"Make sure to use the appropriate driver for your database (pg for PostgreSQL, mysql2 for MySQL, etc.). We'll use better-sqlite3 for this example.",[72,4256],{},[31,4258,4260],{"id":4259},"step-2-configure-drizzle","Step 2: Configure Drizzle",[20,4262,4263],{},"Create a configuration file for Drizzle. This tells Drizzle where your database is and how to handle migrations.",[20,4265,1092,4266,1007],{},[39,4267,4268],{},"drizzle.config.ts",[47,4270,4272],{"className":1010,"code":4271,"filename":4268,"language":1012,"meta":55,"style":55},"import { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n  schema: \".\u002Fserver\u002Fdb\u002Fschema.ts\",\n  out: \".\u002Fdrizzle\",\n  dialect: \"sqlite\",\n  dbCredentials: {\n    url: \".\u002Fbrewstop.db\",\n  },\n});\n",[39,4273,4274,4288,4292,4303,4313,4323,4333,4338,4348,4352],{"__ignoreMap":55},[250,4275,4276,4278,4281,4283,4286],{"class":252,"line":253},[250,4277,1763],{"class":786},[250,4279,4280],{"class":912}," { defineConfig } ",[250,4282,1769],{"class":786},[250,4284,4285],{"class":782}," \"drizzle-kit\"",[250,4287,1379],{"class":912},[250,4289,4290],{"class":252,"line":113},[250,4291,795],{"emptyLinePlaceholder":129},[250,4293,4294,4296,4298,4301],{"class":252,"line":110},[250,4295,1019],{"class":786},[250,4297,1022],{"class":786},[250,4299,4300],{"class":774}," defineConfig",[250,4302,1028],{"class":912},[250,4304,4305,4308,4311],{"class":252,"line":269},[250,4306,4307],{"class":912},"  schema: ",[250,4309,4310],{"class":782},"\".\u002Fserver\u002Fdb\u002Fschema.ts\"",[250,4312,927],{"class":912},[250,4314,4315,4318,4321],{"class":252,"line":275},[250,4316,4317],{"class":912},"  out: ",[250,4319,4320],{"class":782},"\".\u002Fdrizzle\"",[250,4322,927],{"class":912},[250,4324,4325,4328,4331],{"class":252,"line":281},[250,4326,4327],{"class":912},"  dialect: ",[250,4329,4330],{"class":782},"\"sqlite\"",[250,4332,927],{"class":912},[250,4334,4335],{"class":252,"line":287},[250,4336,4337],{"class":912},"  dbCredentials: {\n",[250,4339,4340,4343,4346],{"class":252,"line":293},[250,4341,4342],{"class":912},"    url: ",[250,4344,4345],{"class":782},"\".\u002Fbrewstop.db\"",[250,4347,927],{"class":912},[250,4349,4350],{"class":252,"line":299},[250,4351,1048],{"class":912},[250,4353,4354],{"class":252,"line":132},[250,4355,1077],{"class":912},[72,4357],{},[31,4359,4361],{"id":4360},"step-3-define-your-schema","Step 3: Define Your Schema",[20,4363,4364],{},"Now let's design our database schema. For BrewStop, we need:",[561,4366,4367,4373,4379],{},[564,4368,4369,4372],{},[546,4370,4371],{},"Menu items"," — products the food truck sells",[564,4374,4375,4378],{},[546,4376,4377],{},"Orders"," — customer orders",[564,4380,4381,4384],{},[546,4382,4383],{},"Order items"," — individual items within an order",[20,4386,1092,4387,1007],{},[39,4388,4389],{},"server\u002Fdb\u002Fschema.ts",[47,4391,4393],{"className":1010,"code":4392,"filename":4389,"language":1012,"meta":55,"style":55},"import { sqliteTable, text, integer, real } from \"drizzle-orm\u002Fsqlite-core\";\nimport { sql } from \"drizzle-orm\";\n\n\u002F\u002F Menu Items Table\nexport const menuItems = sqliteTable(\"menu_items\", {\n  id: text(\"id\").primaryKey(),\n  name: text(\"name\").notNull(),\n  description: text(\"description\"),\n  price: real(\"price\").notNull(),\n  category: text(\"category\").notNull(), \u002F\u002F coffee, tea, food\n  available: integer(\"available\", { mode: \"boolean\" }).default(true),\n  createdAt: integer(\"created_at\", { mode: \"timestamp\" })\n    .default(sql`CURRENT_TIMESTAMP`),\n});\n\n\u002F\u002F Orders Table\nexport const orders = sqliteTable(\"orders\", {\n  id: text(\"id\").primaryKey(),\n  status: text(\"status\").notNull().default(\"pending\"), \u002F\u002F pending, preparing, ready, completed\n  customerName: text(\"customer_name\"),\n  total: real(\"total\").notNull(),\n  createdAt: integer(\"created_at\", { mode: \"timestamp\" })\n    .default(sql`CURRENT_TIMESTAMP`),\n  updatedAt: integer(\"updated_at\", { mode: \"timestamp\" })\n    .default(sql`CURRENT_TIMESTAMP`),\n});\n\n\u002F\u002F Order Items Table (junction table)\nexport const orderItems = sqliteTable(\"order_items\", {\n  id: text(\"id\").primaryKey(),\n  orderId: text(\"order_id\")\n    .notNull()\n    .references(() => orders.id),\n  menuItemId: text(\"menu_item_id\")\n    .notNull()\n    .references(() => menuItems.id),\n  quantity: integer(\"quantity\").notNull().default(1),\n  unitPrice: real(\"unit_price\").notNull(),\n});\n\n\u002F\u002F Type exports for TypeScript\nexport type MenuItem = typeof menuItems.$inferSelect;\nexport type NewMenuItem = typeof menuItems.$inferInsert;\nexport type Order = typeof orders.$inferSelect;\nexport type NewOrder = typeof orders.$inferInsert;\n",[39,4394,4395,4409,4423,4427,4432,4455,4474,4493,4508,4527,4549,4580,4600,4617,4621,4625,4630,4649,4665,4695,4709,4727,4743,4757,4775,4789,4793,4797,4802,4822,4838,4853,4862,4876,4890,4898,4911,4937,4955,4959,4963,4968,4986,5002,5018],{"__ignoreMap":55},[250,4396,4397,4399,4402,4404,4407],{"class":252,"line":253},[250,4398,1763],{"class":786},[250,4400,4401],{"class":912}," { sqliteTable, text, integer, real } ",[250,4403,1769],{"class":786},[250,4405,4406],{"class":782}," \"drizzle-orm\u002Fsqlite-core\"",[250,4408,1379],{"class":912},[250,4410,4411,4413,4416,4418,4421],{"class":252,"line":113},[250,4412,1763],{"class":786},[250,4414,4415],{"class":912}," { sql } ",[250,4417,1769],{"class":786},[250,4419,4420],{"class":782}," \"drizzle-orm\"",[250,4422,1379],{"class":912},[250,4424,4425],{"class":252,"line":110},[250,4426,795],{"emptyLinePlaceholder":129},[250,4428,4429],{"class":252,"line":269},[250,4430,4431],{"class":768},"\u002F\u002F Menu Items Table\n",[250,4433,4434,4436,4439,4442,4444,4447,4449,4452],{"class":252,"line":275},[250,4435,1019],{"class":786},[250,4437,4438],{"class":786}," const",[250,4440,4441],{"class":778}," menuItems",[250,4443,1187],{"class":786},[250,4445,4446],{"class":774}," sqliteTable",[250,4448,1434],{"class":912},[250,4450,4451],{"class":782},"\"menu_items\"",[250,4453,4454],{"class":912},", {\n",[250,4456,4457,4460,4462,4464,4467,4469,4472],{"class":252,"line":281},[250,4458,4459],{"class":912},"  id: ",[250,4461,52],{"class":774},[250,4463,1434],{"class":912},[250,4465,4466],{"class":782},"\"id\"",[250,4468,2380],{"class":912},[250,4470,4471],{"class":774},"primaryKey",[250,4473,1156],{"class":912},[250,4475,4476,4479,4481,4483,4486,4488,4491],{"class":252,"line":287},[250,4477,4478],{"class":912},"  name: ",[250,4480,52],{"class":774},[250,4482,1434],{"class":912},[250,4484,4485],{"class":782},"\"name\"",[250,4487,2380],{"class":912},[250,4489,4490],{"class":774},"notNull",[250,4492,1156],{"class":912},[250,4494,4495,4498,4500,4502,4505],{"class":252,"line":293},[250,4496,4497],{"class":912},"  description: ",[250,4499,52],{"class":774},[250,4501,1434],{"class":912},[250,4503,4504],{"class":782},"\"description\"",[250,4506,4507],{"class":912},"),\n",[250,4509,4510,4513,4516,4518,4521,4523,4525],{"class":252,"line":299},[250,4511,4512],{"class":912},"  price: ",[250,4514,4515],{"class":774},"real",[250,4517,1434],{"class":912},[250,4519,4520],{"class":782},"\"price\"",[250,4522,2380],{"class":912},[250,4524,4490],{"class":774},[250,4526,1156],{"class":912},[250,4528,4529,4532,4534,4536,4539,4541,4543,4546],{"class":252,"line":132},[250,4530,4531],{"class":912},"  category: ",[250,4533,52],{"class":774},[250,4535,1434],{"class":912},[250,4537,4538],{"class":782},"\"category\"",[250,4540,2380],{"class":912},[250,4542,4490],{"class":774},[250,4544,4545],{"class":912},"(), ",[250,4547,4548],{"class":768},"\u002F\u002F coffee, tea, food\n",[250,4550,4551,4554,4557,4559,4562,4565,4568,4571,4574,4576,4578],{"class":252,"line":310},[250,4552,4553],{"class":912},"  available: ",[250,4555,4556],{"class":774},"integer",[250,4558,1434],{"class":912},[250,4560,4561],{"class":782},"\"available\"",[250,4563,4564],{"class":912},", { mode: ",[250,4566,4567],{"class":782},"\"boolean\"",[250,4569,4570],{"class":912}," }).",[250,4572,4573],{"class":774},"default",[250,4575,1434],{"class":912},[250,4577,1066],{"class":778},[250,4579,4507],{"class":912},[250,4581,4582,4585,4587,4589,4592,4594,4597],{"class":252,"line":316},[250,4583,4584],{"class":912},"  createdAt: ",[250,4586,4556],{"class":774},[250,4588,1434],{"class":912},[250,4590,4591],{"class":782},"\"created_at\"",[250,4593,4564],{"class":912},[250,4595,4596],{"class":782},"\"timestamp\"",[250,4598,4599],{"class":912}," })\n",[250,4601,4602,4605,4607,4609,4612,4615],{"class":252,"line":322},[250,4603,4604],{"class":912},"    .",[250,4606,4573],{"class":774},[250,4608,1434],{"class":912},[250,4610,4611],{"class":774},"sql",[250,4613,4614],{"class":782},"`CURRENT_TIMESTAMP`",[250,4616,4507],{"class":912},[250,4618,4619],{"class":252,"line":328},[250,4620,1077],{"class":912},[250,4622,4623],{"class":252,"line":334},[250,4624,795],{"emptyLinePlaceholder":129},[250,4626,4627],{"class":252,"line":340},[250,4628,4629],{"class":768},"\u002F\u002F Orders Table\n",[250,4631,4632,4634,4636,4638,4640,4642,4644,4647],{"class":252,"line":346},[250,4633,1019],{"class":786},[250,4635,4438],{"class":786},[250,4637,1405],{"class":778},[250,4639,1187],{"class":786},[250,4641,4446],{"class":774},[250,4643,1434],{"class":912},[250,4645,4646],{"class":782},"\"orders\"",[250,4648,4454],{"class":912},[250,4650,4651,4653,4655,4657,4659,4661,4663],{"class":252,"line":352},[250,4652,4459],{"class":912},[250,4654,52],{"class":774},[250,4656,1434],{"class":912},[250,4658,4466],{"class":782},[250,4660,2380],{"class":912},[250,4662,4471],{"class":774},[250,4664,1156],{"class":912},[250,4666,4667,4670,4672,4674,4677,4679,4681,4683,4685,4687,4689,4692],{"class":252,"line":358},[250,4668,4669],{"class":912},"  status: ",[250,4671,52],{"class":774},[250,4673,1434],{"class":912},[250,4675,4676],{"class":782},"\"status\"",[250,4678,2380],{"class":912},[250,4680,4490],{"class":774},[250,4682,1647],{"class":912},[250,4684,4573],{"class":774},[250,4686,1434],{"class":912},[250,4688,1631],{"class":782},[250,4690,4691],{"class":912},"), ",[250,4693,4694],{"class":768},"\u002F\u002F pending, preparing, ready, completed\n",[250,4696,4697,4700,4702,4704,4707],{"class":252,"line":364},[250,4698,4699],{"class":912},"  customerName: ",[250,4701,52],{"class":774},[250,4703,1434],{"class":912},[250,4705,4706],{"class":782},"\"customer_name\"",[250,4708,4507],{"class":912},[250,4710,4711,4714,4716,4718,4721,4723,4725],{"class":252,"line":370},[250,4712,4713],{"class":912},"  total: ",[250,4715,4515],{"class":774},[250,4717,1434],{"class":912},[250,4719,4720],{"class":782},"\"total\"",[250,4722,2380],{"class":912},[250,4724,4490],{"class":774},[250,4726,1156],{"class":912},[250,4728,4729,4731,4733,4735,4737,4739,4741],{"class":252,"line":376},[250,4730,4584],{"class":912},[250,4732,4556],{"class":774},[250,4734,1434],{"class":912},[250,4736,4591],{"class":782},[250,4738,4564],{"class":912},[250,4740,4596],{"class":782},[250,4742,4599],{"class":912},[250,4744,4745,4747,4749,4751,4753,4755],{"class":252,"line":382},[250,4746,4604],{"class":912},[250,4748,4573],{"class":774},[250,4750,1434],{"class":912},[250,4752,4611],{"class":774},[250,4754,4614],{"class":782},[250,4756,4507],{"class":912},[250,4758,4759,4762,4764,4766,4769,4771,4773],{"class":252,"line":388},[250,4760,4761],{"class":912},"  updatedAt: ",[250,4763,4556],{"class":774},[250,4765,1434],{"class":912},[250,4767,4768],{"class":782},"\"updated_at\"",[250,4770,4564],{"class":912},[250,4772,4596],{"class":782},[250,4774,4599],{"class":912},[250,4776,4777,4779,4781,4783,4785,4787],{"class":252,"line":393},[250,4778,4604],{"class":912},[250,4780,4573],{"class":774},[250,4782,1434],{"class":912},[250,4784,4611],{"class":774},[250,4786,4614],{"class":782},[250,4788,4507],{"class":912},[250,4790,4791],{"class":252,"line":399},[250,4792,1077],{"class":912},[250,4794,4795],{"class":252,"line":405},[250,4796,795],{"emptyLinePlaceholder":129},[250,4798,4799],{"class":252,"line":410},[250,4800,4801],{"class":768},"\u002F\u002F Order Items Table (junction table)\n",[250,4803,4804,4806,4808,4811,4813,4815,4817,4820],{"class":252,"line":415},[250,4805,1019],{"class":786},[250,4807,4438],{"class":786},[250,4809,4810],{"class":778}," orderItems",[250,4812,1187],{"class":786},[250,4814,4446],{"class":774},[250,4816,1434],{"class":912},[250,4818,4819],{"class":782},"\"order_items\"",[250,4821,4454],{"class":912},[250,4823,4824,4826,4828,4830,4832,4834,4836],{"class":252,"line":420},[250,4825,4459],{"class":912},[250,4827,52],{"class":774},[250,4829,1434],{"class":912},[250,4831,4466],{"class":782},[250,4833,2380],{"class":912},[250,4835,4471],{"class":774},[250,4837,1156],{"class":912},[250,4839,4840,4843,4845,4847,4850],{"class":252,"line":426},[250,4841,4842],{"class":912},"  orderId: ",[250,4844,52],{"class":774},[250,4846,1434],{"class":912},[250,4848,4849],{"class":782},"\"order_id\"",[250,4851,4852],{"class":912},")\n",[250,4854,4855,4857,4859],{"class":252,"line":431},[250,4856,4604],{"class":912},[250,4858,4490],{"class":774},[250,4860,4861],{"class":912},"()\n",[250,4863,4864,4866,4869,4871,4873],{"class":252,"line":436},[250,4865,4604],{"class":912},[250,4867,4868],{"class":774},"references",[250,4870,1112],{"class":912},[250,4872,1115],{"class":786},[250,4874,4875],{"class":912}," orders.id),\n",[250,4877,4878,4881,4883,4885,4888],{"class":252,"line":442},[250,4879,4880],{"class":912},"  menuItemId: ",[250,4882,52],{"class":774},[250,4884,1434],{"class":912},[250,4886,4887],{"class":782},"\"menu_item_id\"",[250,4889,4852],{"class":912},[250,4891,4892,4894,4896],{"class":252,"line":447},[250,4893,4604],{"class":912},[250,4895,4490],{"class":774},[250,4897,4861],{"class":912},[250,4899,4900,4902,4904,4906,4908],{"class":252,"line":453},[250,4901,4604],{"class":912},[250,4903,4868],{"class":774},[250,4905,1112],{"class":912},[250,4907,1115],{"class":786},[250,4909,4910],{"class":912}," menuItems.id),\n",[250,4912,4913,4916,4918,4920,4923,4925,4927,4929,4931,4933,4935],{"class":252,"line":459},[250,4914,4915],{"class":912},"  quantity: ",[250,4917,4556],{"class":774},[250,4919,1434],{"class":912},[250,4921,4922],{"class":782},"\"quantity\"",[250,4924,2380],{"class":912},[250,4926,4490],{"class":774},[250,4928,1647],{"class":912},[250,4930,4573],{"class":774},[250,4932,1434],{"class":912},[250,4934,1198],{"class":778},[250,4936,4507],{"class":912},[250,4938,4939,4942,4944,4946,4949,4951,4953],{"class":252,"line":465},[250,4940,4941],{"class":912},"  unitPrice: ",[250,4943,4515],{"class":774},[250,4945,1434],{"class":912},[250,4947,4948],{"class":782},"\"unit_price\"",[250,4950,2380],{"class":912},[250,4952,4490],{"class":774},[250,4954,1156],{"class":912},[250,4956,4957],{"class":252,"line":471},[250,4958,1077],{"class":912},[250,4960,4961],{"class":252,"line":2201},[250,4962,795],{"emptyLinePlaceholder":129},[250,4964,4965],{"class":252,"line":2207},[250,4966,4967],{"class":768},"\u002F\u002F Type exports for TypeScript\n",[250,4969,4970,4972,4975,4978,4980,4983],{"class":252,"line":2213},[250,4971,1019],{"class":786},[250,4973,4974],{"class":786}," type",[250,4976,4977],{"class":774}," MenuItem",[250,4979,1187],{"class":786},[250,4981,4982],{"class":786}," typeof",[250,4984,4985],{"class":912}," menuItems.$inferSelect;\n",[250,4987,4988,4990,4992,4995,4997,4999],{"class":252,"line":2218},[250,4989,1019],{"class":786},[250,4991,4974],{"class":786},[250,4993,4994],{"class":774}," NewMenuItem",[250,4996,1187],{"class":786},[250,4998,4982],{"class":786},[250,5000,5001],{"class":912}," menuItems.$inferInsert;\n",[250,5003,5004,5006,5008,5011,5013,5015],{"class":252,"line":2223},[250,5005,1019],{"class":786},[250,5007,4974],{"class":786},[250,5009,5010],{"class":774}," Order",[250,5012,1187],{"class":786},[250,5014,4982],{"class":786},[250,5016,5017],{"class":912}," orders.$inferSelect;\n",[250,5019,5020,5022,5024,5027,5029,5031],{"class":252,"line":2239},[250,5021,1019],{"class":786},[250,5023,4974],{"class":786},[250,5025,5026],{"class":774}," NewOrder",[250,5028,1187],{"class":786},[250,5030,4982],{"class":786},[250,5032,5033],{"class":912}," orders.$inferInsert;\n",[161,5035,5038],{"icon":5036,"title":5037},"🔑","Schema Best Practices",[20,5039,5040],{},"Always define your schema in TypeScript. Drizzle's type inference means your queries will be fully typed—no more guessing what fields exist on your models.",[72,5042],{},[31,5044,5046],{"id":5045},"step-4-initialize-the-database-connection","Step 4: Initialize the Database Connection",[20,5048,5049],{},"Create a database connection utility that Nitro can use.",[20,5051,1092,5052,1007],{},[39,5053,5054],{},"server\u002Fdb\u002Findex.ts",[47,5056,5058],{"className":1010,"code":5057,"filename":5054,"language":1012,"meta":55,"style":55},"import Database from \"better-sqlite3\";\nimport { drizzle } from \"drizzle-orm\u002Fbetter-sqlite3\";\nimport * as schema from \".\u002Fschema\";\n\nconst sqlite = new Database(\"brewstop.db\");\nexport const db = drizzle(sqlite, { schema });\n\n\u002F\u002F Initialize tables on startup\nexport function initializeDatabase() {\n  sqlite.exec(`\n    CREATE TABLE IF NOT EXISTS menu_items (\n      id TEXT PRIMARY KEY,\n      name TEXT NOT NULL,\n      description TEXT,\n      price REAL NOT NULL,\n      category TEXT NOT NULL,\n      available INTEGER DEFAULT 1,\n      created_at INTEGER DEFAULT (strftime('%s', 'now'))\n    );\n\n    CREATE TABLE IF NOT EXISTS orders (\n      id TEXT PRIMARY KEY,\n      status TEXT NOT NULL DEFAULT 'pending',\n      customer_name TEXT,\n      total REAL NOT NULL,\n      created_at INTEGER DEFAULT (strftime('%s', 'now')),\n      updated_at INTEGER DEFAULT (strftime('%s', 'now'))\n    );\n\n    CREATE TABLE IF NOT EXISTS order_items (\n      id TEXT PRIMARY KEY,\n      order_id TEXT NOT NULL,\n      menu_item_id TEXT NOT NULL,\n      quantity INTEGER DEFAULT 1,\n      unit_price REAL NOT NULL,\n      FOREIGN KEY (order_id) REFERENCES orders(id),\n      FOREIGN KEY (menu_item_id) REFERENCES menu_items(id)\n    );\n  `);\n  \n  console.log(\"✅ Database initialized\");\n}\n",[39,5059,5060,5074,5088,5108,5112,5133,5150,5154,5159,5170,5183,5188,5193,5198,5203,5208,5213,5218,5223,5227,5231,5236,5240,5245,5250,5255,5260,5265,5269,5273,5278,5282,5287,5292,5297,5302,5307,5312,5316,5323,5327,5340],{"__ignoreMap":55},[250,5061,5062,5064,5067,5069,5072],{"class":252,"line":253},[250,5063,1763],{"class":786},[250,5065,5066],{"class":912}," Database ",[250,5068,1769],{"class":786},[250,5070,5071],{"class":782}," \"better-sqlite3\"",[250,5073,1379],{"class":912},[250,5075,5076,5078,5081,5083,5086],{"class":252,"line":113},[250,5077,1763],{"class":786},[250,5079,5080],{"class":912}," { drizzle } ",[250,5082,1769],{"class":786},[250,5084,5085],{"class":782}," \"drizzle-orm\u002Fbetter-sqlite3\"",[250,5087,1379],{"class":912},[250,5089,5090,5092,5095,5098,5101,5103,5106],{"class":252,"line":110},[250,5091,1763],{"class":786},[250,5093,5094],{"class":778}," *",[250,5096,5097],{"class":786}," as",[250,5099,5100],{"class":912}," schema ",[250,5102,1769],{"class":786},[250,5104,5105],{"class":782}," \".\u002Fschema\"",[250,5107,1379],{"class":912},[250,5109,5110],{"class":252,"line":269},[250,5111,795],{"emptyLinePlaceholder":129},[250,5113,5114,5116,5119,5121,5123,5126,5128,5131],{"class":252,"line":275},[250,5115,1181],{"class":786},[250,5117,5118],{"class":778}," sqlite",[250,5120,1187],{"class":786},[250,5122,1568],{"class":786},[250,5124,5125],{"class":774}," Database",[250,5127,1434],{"class":912},[250,5129,5130],{"class":782},"\"brewstop.db\"",[250,5132,1885],{"class":912},[250,5134,5135,5137,5139,5142,5144,5147],{"class":252,"line":281},[250,5136,1019],{"class":786},[250,5138,4438],{"class":786},[250,5140,5141],{"class":778}," db",[250,5143,1187],{"class":786},[250,5145,5146],{"class":774}," drizzle",[250,5148,5149],{"class":912},"(sqlite, { schema });\n",[250,5151,5152],{"class":252,"line":287},[250,5153,795],{"emptyLinePlaceholder":129},[250,5155,5156],{"class":252,"line":293},[250,5157,5158],{"class":768},"\u002F\u002F Initialize tables on startup\n",[250,5160,5161,5163,5165,5168],{"class":252,"line":299},[250,5162,1019],{"class":786},[250,5164,1845],{"class":786},[250,5166,5167],{"class":774}," initializeDatabase",[250,5169,1851],{"class":912},[250,5171,5172,5175,5178,5180],{"class":252,"line":132},[250,5173,5174],{"class":912},"  sqlite.",[250,5176,5177],{"class":774},"exec",[250,5179,1434],{"class":912},[250,5181,5182],{"class":782},"`\n",[250,5184,5185],{"class":252,"line":310},[250,5186,5187],{"class":782},"    CREATE TABLE IF NOT EXISTS menu_items (\n",[250,5189,5190],{"class":252,"line":316},[250,5191,5192],{"class":782},"      id TEXT PRIMARY KEY,\n",[250,5194,5195],{"class":252,"line":322},[250,5196,5197],{"class":782},"      name TEXT NOT NULL,\n",[250,5199,5200],{"class":252,"line":328},[250,5201,5202],{"class":782},"      description TEXT,\n",[250,5204,5205],{"class":252,"line":334},[250,5206,5207],{"class":782},"      price REAL NOT NULL,\n",[250,5209,5210],{"class":252,"line":340},[250,5211,5212],{"class":782},"      category TEXT NOT NULL,\n",[250,5214,5215],{"class":252,"line":346},[250,5216,5217],{"class":782},"      available INTEGER DEFAULT 1,\n",[250,5219,5220],{"class":252,"line":352},[250,5221,5222],{"class":782},"      created_at INTEGER DEFAULT (strftime('%s', 'now'))\n",[250,5224,5225],{"class":252,"line":358},[250,5226,2210],{"class":782},[250,5228,5229],{"class":252,"line":364},[250,5230,795],{"emptyLinePlaceholder":129},[250,5232,5233],{"class":252,"line":370},[250,5234,5235],{"class":782},"    CREATE TABLE IF NOT EXISTS orders (\n",[250,5237,5238],{"class":252,"line":376},[250,5239,5192],{"class":782},[250,5241,5242],{"class":252,"line":382},[250,5243,5244],{"class":782},"      status TEXT NOT NULL DEFAULT 'pending',\n",[250,5246,5247],{"class":252,"line":388},[250,5248,5249],{"class":782},"      customer_name TEXT,\n",[250,5251,5252],{"class":252,"line":393},[250,5253,5254],{"class":782},"      total REAL NOT NULL,\n",[250,5256,5257],{"class":252,"line":399},[250,5258,5259],{"class":782},"      created_at INTEGER DEFAULT (strftime('%s', 'now')),\n",[250,5261,5262],{"class":252,"line":405},[250,5263,5264],{"class":782},"      updated_at INTEGER DEFAULT (strftime('%s', 'now'))\n",[250,5266,5267],{"class":252,"line":410},[250,5268,2210],{"class":782},[250,5270,5271],{"class":252,"line":415},[250,5272,795],{"emptyLinePlaceholder":129},[250,5274,5275],{"class":252,"line":420},[250,5276,5277],{"class":782},"    CREATE TABLE IF NOT EXISTS order_items (\n",[250,5279,5280],{"class":252,"line":426},[250,5281,5192],{"class":782},[250,5283,5284],{"class":252,"line":431},[250,5285,5286],{"class":782},"      order_id TEXT NOT NULL,\n",[250,5288,5289],{"class":252,"line":436},[250,5290,5291],{"class":782},"      menu_item_id TEXT NOT NULL,\n",[250,5293,5294],{"class":252,"line":442},[250,5295,5296],{"class":782},"      quantity INTEGER DEFAULT 1,\n",[250,5298,5299],{"class":252,"line":447},[250,5300,5301],{"class":782},"      unit_price REAL NOT NULL,\n",[250,5303,5304],{"class":252,"line":453},[250,5305,5306],{"class":782},"      FOREIGN KEY (order_id) REFERENCES orders(id),\n",[250,5308,5309],{"class":252,"line":459},[250,5310,5311],{"class":782},"      FOREIGN KEY (menu_item_id) REFERENCES menu_items(id)\n",[250,5313,5314],{"class":252,"line":465},[250,5315,2210],{"class":782},[250,5317,5318,5321],{"class":252,"line":471},[250,5319,5320],{"class":782},"  `",[250,5322,1885],{"class":912},[250,5324,5325],{"class":252,"line":2201},[250,5326,1053],{"class":912},[250,5328,5329,5331,5333,5335,5338],{"class":252,"line":2207},[250,5330,1856],{"class":912},[250,5332,1859],{"class":774},[250,5334,1434],{"class":912},[250,5336,5337],{"class":782},"\"✅ Database initialized\"",[250,5339,1885],{"class":912},[250,5341,5342],{"class":252,"line":2213},[250,5343,991],{"class":912},[72,5345],{},[31,5347,5349],{"id":5348},"step-5-seed-some-data","Step 5: Seed Some Data",[20,5351,5352],{},"Let's add an endpoint to populate our menu with sample data.",[20,5354,1092,5355,1007],{},[39,5356,5357],{},"server\u002Fapi\u002Fseed.post.ts",[47,5359,5361],{"className":1010,"code":5360,"filename":5357,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { menuItems } from \"..\u002Fdb\u002Fschema\";\n\nconst defaultMenuItems = [\n  { id: \"latte\", name: \"Latte\", description: \"Smooth espresso with steamed milk\", price: 4.5, category: \"coffee\" },\n  { id: \"espresso\", name: \"Espresso\", description: \"Rich, bold espresso shot\", price: 3.0, category: \"coffee\" },\n  { id: \"americano\", name: \"Americano\", description: \"Espresso with hot water\", price: 3.5, category: \"coffee\" },\n  { id: \"cappuccino\", name: \"Cappuccino\", description: \"Espresso with equal parts milk foam\", price: 4.5, category: \"coffee\" },\n  { id: \"chai\", name: \"Chai Tea\", description: \"Spiced black tea with milk\", price: 4.0, category: \"tea\" },\n  { id: \"green-tea\", name: \"Green Tea\", description: \"Organic Japanese green tea\", price: 3.5, category: \"tea\" },\n  { id: \"croissant\", name: \"Croissant\", description: \"Buttery French pastry\", price: 3.5, category: \"food\" },\n  { id: \"muffin\", name: \"Blueberry Muffin\", description: \"Freshly baked muffin\", price: 3.0, category: \"food\" },\n  { id: \"bagel\", name: \"Bagel with Cream Cheese\", description: \"Toasted bagel with cream cheese\", price: 4.0, category: \"food\" },\n];\n\nexport default defineEventHandler(async () => {\n  \u002F\u002F Clear existing menu items\n  await db.delete(menuItems).run();\n  \n  \u002F\u002F Insert default items\n  for (const item of defaultMenuItems) {\n    await db.insert(menuItems).values({\n      ...item,\n      available: true,\n    });\n  }\n  \n  return { message: \"Menu seeded successfully\", count: defaultMenuItems.length };\n});\n",[39,5362,5363,5377,5391,5395,5406,5433,5459,5486,5513,5539,5566,5592,5619,5646,5650,5654,5672,5677,5695,5699,5704,5721,5738,5746,5755,5759,5763,5767,5785],{"__ignoreMap":55},[250,5364,5365,5367,5370,5372,5375],{"class":252,"line":253},[250,5366,1763],{"class":786},[250,5368,5369],{"class":912}," { db } ",[250,5371,1769],{"class":786},[250,5373,5374],{"class":782}," \"..\u002Fdb\"",[250,5376,1379],{"class":912},[250,5378,5379,5381,5384,5386,5389],{"class":252,"line":113},[250,5380,1763],{"class":786},[250,5382,5383],{"class":912}," { menuItems } ",[250,5385,1769],{"class":786},[250,5387,5388],{"class":782}," \"..\u002Fdb\u002Fschema\"",[250,5390,1379],{"class":912},[250,5392,5393],{"class":252,"line":110},[250,5394,795],{"emptyLinePlaceholder":129},[250,5396,5397,5399,5402,5404],{"class":252,"line":269},[250,5398,1181],{"class":786},[250,5400,5401],{"class":778}," defaultMenuItems",[250,5403,1187],{"class":786},[250,5405,1190],{"class":912},[250,5407,5408,5410,5413,5415,5417,5420,5423,5425,5427,5429,5431],{"class":252,"line":275},[250,5409,1195],{"class":912},[250,5411,5412],{"class":782},"\"latte\"",[250,5414,1201],{"class":912},[250,5416,1204],{"class":782},[250,5418,5419],{"class":912},", description: ",[250,5421,5422],{"class":782},"\"Smooth espresso with steamed milk\"",[250,5424,1207],{"class":912},[250,5426,1210],{"class":778},[250,5428,1213],{"class":912},[250,5430,1216],{"class":782},[250,5432,1219],{"class":912},[250,5434,5435,5437,5440,5442,5444,5446,5449,5451,5453,5455,5457],{"class":252,"line":281},[250,5436,1195],{"class":912},[250,5438,5439],{"class":782},"\"espresso\"",[250,5441,1201],{"class":912},[250,5443,1231],{"class":782},[250,5445,5419],{"class":912},[250,5447,5448],{"class":782},"\"Rich, bold espresso shot\"",[250,5450,1207],{"class":912},[250,5452,1236],{"class":778},[250,5454,1213],{"class":912},[250,5456,1216],{"class":782},[250,5458,1219],{"class":912},[250,5460,5461,5463,5466,5468,5471,5473,5476,5478,5480,5482,5484],{"class":252,"line":287},[250,5462,1195],{"class":912},[250,5464,5465],{"class":782},"\"americano\"",[250,5467,1201],{"class":912},[250,5469,5470],{"class":782},"\"Americano\"",[250,5472,5419],{"class":912},[250,5474,5475],{"class":782},"\"Espresso with hot water\"",[250,5477,1207],{"class":912},[250,5479,1259],{"class":778},[250,5481,1213],{"class":912},[250,5483,1216],{"class":782},[250,5485,1219],{"class":912},[250,5487,5488,5490,5493,5495,5498,5500,5503,5505,5507,5509,5511],{"class":252,"line":293},[250,5489,1195],{"class":912},[250,5491,5492],{"class":782},"\"cappuccino\"",[250,5494,1201],{"class":912},[250,5496,5497],{"class":782},"\"Cappuccino\"",[250,5499,5419],{"class":912},[250,5501,5502],{"class":782},"\"Espresso with equal parts milk foam\"",[250,5504,1207],{"class":912},[250,5506,1210],{"class":778},[250,5508,1213],{"class":912},[250,5510,1216],{"class":782},[250,5512,1219],{"class":912},[250,5514,5515,5517,5520,5522,5524,5526,5529,5531,5533,5535,5537],{"class":252,"line":299},[250,5516,1195],{"class":912},[250,5518,5519],{"class":782},"\"chai\"",[250,5521,1201],{"class":912},[250,5523,1278],{"class":782},[250,5525,5419],{"class":912},[250,5527,5528],{"class":782},"\"Spiced black tea with milk\"",[250,5530,1207],{"class":912},[250,5532,1283],{"class":778},[250,5534,1213],{"class":912},[250,5536,1288],{"class":782},[250,5538,1219],{"class":912},[250,5540,5541,5543,5546,5548,5551,5553,5556,5558,5560,5562,5564],{"class":252,"line":132},[250,5542,1195],{"class":912},[250,5544,5545],{"class":782},"\"green-tea\"",[250,5547,1201],{"class":912},[250,5549,5550],{"class":782},"\"Green Tea\"",[250,5552,5419],{"class":912},[250,5554,5555],{"class":782},"\"Organic Japanese green tea\"",[250,5557,1207],{"class":912},[250,5559,1259],{"class":778},[250,5561,1213],{"class":912},[250,5563,1288],{"class":782},[250,5565,1219],{"class":912},[250,5567,5568,5570,5573,5575,5577,5579,5582,5584,5586,5588,5590],{"class":252,"line":310},[250,5569,1195],{"class":912},[250,5571,5572],{"class":782},"\"croissant\"",[250,5574,1201],{"class":912},[250,5576,1254],{"class":782},[250,5578,5419],{"class":912},[250,5580,5581],{"class":782},"\"Buttery French pastry\"",[250,5583,1207],{"class":912},[250,5585,1259],{"class":778},[250,5587,1213],{"class":912},[250,5589,1264],{"class":782},[250,5591,1219],{"class":912},[250,5593,5594,5596,5599,5601,5604,5606,5609,5611,5613,5615,5617],{"class":252,"line":316},[250,5595,1195],{"class":912},[250,5597,5598],{"class":782},"\"muffin\"",[250,5600,1201],{"class":912},[250,5602,5603],{"class":782},"\"Blueberry Muffin\"",[250,5605,5419],{"class":912},[250,5607,5608],{"class":782},"\"Freshly baked muffin\"",[250,5610,1207],{"class":912},[250,5612,1236],{"class":778},[250,5614,1213],{"class":912},[250,5616,1264],{"class":782},[250,5618,1219],{"class":912},[250,5620,5621,5623,5626,5628,5631,5633,5636,5638,5640,5642,5644],{"class":252,"line":322},[250,5622,1195],{"class":912},[250,5624,5625],{"class":782},"\"bagel\"",[250,5627,1201],{"class":912},[250,5629,5630],{"class":782},"\"Bagel with Cream Cheese\"",[250,5632,5419],{"class":912},[250,5634,5635],{"class":782},"\"Toasted bagel with cream cheese\"",[250,5637,1207],{"class":912},[250,5639,1283],{"class":778},[250,5641,1213],{"class":912},[250,5643,1264],{"class":782},[250,5645,1219],{"class":912},[250,5647,5648],{"class":252,"line":328},[250,5649,1317],{"class":912},[250,5651,5652],{"class":252,"line":334},[250,5653,795],{"emptyLinePlaceholder":129},[250,5655,5656,5658,5660,5662,5664,5666,5668,5670],{"class":252,"line":340},[250,5657,1019],{"class":786},[250,5659,1022],{"class":786},[250,5661,1109],{"class":774},[250,5663,1434],{"class":912},[250,5665,1437],{"class":786},[250,5667,2015],{"class":912},[250,5669,1115],{"class":786},[250,5671,1118],{"class":912},[250,5673,5674],{"class":252,"line":346},[250,5675,5676],{"class":768},"  \u002F\u002F Clear existing menu items\n",[250,5678,5679,5681,5684,5687,5690,5693],{"class":252,"line":352},[250,5680,1565],{"class":786},[250,5682,5683],{"class":912}," db.",[250,5685,5686],{"class":774},"delete",[250,5688,5689],{"class":912},"(menuItems).",[250,5691,5692],{"class":774},"run",[250,5694,1906],{"class":912},[250,5696,5697],{"class":252,"line":358},[250,5698,1053],{"class":912},[250,5700,5701],{"class":252,"line":364},[250,5702,5703],{"class":768},"  \u002F\u002F Insert default items\n",[250,5705,5706,5708,5710,5712,5715,5718],{"class":252,"line":370},[250,5707,1944],{"class":786},[250,5709,1440],{"class":912},[250,5711,1181],{"class":786},[250,5713,5714],{"class":778}," item",[250,5716,5717],{"class":786}," of",[250,5719,5720],{"class":912}," defaultMenuItems) {\n",[250,5722,5723,5726,5728,5731,5733,5736],{"class":252,"line":376},[250,5724,5725],{"class":786},"    await",[250,5727,5683],{"class":912},[250,5729,5730],{"class":774},"insert",[250,5732,5689],{"class":912},[250,5734,5735],{"class":774},"values",[250,5737,1028],{"class":912},[250,5739,5740,5743],{"class":252,"line":382},[250,5741,5742],{"class":786},"      ...",[250,5744,5745],{"class":912},"item,\n",[250,5747,5748,5751,5753],{"class":252,"line":388},[250,5749,5750],{"class":912},"      available: ",[250,5752,1066],{"class":778},[250,5754,927],{"class":912},[250,5756,5757],{"class":252,"line":393},[250,5758,1547],{"class":912},[250,5760,5761],{"class":252,"line":399},[250,5762,986],{"class":912},[250,5764,5765],{"class":252,"line":405},[250,5766,1053],{"class":912},[250,5768,5769,5771,5774,5777,5780,5782],{"class":252,"line":410},[250,5770,1123],{"class":786},[250,5772,5773],{"class":912}," { message: ",[250,5775,5776],{"class":782},"\"Menu seeded successfully\"",[250,5778,5779],{"class":912},", count: defaultMenuItems.",[250,5781,1503],{"class":778},[250,5783,5784],{"class":912}," };\n",[250,5786,5787],{"class":252,"line":415},[250,5788,1077],{"class":912},[72,5790],{},[31,5792,5794],{"id":5793},"step-6-create-api-endpoints","Step 6: Create API Endpoints",[2459,5796,5798],{"id":5797},"get-menu","Get Menu",[20,5800,1092,5801,1007],{},[39,5802,5803],{},"server\u002Fapi\u002Fmenu.get.ts",[47,5805,5807],{"className":1010,"code":5806,"filename":5803,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { menuItems } from \"..\u002Fdb\u002Fschema\";\n\nexport default defineEventHandler(async () => {\n  const items = await db.select().from(menuItems).where(menuItems.available);\n  return { items };\n});\n",[39,5808,5809,5821,5833,5837,5855,5883,5890],{"__ignoreMap":55},[250,5810,5811,5813,5815,5817,5819],{"class":252,"line":253},[250,5812,1763],{"class":786},[250,5814,5369],{"class":912},[250,5816,1769],{"class":786},[250,5818,5374],{"class":782},[250,5820,1379],{"class":912},[250,5822,5823,5825,5827,5829,5831],{"class":252,"line":113},[250,5824,1763],{"class":786},[250,5826,5383],{"class":912},[250,5828,1769],{"class":786},[250,5830,5388],{"class":782},[250,5832,1379],{"class":912},[250,5834,5835],{"class":252,"line":110},[250,5836,795],{"emptyLinePlaceholder":129},[250,5838,5839,5841,5843,5845,5847,5849,5851,5853],{"class":252,"line":269},[250,5840,1019],{"class":786},[250,5842,1022],{"class":786},[250,5844,1109],{"class":774},[250,5846,1434],{"class":912},[250,5848,1437],{"class":786},[250,5850,2015],{"class":912},[250,5852,1115],{"class":786},[250,5854,1118],{"class":912},[250,5856,5857,5859,5862,5864,5866,5868,5871,5873,5875,5877,5880],{"class":252,"line":275},[250,5858,1455],{"class":786},[250,5860,5861],{"class":778}," items",[250,5863,1187],{"class":786},[250,5865,1463],{"class":786},[250,5867,5683],{"class":912},[250,5869,5870],{"class":774},"select",[250,5872,1647],{"class":912},[250,5874,1769],{"class":774},[250,5876,5689],{"class":912},[250,5878,5879],{"class":774},"where",[250,5881,5882],{"class":912},"(menuItems.available);\n",[250,5884,5885,5887],{"class":252,"line":281},[250,5886,1123],{"class":786},[250,5888,5889],{"class":912}," { items };\n",[250,5891,5892],{"class":252,"line":287},[250,5893,1077],{"class":912},[2459,5895,5897],{"id":5896},"get-single-menu-item","Get Single Menu Item",[20,5899,1092,5900,1007],{},[39,5901,5902],{},"server\u002Fapi\u002Fmenu\u002F[id].get.ts",[47,5904,5906],{"className":1010,"code":5905,"filename":5902,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { menuItems } from \"..\u002Fdb\u002Fschema\";\n\nexport default defineEventHandler(async (event) => {\n  const id = getRouterParam(event, \"id\");\n  \n  if (!id) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Menu item ID is required\",\n    });\n  }\n  \n  const item = await db.select().from(menuItems).where(menuItems.id.equals(id)).get();\n  \n  if (!item) {\n    throw createError({\n      statusCode: 404,\n      statusMessage: \"Menu item not found\",\n    });\n  }\n  \n  return item;\n});\n",[39,5907,5908,5920,5932,5936,5958,5977,5981,5992,6000,6008,6017,6021,6025,6029,6065,6069,6080,6088,6097,6106,6110,6114,6118,6125],{"__ignoreMap":55},[250,5909,5910,5912,5914,5916,5918],{"class":252,"line":253},[250,5911,1763],{"class":786},[250,5913,5369],{"class":912},[250,5915,1769],{"class":786},[250,5917,5374],{"class":782},[250,5919,1379],{"class":912},[250,5921,5922,5924,5926,5928,5930],{"class":252,"line":113},[250,5923,1763],{"class":786},[250,5925,5383],{"class":912},[250,5927,1769],{"class":786},[250,5929,5388],{"class":782},[250,5931,1379],{"class":912},[250,5933,5934],{"class":252,"line":110},[250,5935,795],{"emptyLinePlaceholder":129},[250,5937,5938,5940,5942,5944,5946,5948,5950,5952,5954,5956],{"class":252,"line":269},[250,5939,1019],{"class":786},[250,5941,1022],{"class":786},[250,5943,1109],{"class":774},[250,5945,1434],{"class":912},[250,5947,1437],{"class":786},[250,5949,1440],{"class":912},[250,5951,1443],{"class":1370},[250,5953,1446],{"class":912},[250,5955,1115],{"class":786},[250,5957,1118],{"class":912},[250,5959,5960,5962,5965,5967,5970,5973,5975],{"class":252,"line":275},[250,5961,1455],{"class":786},[250,5963,5964],{"class":778}," id",[250,5966,1187],{"class":786},[250,5968,5969],{"class":774}," getRouterParam",[250,5971,5972],{"class":912},"(event, ",[250,5974,4466],{"class":782},[250,5976,1885],{"class":912},[250,5978,5979],{"class":252,"line":281},[250,5980,1053],{"class":912},[250,5982,5983,5985,5987,5989],{"class":252,"line":287},[250,5984,1486],{"class":786},[250,5986,1440],{"class":912},[250,5988,1491],{"class":786},[250,5990,5991],{"class":912},"id) {\n",[250,5993,5994,5996,5998],{"class":252,"line":293},[250,5995,1517],{"class":786},[250,5997,1520],{"class":774},[250,5999,1028],{"class":912},[250,6001,6002,6004,6006],{"class":252,"line":299},[250,6003,1527],{"class":912},[250,6005,1530],{"class":778},[250,6007,927],{"class":912},[250,6009,6010,6012,6015],{"class":252,"line":132},[250,6011,1537],{"class":912},[250,6013,6014],{"class":782},"\"Menu item ID is required\"",[250,6016,927],{"class":912},[250,6018,6019],{"class":252,"line":310},[250,6020,1547],{"class":912},[250,6022,6023],{"class":252,"line":316},[250,6024,986],{"class":912},[250,6026,6027],{"class":252,"line":322},[250,6028,1053],{"class":912},[250,6030,6031,6033,6035,6037,6039,6041,6043,6045,6047,6049,6051,6054,6057,6060,6063],{"class":252,"line":328},[250,6032,1455],{"class":786},[250,6034,5714],{"class":778},[250,6036,1187],{"class":786},[250,6038,1463],{"class":786},[250,6040,5683],{"class":912},[250,6042,5870],{"class":774},[250,6044,1647],{"class":912},[250,6046,1769],{"class":774},[250,6048,5689],{"class":912},[250,6050,5879],{"class":774},[250,6052,6053],{"class":912},"(menuItems.id.",[250,6055,6056],{"class":774},"equals",[250,6058,6059],{"class":912},"(id)).",[250,6061,6062],{"class":774},"get",[250,6064,1906],{"class":912},[250,6066,6067],{"class":252,"line":334},[250,6068,1053],{"class":912},[250,6070,6071,6073,6075,6077],{"class":252,"line":340},[250,6072,1486],{"class":786},[250,6074,1440],{"class":912},[250,6076,1491],{"class":786},[250,6078,6079],{"class":912},"item) {\n",[250,6081,6082,6084,6086],{"class":252,"line":346},[250,6083,1517],{"class":786},[250,6085,1520],{"class":774},[250,6087,1028],{"class":912},[250,6089,6090,6092,6095],{"class":252,"line":352},[250,6091,1527],{"class":912},[250,6093,6094],{"class":778},"404",[250,6096,927],{"class":912},[250,6098,6099,6101,6104],{"class":252,"line":358},[250,6100,1537],{"class":912},[250,6102,6103],{"class":782},"\"Menu item not found\"",[250,6105,927],{"class":912},[250,6107,6108],{"class":252,"line":364},[250,6109,1547],{"class":912},[250,6111,6112],{"class":252,"line":370},[250,6113,986],{"class":912},[250,6115,6116],{"class":252,"line":376},[250,6117,1053],{"class":912},[250,6119,6120,6122],{"class":252,"line":382},[250,6121,1123],{"class":786},[250,6123,6124],{"class":912}," item;\n",[250,6126,6127],{"class":252,"line":388},[250,6128,1077],{"class":912},[2459,6130,6132],{"id":6131},"create-order","Create Order",[20,6134,6135],{},"This is where Drizzle really shines—let's create a proper order with related items.",[20,6137,1092,6138,1007],{},[39,6139,1353],{},[47,6141,6143],{"className":1010,"code":6142,"filename":1353,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { orders, orderItems, menuItems } from \"..\u002Fdb\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\n\ninterface OrderItemInput {\n  menuItemId: string;\n  quantity: number;\n}\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event);\n  \n  \u002F\u002F Validate input\n  if (!body.items || !Array.isArray(body.items) || body.items.length === 0) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Order must contain at least one item\",\n    });\n  }\n  \n  \u002F\u002F Calculate total and fetch menu item prices\n  let total = 0;\n  const orderItemInputs: OrderItemInput[] = [];\n  \n  for (const item of body.items) {\n    const menuItem = await db\n      .select()\n      .from(menuItems)\n      .where(eq(menuItems.id, item.menuItemId))\n      .get();\n    \n    if (!menuItem) {\n      throw createError({\n        statusCode: 400,\n        statusMessage: `Menu item ${item.menuItemId} not found`,\n      });\n    }\n    \n    if (!menuItem.available) {\n      throw createError({\n        statusCode: 400,\n        statusMessage: `Menu item ${menuItem.name} is not available`,\n      });\n    }\n    \n    total += menuItem.price * item.quantity;\n    orderItemInputs.push({\n      menuItemId: item.menuItemId,\n      quantity: item.quantity,\n    });\n  }\n  \n  \u002F\u002F Create the order\n  const orderId = crypto.randomUUID();\n  const now = Date.now();\n  \n  await db.insert(orders).values({\n    id: orderId,\n    customerName: body.customerName || \"Guest\",\n    status: \"pending\",\n    total,\n    createdAt: new Date(now),\n    updatedAt: new Date(now),\n  });\n  \n  \u002F\u002F Create order items\n  for (const input of orderItemInputs) {\n    const menuItem = await db\n      .select()\n      .from(menuItems)\n      .where(eq(menuItems.id, input.menuItemId))\n      .get();\n    \n    await db.insert(orderItems).values({\n      id: crypto.randomUUID(),\n      orderId,\n      menuItemId: input.menuItemId,\n      quantity: input.quantity,\n      unitPrice: menuItem!.price,\n    });\n  }\n  \n  \u002F\u002F Fetch the complete order\n  const createdOrder = await db\n    .select()\n    .from(orders)\n    .where(eq(orders.id, orderId))\n    .get();\n  \n  const items = await db\n    .select()\n    .from(orderItems)\n    .where(eq(orderItems.orderId, orderId));\n  \n  return {\n    ...createdOrder,\n    items,\n  };\n});\n",[39,6144,6145,6157,6170,6183,6187,6196,6207,6217,6221,6225,6247,6262,6266,6271,6309,6317,6325,6333,6337,6341,6345,6350,6363,6380,6384,6399,6414,6423,6432,6446,6454,6459,6471,6480,6489,6510,6515,6519,6523,6534,6542,6550,6569,6573,6577,6581,6598,6607,6612,6617,6621,6625,6629,6634,6650,6665,6670,6686,6692,6705,6714,6720,6732,6744,6750,6755,6761,6778,6791,6800,6809,6823,6832,6837,6853,6863,6869,6875,6881,6892,6897,6902,6907,6913,6927,6936,6946,6960,6969,6974,6987,6996,7006,7020,7025,7032,7041,7047,7052],{"__ignoreMap":55},[250,6146,6147,6149,6151,6153,6155],{"class":252,"line":253},[250,6148,1763],{"class":786},[250,6150,5369],{"class":912},[250,6152,1769],{"class":786},[250,6154,5374],{"class":782},[250,6156,1379],{"class":912},[250,6158,6159,6161,6164,6166,6168],{"class":252,"line":113},[250,6160,1763],{"class":786},[250,6162,6163],{"class":912}," { orders, orderItems, menuItems } ",[250,6165,1769],{"class":786},[250,6167,5388],{"class":782},[250,6169,1379],{"class":912},[250,6171,6172,6174,6177,6179,6181],{"class":252,"line":110},[250,6173,1763],{"class":786},[250,6175,6176],{"class":912}," { eq } ",[250,6178,1769],{"class":786},[250,6180,4420],{"class":782},[250,6182,1379],{"class":912},[250,6184,6185],{"class":252,"line":269},[250,6186,795],{"emptyLinePlaceholder":129},[250,6188,6189,6191,6194],{"class":252,"line":275},[250,6190,1360],{"class":786},[250,6192,6193],{"class":774}," OrderItemInput",[250,6195,1118],{"class":912},[250,6197,6198,6201,6203,6205],{"class":252,"line":281},[250,6199,6200],{"class":1370},"  menuItemId",[250,6202,1007],{"class":786},[250,6204,2506],{"class":778},[250,6206,1379],{"class":912},[250,6208,6209,6211,6213,6215],{"class":252,"line":287},[250,6210,1384],{"class":1370},[250,6212,1007],{"class":786},[250,6214,1376],{"class":778},[250,6216,1379],{"class":912},[250,6218,6219],{"class":252,"line":293},[250,6220,991],{"class":912},[250,6222,6223],{"class":252,"line":299},[250,6224,795],{"emptyLinePlaceholder":129},[250,6226,6227,6229,6231,6233,6235,6237,6239,6241,6243,6245],{"class":252,"line":132},[250,6228,1019],{"class":786},[250,6230,1022],{"class":786},[250,6232,1109],{"class":774},[250,6234,1434],{"class":912},[250,6236,1437],{"class":786},[250,6238,1440],{"class":912},[250,6240,1443],{"class":1370},[250,6242,1446],{"class":912},[250,6244,1115],{"class":786},[250,6246,1118],{"class":912},[250,6248,6249,6251,6253,6255,6257,6259],{"class":252,"line":310},[250,6250,1455],{"class":786},[250,6252,1458],{"class":778},[250,6254,1187],{"class":786},[250,6256,1463],{"class":786},[250,6258,1466],{"class":774},[250,6260,6261],{"class":912},"(event);\n",[250,6263,6264],{"class":252,"line":316},[250,6265,1053],{"class":912},[250,6267,6268],{"class":252,"line":322},[250,6269,6270],{"class":768},"  \u002F\u002F Validate input\n",[250,6272,6273,6275,6277,6279,6282,6284,6287,6290,6293,6296,6298,6301,6303,6305,6307],{"class":252,"line":328},[250,6274,1486],{"class":786},[250,6276,1440],{"class":912},[250,6278,1491],{"class":786},[250,6280,6281],{"class":912},"body.items ",[250,6283,1497],{"class":786},[250,6285,6286],{"class":786}," !",[250,6288,6289],{"class":912},"Array.",[250,6291,6292],{"class":774},"isArray",[250,6294,6295],{"class":912},"(body.items) ",[250,6297,1497],{"class":786},[250,6299,6300],{"class":912}," body.items.",[250,6302,1503],{"class":778},[250,6304,1506],{"class":786},[250,6306,1509],{"class":778},[250,6308,1512],{"class":912},[250,6310,6311,6313,6315],{"class":252,"line":334},[250,6312,1517],{"class":786},[250,6314,1520],{"class":774},[250,6316,1028],{"class":912},[250,6318,6319,6321,6323],{"class":252,"line":340},[250,6320,1527],{"class":912},[250,6322,1530],{"class":778},[250,6324,927],{"class":912},[250,6326,6327,6329,6331],{"class":252,"line":346},[250,6328,1537],{"class":912},[250,6330,1540],{"class":782},[250,6332,927],{"class":912},[250,6334,6335],{"class":252,"line":352},[250,6336,1547],{"class":912},[250,6338,6339],{"class":252,"line":358},[250,6340,986],{"class":912},[250,6342,6343],{"class":252,"line":364},[250,6344,1053],{"class":912},[250,6346,6347],{"class":252,"line":370},[250,6348,6349],{"class":768},"  \u002F\u002F Calculate total and fetch menu item prices\n",[250,6351,6352,6354,6357,6359,6361],{"class":252,"line":376},[250,6353,1911],{"class":786},[250,6355,6356],{"class":912}," total ",[250,6358,1416],{"class":786},[250,6360,1509],{"class":778},[250,6362,1379],{"class":912},[250,6364,6365,6367,6370,6372,6374,6376,6378],{"class":252,"line":382},[250,6366,1455],{"class":786},[250,6368,6369],{"class":778}," orderItemInputs",[250,6371,1007],{"class":786},[250,6373,6193],{"class":774},[250,6375,1413],{"class":912},[250,6377,1416],{"class":786},[250,6379,1419],{"class":912},[250,6381,6382],{"class":252,"line":388},[250,6383,1053],{"class":912},[250,6385,6386,6388,6390,6392,6394,6396],{"class":252,"line":393},[250,6387,1944],{"class":786},[250,6389,1440],{"class":912},[250,6391,1181],{"class":786},[250,6393,5714],{"class":778},[250,6395,5717],{"class":786},[250,6397,6398],{"class":912}," body.items) {\n",[250,6400,6401,6404,6407,6409,6411],{"class":252,"line":399},[250,6402,6403],{"class":786},"    const",[250,6405,6406],{"class":778}," menuItem",[250,6408,1187],{"class":786},[250,6410,1463],{"class":786},[250,6412,6413],{"class":912}," db\n",[250,6415,6416,6419,6421],{"class":252,"line":405},[250,6417,6418],{"class":912},"      .",[250,6420,5870],{"class":774},[250,6422,4861],{"class":912},[250,6424,6425,6427,6429],{"class":252,"line":410},[250,6426,6418],{"class":912},[250,6428,1769],{"class":774},[250,6430,6431],{"class":912},"(menuItems)\n",[250,6433,6434,6436,6438,6440,6443],{"class":252,"line":415},[250,6435,6418],{"class":912},[250,6437,5879],{"class":774},[250,6439,1434],{"class":912},[250,6441,6442],{"class":774},"eq",[250,6444,6445],{"class":912},"(menuItems.id, item.menuItemId))\n",[250,6447,6448,6450,6452],{"class":252,"line":420},[250,6449,6418],{"class":912},[250,6451,6062],{"class":774},[250,6453,1906],{"class":912},[250,6455,6456],{"class":252,"line":426},[250,6457,6458],{"class":912},"    \n",[250,6460,6461,6464,6466,6468],{"class":252,"line":431},[250,6462,6463],{"class":786},"    if",[250,6465,1440],{"class":912},[250,6467,1491],{"class":786},[250,6469,6470],{"class":912},"menuItem) {\n",[250,6472,6473,6476,6478],{"class":252,"line":436},[250,6474,6475],{"class":786},"      throw",[250,6477,1520],{"class":774},[250,6479,1028],{"class":912},[250,6481,6482,6485,6487],{"class":252,"line":442},[250,6483,6484],{"class":912},"        statusCode: ",[250,6486,1530],{"class":778},[250,6488,927],{"class":912},[250,6490,6491,6494,6497,6500,6502,6505,6508],{"class":252,"line":447},[250,6492,6493],{"class":912},"        statusMessage: ",[250,6495,6496],{"class":782},"`Menu item ${",[250,6498,6499],{"class":912},"item",[250,6501,2230],{"class":782},[250,6503,6504],{"class":912},"menuItemId",[250,6506,6507],{"class":782},"} not found`",[250,6509,927],{"class":912},[250,6511,6512],{"class":252,"line":453},[250,6513,6514],{"class":912},"      });\n",[250,6516,6517],{"class":252,"line":459},[250,6518,3684],{"class":912},[250,6520,6521],{"class":252,"line":465},[250,6522,6458],{"class":912},[250,6524,6525,6527,6529,6531],{"class":252,"line":471},[250,6526,6463],{"class":786},[250,6528,1440],{"class":912},[250,6530,1491],{"class":786},[250,6532,6533],{"class":912},"menuItem.available) {\n",[250,6535,6536,6538,6540],{"class":252,"line":2201},[250,6537,6475],{"class":786},[250,6539,1520],{"class":774},[250,6541,1028],{"class":912},[250,6543,6544,6546,6548],{"class":252,"line":2207},[250,6545,6484],{"class":912},[250,6547,1530],{"class":778},[250,6549,927],{"class":912},[250,6551,6552,6554,6556,6559,6561,6564,6567],{"class":252,"line":2213},[250,6553,6493],{"class":912},[250,6555,6496],{"class":782},[250,6557,6558],{"class":912},"menuItem",[250,6560,2230],{"class":782},[250,6562,6563],{"class":912},"name",[250,6565,6566],{"class":782},"} is not available`",[250,6568,927],{"class":912},[250,6570,6571],{"class":252,"line":2218},[250,6572,6514],{"class":912},[250,6574,6575],{"class":252,"line":2223},[250,6576,3684],{"class":912},[250,6578,6579],{"class":252,"line":2239},[250,6580,6458],{"class":912},[250,6582,6583,6586,6589,6592,6595],{"class":252,"line":2244},[250,6584,6585],{"class":912},"    total ",[250,6587,6588],{"class":786},"+=",[250,6590,6591],{"class":912}," menuItem.price ",[250,6593,6594],{"class":786},"*",[250,6596,6597],{"class":912}," item.quantity;\n",[250,6599,6600,6603,6605],{"class":252,"line":2267},[250,6601,6602],{"class":912},"    orderItemInputs.",[250,6604,1668],{"class":774},[250,6606,1028],{"class":912},[250,6608,6609],{"class":252,"line":2301},[250,6610,6611],{"class":912},"      menuItemId: item.menuItemId,\n",[250,6613,6614],{"class":252,"line":2306},[250,6615,6616],{"class":912},"      quantity: item.quantity,\n",[250,6618,6619],{"class":252,"line":2320},[250,6620,1547],{"class":912},[250,6622,6623],{"class":252,"line":2340},[250,6624,986],{"class":912},[250,6626,6627],{"class":252,"line":2360},[250,6628,1053],{"class":912},[250,6630,6631],{"class":252,"line":2397},[250,6632,6633],{"class":768},"  \u002F\u002F Create the order\n",[250,6635,6636,6638,6641,6643,6646,6648],{"class":252,"line":2402},[250,6637,1455],{"class":786},[250,6639,6640],{"class":778}," orderId",[250,6642,1187],{"class":786},[250,6644,6645],{"class":912}," crypto.",[250,6647,1616],{"class":774},[250,6649,1906],{"class":912},[250,6651,6652,6654,6657,6659,6661,6663],{"class":252,"line":2407},[250,6653,1455],{"class":786},[250,6655,6656],{"class":778}," now",[250,6658,1187],{"class":786},[250,6660,1901],{"class":912},[250,6662,1153],{"class":774},[250,6664,1906],{"class":912},[250,6666,6668],{"class":252,"line":6667},56,[250,6669,1053],{"class":912},[250,6671,6673,6675,6677,6679,6682,6684],{"class":252,"line":6672},57,[250,6674,1565],{"class":786},[250,6676,5683],{"class":912},[250,6678,5730],{"class":774},[250,6680,6681],{"class":912},"(orders).",[250,6683,5735],{"class":774},[250,6685,1028],{"class":912},[250,6687,6689],{"class":252,"line":6688},58,[250,6690,6691],{"class":912},"    id: orderId,\n",[250,6693,6695,6698,6700,6703],{"class":252,"line":6694},59,[250,6696,6697],{"class":912},"    customerName: body.customerName ",[250,6699,1497],{"class":786},[250,6701,6702],{"class":782}," \"Guest\"",[250,6704,927],{"class":912},[250,6706,6708,6710,6712],{"class":252,"line":6707},60,[250,6709,1628],{"class":912},[250,6711,1631],{"class":782},[250,6713,927],{"class":912},[250,6715,6717],{"class":252,"line":6716},61,[250,6718,6719],{"class":912},"    total,\n",[250,6721,6723,6725,6727,6729],{"class":252,"line":6722},62,[250,6724,1638],{"class":912},[250,6726,1641],{"class":786},[250,6728,1644],{"class":774},[250,6730,6731],{"class":912},"(now),\n",[250,6733,6735,6738,6740,6742],{"class":252,"line":6734},63,[250,6736,6737],{"class":912},"    updatedAt: ",[250,6739,1641],{"class":786},[250,6741,1644],{"class":774},[250,6743,6731],{"class":912},[250,6745,6747],{"class":252,"line":6746},64,[250,6748,6749],{"class":912},"  });\n",[250,6751,6753],{"class":252,"line":6752},65,[250,6754,1053],{"class":912},[250,6756,6758],{"class":252,"line":6757},66,[250,6759,6760],{"class":768},"  \u002F\u002F Create order items\n",[250,6762,6764,6766,6768,6770,6773,6775],{"class":252,"line":6763},67,[250,6765,1944],{"class":786},[250,6767,1440],{"class":912},[250,6769,1181],{"class":786},[250,6771,6772],{"class":778}," input",[250,6774,5717],{"class":786},[250,6776,6777],{"class":912}," orderItemInputs) {\n",[250,6779,6781,6783,6785,6787,6789],{"class":252,"line":6780},68,[250,6782,6403],{"class":786},[250,6784,6406],{"class":778},[250,6786,1187],{"class":786},[250,6788,1463],{"class":786},[250,6790,6413],{"class":912},[250,6792,6794,6796,6798],{"class":252,"line":6793},69,[250,6795,6418],{"class":912},[250,6797,5870],{"class":774},[250,6799,4861],{"class":912},[250,6801,6803,6805,6807],{"class":252,"line":6802},70,[250,6804,6418],{"class":912},[250,6806,1769],{"class":774},[250,6808,6431],{"class":912},[250,6810,6812,6814,6816,6818,6820],{"class":252,"line":6811},71,[250,6813,6418],{"class":912},[250,6815,5879],{"class":774},[250,6817,1434],{"class":912},[250,6819,6442],{"class":774},[250,6821,6822],{"class":912},"(menuItems.id, input.menuItemId))\n",[250,6824,6826,6828,6830],{"class":252,"line":6825},72,[250,6827,6418],{"class":912},[250,6829,6062],{"class":774},[250,6831,1906],{"class":912},[250,6833,6835],{"class":252,"line":6834},73,[250,6836,6458],{"class":912},[250,6838,6840,6842,6844,6846,6849,6851],{"class":252,"line":6839},74,[250,6841,5725],{"class":786},[250,6843,5683],{"class":912},[250,6845,5730],{"class":774},[250,6847,6848],{"class":912},"(orderItems).",[250,6850,5735],{"class":774},[250,6852,1028],{"class":912},[250,6854,6856,6859,6861],{"class":252,"line":6855},75,[250,6857,6858],{"class":912},"      id: crypto.",[250,6860,1616],{"class":774},[250,6862,1156],{"class":912},[250,6864,6866],{"class":252,"line":6865},76,[250,6867,6868],{"class":912},"      orderId,\n",[250,6870,6872],{"class":252,"line":6871},77,[250,6873,6874],{"class":912},"      menuItemId: input.menuItemId,\n",[250,6876,6878],{"class":252,"line":6877},78,[250,6879,6880],{"class":912},"      quantity: input.quantity,\n",[250,6882,6884,6887,6889],{"class":252,"line":6883},79,[250,6885,6886],{"class":912},"      unitPrice: menuItem",[250,6888,1491],{"class":786},[250,6890,6891],{"class":912},".price,\n",[250,6893,6895],{"class":252,"line":6894},80,[250,6896,1547],{"class":912},[250,6898,6900],{"class":252,"line":6899},81,[250,6901,986],{"class":912},[250,6903,6905],{"class":252,"line":6904},82,[250,6906,1053],{"class":912},[250,6908,6910],{"class":252,"line":6909},83,[250,6911,6912],{"class":768},"  \u002F\u002F Fetch the complete order\n",[250,6914,6916,6918,6921,6923,6925],{"class":252,"line":6915},84,[250,6917,1455],{"class":786},[250,6919,6920],{"class":778}," createdOrder",[250,6922,1187],{"class":786},[250,6924,1463],{"class":786},[250,6926,6413],{"class":912},[250,6928,6930,6932,6934],{"class":252,"line":6929},85,[250,6931,4604],{"class":912},[250,6933,5870],{"class":774},[250,6935,4861],{"class":912},[250,6937,6939,6941,6943],{"class":252,"line":6938},86,[250,6940,4604],{"class":912},[250,6942,1769],{"class":774},[250,6944,6945],{"class":912},"(orders)\n",[250,6947,6949,6951,6953,6955,6957],{"class":252,"line":6948},87,[250,6950,4604],{"class":912},[250,6952,5879],{"class":774},[250,6954,1434],{"class":912},[250,6956,6442],{"class":774},[250,6958,6959],{"class":912},"(orders.id, orderId))\n",[250,6961,6963,6965,6967],{"class":252,"line":6962},88,[250,6964,4604],{"class":912},[250,6966,6062],{"class":774},[250,6968,1906],{"class":912},[250,6970,6972],{"class":252,"line":6971},89,[250,6973,1053],{"class":912},[250,6975,6977,6979,6981,6983,6985],{"class":252,"line":6976},90,[250,6978,1455],{"class":786},[250,6980,5861],{"class":778},[250,6982,1187],{"class":786},[250,6984,1463],{"class":786},[250,6986,6413],{"class":912},[250,6988,6990,6992,6994],{"class":252,"line":6989},91,[250,6991,4604],{"class":912},[250,6993,5870],{"class":774},[250,6995,4861],{"class":912},[250,6997,6999,7001,7003],{"class":252,"line":6998},92,[250,7000,4604],{"class":912},[250,7002,1769],{"class":774},[250,7004,7005],{"class":912},"(orderItems)\n",[250,7007,7009,7011,7013,7015,7017],{"class":252,"line":7008},93,[250,7010,4604],{"class":912},[250,7012,5879],{"class":774},[250,7014,1434],{"class":912},[250,7016,6442],{"class":774},[250,7018,7019],{"class":912},"(orderItems.orderId, orderId));\n",[250,7021,7023],{"class":252,"line":7022},94,[250,7024,1053],{"class":912},[250,7026,7028,7030],{"class":252,"line":7027},95,[250,7029,1123],{"class":786},[250,7031,1118],{"class":912},[250,7033,7035,7038],{"class":252,"line":7034},96,[250,7036,7037],{"class":786},"    ...",[250,7039,7040],{"class":912},"createdOrder,\n",[250,7042,7044],{"class":252,"line":7043},97,[250,7045,7046],{"class":912},"    items,\n",[250,7048,7050],{"class":252,"line":7049},98,[250,7051,1161],{"class":912},[250,7053,7055],{"class":252,"line":7054},99,[250,7056,1077],{"class":912},[2459,7058,7060],{"id":7059},"update-order-status","Update Order Status",[20,7062,1092,7063,1007],{},[39,7064,7065],{},"server\u002Fapi\u002Forders\u002F[id].patch.ts",[47,7067,7069],{"className":1010,"code":7068,"filename":7065,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { orders } from \"..\u002Fdb\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\n\nconst validStatuses = [\"pending\", \"preparing\", \"ready\", \"completed\", \"cancelled\"];\n\nexport default defineEventHandler(async (event) => {\n  const id = getRouterParam(event, \"id\");\n  const body = await readBody(event);\n  \n  if (!id) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Order ID is required\",\n    });\n  }\n  \n  if (!body.status || !validStatuses.includes(body.status)) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: `Invalid status. Must be one of: ${validStatuses.join(\", \")}`,\n    });\n  }\n  \n  const existingOrder = await db\n    .select()\n    .from(orders)\n    .where(eq(orders.id, id))\n    .get();\n  \n  if (!existingOrder) {\n    throw createError({\n      statusCode: 404,\n      statusMessage: \"Order not found\",\n    });\n  }\n  \n  \u002F\u002F Update the order\n  await db\n    .update(orders)\n    .set({\n      status: body.status,\n      updatedAt: new Date(),\n    })\n    .where(eq(orders.id, id));\n  \n  const updatedOrder = await db\n    .select()\n    .from(orders)\n    .where(eq(orders.id, id))\n    .get();\n  \n  return updatedOrder;\n});\n",[39,7070,7071,7083,7096,7108,7112,7149,7153,7175,7191,7205,7209,7219,7227,7235,7244,7248,7252,7256,7280,7288,7296,7322,7326,7330,7334,7347,7355,7363,7376,7384,7388,7399,7407,7415,7424,7428,7432,7436,7441,7447,7456,7465,7470,7481,7486,7499,7503,7516,7524,7532,7544,7552,7556,7563],{"__ignoreMap":55},[250,7072,7073,7075,7077,7079,7081],{"class":252,"line":253},[250,7074,1763],{"class":786},[250,7076,5369],{"class":912},[250,7078,1769],{"class":786},[250,7080,5374],{"class":782},[250,7082,1379],{"class":912},[250,7084,7085,7087,7090,7092,7094],{"class":252,"line":113},[250,7086,1763],{"class":786},[250,7088,7089],{"class":912}," { orders } ",[250,7091,1769],{"class":786},[250,7093,5388],{"class":782},[250,7095,1379],{"class":912},[250,7097,7098,7100,7102,7104,7106],{"class":252,"line":110},[250,7099,1763],{"class":786},[250,7101,6176],{"class":912},[250,7103,1769],{"class":786},[250,7105,4420],{"class":782},[250,7107,1379],{"class":912},[250,7109,7110],{"class":252,"line":269},[250,7111,795],{"emptyLinePlaceholder":129},[250,7113,7114,7116,7119,7121,7124,7126,7129,7132,7134,7137,7139,7142,7144,7147],{"class":252,"line":275},[250,7115,1181],{"class":786},[250,7117,7118],{"class":778}," validStatuses",[250,7120,1187],{"class":786},[250,7122,7123],{"class":912}," [",[250,7125,1631],{"class":782},[250,7127,7128],{"class":912},", ",[250,7130,7131],{"class":782},"\"preparing\"",[250,7133,7128],{"class":912},[250,7135,7136],{"class":782},"\"ready\"",[250,7138,7128],{"class":912},[250,7140,7141],{"class":782},"\"completed\"",[250,7143,7128],{"class":912},[250,7145,7146],{"class":782},"\"cancelled\"",[250,7148,1317],{"class":912},[250,7150,7151],{"class":252,"line":281},[250,7152,795],{"emptyLinePlaceholder":129},[250,7154,7155,7157,7159,7161,7163,7165,7167,7169,7171,7173],{"class":252,"line":287},[250,7156,1019],{"class":786},[250,7158,1022],{"class":786},[250,7160,1109],{"class":774},[250,7162,1434],{"class":912},[250,7164,1437],{"class":786},[250,7166,1440],{"class":912},[250,7168,1443],{"class":1370},[250,7170,1446],{"class":912},[250,7172,1115],{"class":786},[250,7174,1118],{"class":912},[250,7176,7177,7179,7181,7183,7185,7187,7189],{"class":252,"line":293},[250,7178,1455],{"class":786},[250,7180,5964],{"class":778},[250,7182,1187],{"class":786},[250,7184,5969],{"class":774},[250,7186,5972],{"class":912},[250,7188,4466],{"class":782},[250,7190,1885],{"class":912},[250,7192,7193,7195,7197,7199,7201,7203],{"class":252,"line":299},[250,7194,1455],{"class":786},[250,7196,1458],{"class":778},[250,7198,1187],{"class":786},[250,7200,1463],{"class":786},[250,7202,1466],{"class":774},[250,7204,6261],{"class":912},[250,7206,7207],{"class":252,"line":132},[250,7208,1053],{"class":912},[250,7210,7211,7213,7215,7217],{"class":252,"line":310},[250,7212,1486],{"class":786},[250,7214,1440],{"class":912},[250,7216,1491],{"class":786},[250,7218,5991],{"class":912},[250,7220,7221,7223,7225],{"class":252,"line":316},[250,7222,1517],{"class":786},[250,7224,1520],{"class":774},[250,7226,1028],{"class":912},[250,7228,7229,7231,7233],{"class":252,"line":322},[250,7230,1527],{"class":912},[250,7232,1530],{"class":778},[250,7234,927],{"class":912},[250,7236,7237,7239,7242],{"class":252,"line":328},[250,7238,1537],{"class":912},[250,7240,7241],{"class":782},"\"Order ID is required\"",[250,7243,927],{"class":912},[250,7245,7246],{"class":252,"line":334},[250,7247,1547],{"class":912},[250,7249,7250],{"class":252,"line":340},[250,7251,986],{"class":912},[250,7253,7254],{"class":252,"line":346},[250,7255,1053],{"class":912},[250,7257,7258,7260,7262,7264,7267,7269,7271,7274,7277],{"class":252,"line":352},[250,7259,1486],{"class":786},[250,7261,1440],{"class":912},[250,7263,1491],{"class":786},[250,7265,7266],{"class":912},"body.status ",[250,7268,1497],{"class":786},[250,7270,6286],{"class":786},[250,7272,7273],{"class":912},"validStatuses.",[250,7275,7276],{"class":774},"includes",[250,7278,7279],{"class":912},"(body.status)) {\n",[250,7281,7282,7284,7286],{"class":252,"line":358},[250,7283,1517],{"class":786},[250,7285,1520],{"class":774},[250,7287,1028],{"class":912},[250,7289,7290,7292,7294],{"class":252,"line":364},[250,7291,1527],{"class":912},[250,7293,1530],{"class":778},[250,7295,927],{"class":912},[250,7297,7298,7300,7303,7306,7308,7311,7313,7316,7318,7320],{"class":252,"line":370},[250,7299,1537],{"class":912},[250,7301,7302],{"class":782},"`Invalid status. Must be one of: ${",[250,7304,7305],{"class":912},"validStatuses",[250,7307,2230],{"class":782},[250,7309,7310],{"class":774},"join",[250,7312,1434],{"class":782},[250,7314,7315],{"class":782},"\", \"",[250,7317,2390],{"class":782},[250,7319,2355],{"class":782},[250,7321,927],{"class":912},[250,7323,7324],{"class":252,"line":376},[250,7325,1547],{"class":912},[250,7327,7328],{"class":252,"line":382},[250,7329,986],{"class":912},[250,7331,7332],{"class":252,"line":388},[250,7333,1053],{"class":912},[250,7335,7336,7338,7341,7343,7345],{"class":252,"line":393},[250,7337,1455],{"class":786},[250,7339,7340],{"class":778}," existingOrder",[250,7342,1187],{"class":786},[250,7344,1463],{"class":786},[250,7346,6413],{"class":912},[250,7348,7349,7351,7353],{"class":252,"line":399},[250,7350,4604],{"class":912},[250,7352,5870],{"class":774},[250,7354,4861],{"class":912},[250,7356,7357,7359,7361],{"class":252,"line":405},[250,7358,4604],{"class":912},[250,7360,1769],{"class":774},[250,7362,6945],{"class":912},[250,7364,7365,7367,7369,7371,7373],{"class":252,"line":410},[250,7366,4604],{"class":912},[250,7368,5879],{"class":774},[250,7370,1434],{"class":912},[250,7372,6442],{"class":774},[250,7374,7375],{"class":912},"(orders.id, id))\n",[250,7377,7378,7380,7382],{"class":252,"line":415},[250,7379,4604],{"class":912},[250,7381,6062],{"class":774},[250,7383,1906],{"class":912},[250,7385,7386],{"class":252,"line":420},[250,7387,1053],{"class":912},[250,7389,7390,7392,7394,7396],{"class":252,"line":426},[250,7391,1486],{"class":786},[250,7393,1440],{"class":912},[250,7395,1491],{"class":786},[250,7397,7398],{"class":912},"existingOrder) {\n",[250,7400,7401,7403,7405],{"class":252,"line":431},[250,7402,1517],{"class":786},[250,7404,1520],{"class":774},[250,7406,1028],{"class":912},[250,7408,7409,7411,7413],{"class":252,"line":436},[250,7410,1527],{"class":912},[250,7412,6094],{"class":778},[250,7414,927],{"class":912},[250,7416,7417,7419,7422],{"class":252,"line":442},[250,7418,1537],{"class":912},[250,7420,7421],{"class":782},"\"Order not found\"",[250,7423,927],{"class":912},[250,7425,7426],{"class":252,"line":447},[250,7427,1547],{"class":912},[250,7429,7430],{"class":252,"line":453},[250,7431,986],{"class":912},[250,7433,7434],{"class":252,"line":459},[250,7435,1053],{"class":912},[250,7437,7438],{"class":252,"line":465},[250,7439,7440],{"class":768},"  \u002F\u002F Update the order\n",[250,7442,7443,7445],{"class":252,"line":471},[250,7444,1565],{"class":786},[250,7446,6413],{"class":912},[250,7448,7449,7451,7454],{"class":252,"line":2201},[250,7450,4604],{"class":912},[250,7452,7453],{"class":774},"update",[250,7455,6945],{"class":912},[250,7457,7458,7460,7463],{"class":252,"line":2207},[250,7459,4604],{"class":912},[250,7461,7462],{"class":774},"set",[250,7464,1028],{"class":912},[250,7466,7467],{"class":252,"line":2213},[250,7468,7469],{"class":912},"      status: body.status,\n",[250,7471,7472,7475,7477,7479],{"class":252,"line":2218},[250,7473,7474],{"class":912},"      updatedAt: ",[250,7476,1641],{"class":786},[250,7478,1644],{"class":774},[250,7480,1156],{"class":912},[250,7482,7483],{"class":252,"line":2223},[250,7484,7485],{"class":912},"    })\n",[250,7487,7488,7490,7492,7494,7496],{"class":252,"line":2239},[250,7489,4604],{"class":912},[250,7491,5879],{"class":774},[250,7493,1434],{"class":912},[250,7495,6442],{"class":774},[250,7497,7498],{"class":912},"(orders.id, id));\n",[250,7500,7501],{"class":252,"line":2244},[250,7502,1053],{"class":912},[250,7504,7505,7507,7510,7512,7514],{"class":252,"line":2267},[250,7506,1455],{"class":786},[250,7508,7509],{"class":778}," updatedOrder",[250,7511,1187],{"class":786},[250,7513,1463],{"class":786},[250,7515,6413],{"class":912},[250,7517,7518,7520,7522],{"class":252,"line":2301},[250,7519,4604],{"class":912},[250,7521,5870],{"class":774},[250,7523,4861],{"class":912},[250,7525,7526,7528,7530],{"class":252,"line":2306},[250,7527,4604],{"class":912},[250,7529,1769],{"class":774},[250,7531,6945],{"class":912},[250,7533,7534,7536,7538,7540,7542],{"class":252,"line":2320},[250,7535,4604],{"class":912},[250,7537,5879],{"class":774},[250,7539,1434],{"class":912},[250,7541,6442],{"class":774},[250,7543,7375],{"class":912},[250,7545,7546,7548,7550],{"class":252,"line":2340},[250,7547,4604],{"class":912},[250,7549,6062],{"class":774},[250,7551,1906],{"class":912},[250,7553,7554],{"class":252,"line":2360},[250,7555,1053],{"class":912},[250,7557,7558,7560],{"class":252,"line":2397},[250,7559,1123],{"class":786},[250,7561,7562],{"class":912}," updatedOrder;\n",[250,7564,7565],{"class":252,"line":2402},[250,7566,1077],{"class":912},[2459,7568,7570],{"id":7569},"get-all-orders","Get All Orders",[20,7572,1092,7573,1007],{},[39,7574,7575],{},"server\u002Fapi\u002Forders.get.ts",[47,7577,7579],{"className":1010,"code":7578,"filename":7575,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { orders, orderItems } from \"..\u002Fdb\u002Fschema\";\n\nexport default defineEventHandler(async () => {\n  const allOrders = await db\n    .select()\n    .from(orders)\n    .orderBy(orders.createdAt);\n  \n  \u002F\u002F Fetch items for each order\n  const ordersWithItems = await Promise.all(\n    allOrders.map(async (order) => {\n      const items = await db\n        .select()\n        .from(orderItems)\n        .where(orderItems.orderId.equals(order.id));\n      return { ...order, items };\n    })\n  );\n  \n  return { orders: ordersWithItems };\n});\n",[39,7580,7581,7593,7606,7610,7628,7641,7649,7657,7667,7671,7676,7695,7717,7730,7739,7747,7761,7775,7779,7783,7787,7794],{"__ignoreMap":55},[250,7582,7583,7585,7587,7589,7591],{"class":252,"line":253},[250,7584,1763],{"class":786},[250,7586,5369],{"class":912},[250,7588,1769],{"class":786},[250,7590,5374],{"class":782},[250,7592,1379],{"class":912},[250,7594,7595,7597,7600,7602,7604],{"class":252,"line":113},[250,7596,1763],{"class":786},[250,7598,7599],{"class":912}," { orders, orderItems } ",[250,7601,1769],{"class":786},[250,7603,5388],{"class":782},[250,7605,1379],{"class":912},[250,7607,7608],{"class":252,"line":110},[250,7609,795],{"emptyLinePlaceholder":129},[250,7611,7612,7614,7616,7618,7620,7622,7624,7626],{"class":252,"line":269},[250,7613,1019],{"class":786},[250,7615,1022],{"class":786},[250,7617,1109],{"class":774},[250,7619,1434],{"class":912},[250,7621,1437],{"class":786},[250,7623,2015],{"class":912},[250,7625,1115],{"class":786},[250,7627,1118],{"class":912},[250,7629,7630,7632,7635,7637,7639],{"class":252,"line":275},[250,7631,1455],{"class":786},[250,7633,7634],{"class":778}," allOrders",[250,7636,1187],{"class":786},[250,7638,1463],{"class":786},[250,7640,6413],{"class":912},[250,7642,7643,7645,7647],{"class":252,"line":281},[250,7644,4604],{"class":912},[250,7646,5870],{"class":774},[250,7648,4861],{"class":912},[250,7650,7651,7653,7655],{"class":252,"line":287},[250,7652,4604],{"class":912},[250,7654,1769],{"class":774},[250,7656,6945],{"class":912},[250,7658,7659,7661,7664],{"class":252,"line":293},[250,7660,4604],{"class":912},[250,7662,7663],{"class":774},"orderBy",[250,7665,7666],{"class":912},"(orders.createdAt);\n",[250,7668,7669],{"class":252,"line":299},[250,7670,1053],{"class":912},[250,7672,7673],{"class":252,"line":132},[250,7674,7675],{"class":768},"  \u002F\u002F Fetch items for each order\n",[250,7677,7678,7680,7683,7685,7687,7689,7691,7693],{"class":252,"line":310},[250,7679,1455],{"class":786},[250,7681,7682],{"class":778}," ordersWithItems",[250,7684,1187],{"class":786},[250,7686,1463],{"class":786},[250,7688,1571],{"class":778},[250,7690,2230],{"class":912},[250,7692,2233],{"class":774},[250,7694,1982],{"class":912},[250,7696,7697,7700,7702,7704,7706,7708,7711,7713,7715],{"class":252,"line":316},[250,7698,7699],{"class":912},"    allOrders.",[250,7701,2820],{"class":774},[250,7703,1434],{"class":912},[250,7705,1437],{"class":786},[250,7707,1440],{"class":912},[250,7709,7710],{"class":1370},"order",[250,7712,1446],{"class":912},[250,7714,1115],{"class":786},[250,7716,1118],{"class":912},[250,7718,7719,7722,7724,7726,7728],{"class":252,"line":322},[250,7720,7721],{"class":786},"      const",[250,7723,5861],{"class":778},[250,7725,1187],{"class":786},[250,7727,1463],{"class":786},[250,7729,6413],{"class":912},[250,7731,7732,7735,7737],{"class":252,"line":328},[250,7733,7734],{"class":912},"        .",[250,7736,5870],{"class":774},[250,7738,4861],{"class":912},[250,7740,7741,7743,7745],{"class":252,"line":334},[250,7742,7734],{"class":912},[250,7744,1769],{"class":774},[250,7746,7005],{"class":912},[250,7748,7749,7751,7753,7756,7758],{"class":252,"line":340},[250,7750,7734],{"class":912},[250,7752,5879],{"class":774},[250,7754,7755],{"class":912},"(orderItems.orderId.",[250,7757,6056],{"class":774},[250,7759,7760],{"class":912},"(order.id));\n",[250,7762,7763,7766,7769,7772],{"class":252,"line":346},[250,7764,7765],{"class":786},"      return",[250,7767,7768],{"class":912}," { ",[250,7770,7771],{"class":786},"...",[250,7773,7774],{"class":912},"order, items };\n",[250,7776,7777],{"class":252,"line":352},[250,7778,7485],{"class":912},[250,7780,7781],{"class":252,"line":358},[250,7782,2859],{"class":912},[250,7784,7785],{"class":252,"line":364},[250,7786,1053],{"class":912},[250,7788,7789,7791],{"class":252,"line":370},[250,7790,1123],{"class":786},[250,7792,7793],{"class":912}," { orders: ordersWithItems };\n",[250,7795,7796],{"class":252,"line":376},[250,7797,1077],{"class":912},[72,7799],{},[31,7801,7803],{"id":7802},"step-7-run-migrations","Step 7: Run Migrations",[20,7805,7806],{},"Now that our schema is defined, let's generate and push the migrations.",[47,7808,7810],{"className":758,"code":7809,"filename":760,"language":761,"meta":55,"style":55},"# Generate migration files\nnpx drizzle-kit generate:sqlite\n\n# Push schema to database\nnpx drizzle-kit push:sqlite\n",[39,7811,7812,7817,7826,7830,7835],{"__ignoreMap":55},[250,7813,7814],{"class":252,"line":253},[250,7815,7816],{"class":768},"# Generate migration files\n",[250,7818,7819,7821,7823],{"class":252,"line":113},[250,7820,4200],{"class":774},[250,7822,4246],{"class":782},[250,7824,7825],{"class":782}," generate:sqlite\n",[250,7827,7828],{"class":252,"line":110},[250,7829,795],{"emptyLinePlaceholder":129},[250,7831,7832],{"class":252,"line":269},[250,7833,7834],{"class":768},"# Push schema to database\n",[250,7836,7837,7839,7841],{"class":252,"line":275},[250,7838,4200],{"class":774},[250,7840,4246],{"class":782},[250,7842,7843],{"class":782}," push:sqlite\n",[161,7845,7848],{"icon":7846,"title":7847},"🛠️","Migration Workflow",[20,7849,7850,7851,7854,7855,7858],{},"In development, you can use ",[39,7852,7853],{},"push:sqlite"," to sync changes quickly. For production, use ",[39,7856,7857],{},"generate"," to create migration files and run them separately.",[72,7860],{},[31,7862,7864],{"id":7863},"step-8-test-the-api","Step 8: Test the API",[20,7866,7867],{},"Start your server and test the endpoints:",[47,7869,7870],{"className":758,"code":196,"filename":760,"language":761,"meta":55,"style":55},[39,7871,7872],{"__ignoreMap":55},[250,7873,7874,7876,7878],{"class":252,"line":253},[250,7875,4226],{"class":774},[250,7877,1707],{"class":782},[250,7879,1710],{"class":782},[2459,7881,7883],{"id":7882},"seed-the-menu","Seed the menu:",[47,7885,7887],{"className":758,"code":7886,"language":761,"meta":55,"style":55},"curl -X POST http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fseed\n",[39,7888,7889],{"__ignoreMap":55},[250,7890,7891,7893,7896,7899],{"class":252,"line":253},[250,7892,775],{"class":774},[250,7894,7895],{"class":778}," -X",[250,7897,7898],{"class":782}," POST",[250,7900,7901],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fseed\n",[2459,7903,7905],{"id":7904},"get-the-menu","Get the menu:",[47,7907,7909],{"className":758,"code":7908,"language":761,"meta":55,"style":55},"curl http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fmenu\n",[39,7910,7911],{"__ignoreMap":55},[250,7912,7913,7915],{"class":252,"line":253},[250,7914,775],{"class":774},[250,7916,7917],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fmenu\n",[2459,7919,7921],{"id":7920},"create-an-order","Create an order:",[47,7923,7925],{"className":758,"code":7924,"language":761,"meta":55,"style":55},"curl -X POST http:\u002F\u002Flocalhost:3000\u002Fapi\u002Forders \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"customerName\": \"John\",\n    \"items\": [\n      { \"menuItemId\": \"latte\", \"quantity\": 2 },\n      { \"menuItemId\": \"croissant\", \"quantity\": 1 }\n    ]\n  }'\n",[39,7926,7927,7941,7951,7959,7964,7969,7974,7979,7984],{"__ignoreMap":55},[250,7928,7929,7931,7933,7935,7938],{"class":252,"line":253},[250,7930,775],{"class":774},[250,7932,7895],{"class":778},[250,7934,7898],{"class":782},[250,7936,7937],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Forders",[250,7939,7940],{"class":778}," \\\n",[250,7942,7943,7946,7949],{"class":252,"line":113},[250,7944,7945],{"class":778},"  -H",[250,7947,7948],{"class":782}," \"Content-Type: application\u002Fjson\"",[250,7950,7940],{"class":778},[250,7952,7953,7956],{"class":252,"line":110},[250,7954,7955],{"class":778},"  -d",[250,7957,7958],{"class":782}," '{\n",[250,7960,7961],{"class":252,"line":269},[250,7962,7963],{"class":782},"    \"customerName\": \"John\",\n",[250,7965,7966],{"class":252,"line":275},[250,7967,7968],{"class":782},"    \"items\": [\n",[250,7970,7971],{"class":252,"line":281},[250,7972,7973],{"class":782},"      { \"menuItemId\": \"latte\", \"quantity\": 2 },\n",[250,7975,7976],{"class":252,"line":287},[250,7977,7978],{"class":782},"      { \"menuItemId\": \"croissant\", \"quantity\": 1 }\n",[250,7980,7981],{"class":252,"line":293},[250,7982,7983],{"class":782},"    ]\n",[250,7985,7986],{"class":252,"line":299},[250,7987,7988],{"class":782},"  }'\n",[2459,7990,7992],{"id":7991},"update-order-status-1","Update order status:",[47,7994,7996],{"className":758,"code":7995,"language":761,"meta":55,"style":55},"curl -X PATCH http:\u002F\u002Flocalhost:3000\u002Fapi\u002Forders\u002FORDER_ID \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"status\": \"preparing\"}'\n",[39,7997,7998,8012,8020],{"__ignoreMap":55},[250,7999,8000,8002,8004,8007,8010],{"class":252,"line":253},[250,8001,775],{"class":774},[250,8003,7895],{"class":778},[250,8005,8006],{"class":782}," PATCH",[250,8008,8009],{"class":782}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Forders\u002FORDER_ID",[250,8011,7940],{"class":778},[250,8013,8014,8016,8018],{"class":252,"line":113},[250,8015,7945],{"class":778},[250,8017,7948],{"class":782},[250,8019,7940],{"class":778},[250,8021,8022,8024],{"class":252,"line":110},[250,8023,7955],{"class":778},[250,8025,8026],{"class":782}," '{\"status\": \"preparing\"}'\n",[72,8028],{},[31,8030,3256],{"id":3255},[20,8032,3259],{},[561,8034,8035,8038,8041,8044,8047],{},[564,8036,8037],{},"A fully typed database schema using Drizzle ORM",[564,8039,8040],{},"Type-safe queries throughout your API",[564,8042,8043],{},"Proper data validation and error handling",[564,8045,8046],{},"Order creation with transaction-like behavior",[564,8048,8049],{},"Status update workflow",[2459,8051,3280],{"id":3279},[645,8053,8054,8065],{},[648,8055,8056],{},[651,8057,8058,8061,8063],{},[654,8059,8060],{},"Method",[654,8062,3289],{},[654,8064,3292],{},[666,8066,8067,8080,8092,8104,8115,8128],{},[651,8068,8069,8072,8077],{},[671,8070,8071],{},"GET",[671,8073,8074],{},[39,8075,8076],{},"\u002Fapi\u002Fmenu",[671,8078,8079],{},"Get available menu items",[651,8081,8082,8084,8089],{},[671,8083,8071],{},[671,8085,8086],{},[39,8087,8088],{},"\u002Fapi\u002Fmenu\u002F:id",[671,8090,8091],{},"Get single menu item",[651,8093,8094,8097,8101],{},[671,8095,8096],{},"POST",[671,8098,8099],{},[39,8100,3343],{},[671,8102,8103],{},"Create new order",[651,8105,8106,8108,8112],{},[671,8107,8071],{},[671,8109,8110],{},[39,8111,3343],{},[671,8113,8114],{},"Get all orders",[651,8116,8117,8120,8125],{},[671,8118,8119],{},"PATCH",[671,8121,8122],{},[39,8123,8124],{},"\u002Fapi\u002Forders\u002F:id",[671,8126,8127],{},"Update order status",[651,8129,8130,8132,8137],{},[671,8131,8096],{},[671,8133,8134],{},[39,8135,8136],{},"\u002Fapi\u002Fseed",[671,8138,8139],{},"Seed menu data",[72,8141],{},[15,8143,3352],{"id":3351},[20,8145,8146,8147,8150],{},"Drizzle ORM transforms your database layer from an afterthought into a ",[546,8148,8149],{},"first-class citizen"," of your application. The type safety alone justifies the switch—no more runtime errors from typos in column names, no more guessing what a query returns.",[20,8152,8153],{},"Combined with Nitro's filesystem routing and deployment flexibility, you have a production-ready stack that scales:",[561,8155,8156,8162,8168],{},[564,8157,8158,8161],{},[546,8159,8160],{},"Start with SQLite"," for development and small projects",[564,8163,8164,8167],{},[546,8165,8166],{},"Switch to PostgreSQL"," for production without changing your code",[564,8169,8170,8173],{},[546,8171,8172],{},"Deploy anywhere"," — Node.js, serverless, edge",[20,8175,8176,8177,8180],{},"In the next post, we'll add ",[546,8178,8179],{},"authentication"," to protect our order management endpoints. Until then, enjoy your type-safe API! ☕🚀",[500,8182,8183],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":110,"depth":110,"links":8185},[8186,8187,8188,8189,8190,8191,8192,8199,8200,8206],{"id":4161,"depth":113,"text":4162},{"id":4181,"depth":113,"text":4182},{"id":4259,"depth":113,"text":4260},{"id":4360,"depth":113,"text":4361},{"id":5045,"depth":113,"text":5046},{"id":5348,"depth":113,"text":5349},{"id":5793,"depth":113,"text":5794,"children":8193},[8194,8195,8196,8197,8198],{"id":5797,"depth":110,"text":5798},{"id":5896,"depth":110,"text":5897},{"id":6131,"depth":110,"text":6132},{"id":7059,"depth":110,"text":7060},{"id":7569,"depth":110,"text":7570},{"id":7802,"depth":113,"text":7803},{"id":7863,"depth":113,"text":7864,"children":8201},[8202,8203,8204,8205],{"id":7882,"depth":110,"text":7883},{"id":7904,"depth":110,"text":7905},{"id":7920,"depth":110,"text":7921},{"id":7991,"depth":110,"text":7992},{"id":3255,"depth":113,"text":3256,"children":8207},[8208],{"id":3279,"depth":110,"text":3280},"Learn how to build a production-ready API using Drizzle ORM with Nitro. From setup to deployment, this guide covers everything you need for type-safe database operations.",{"type":12,"value":8211},[8212,8214,8218,8222,8224],[15,8213,541],{"id":540},[20,8215,4089,8216,4093],{},[546,8217,4092],{},[20,8219,4096,8220,4100],{},[546,8221,4099],{},[20,8223,4103],{},[20,8225,4106,8226,4110],{},[546,8227,4109],{},[8229,8230,3504,8231,8232,8233,8234],"drizzle","orm","database","postgres","sqlite","typescript",{},"\u002Fblog\u002Fdrizzle-nitro-api",{"title":4081,"description":8209},"blog\u002Fdrizzle-nitro-api","hs3hXuZ30XGpX2W4zEGOKNf1WS5VkLpwh9An2SIz5jY",{"id":8241,"title":8242,"author":8243,"body":8244,"canonical":115,"categories":115,"date":8285,"description":8286,"excerpt":8287,"extension":118,"img":8293,"keywords":8294,"language":8295,"meta":8296,"navigation":129,"ogImage":115,"path":8297,"rating":131,"readTime":275,"seo":8298,"stem":8299,"tag":8300,"__hash__":8301},"blog\u002Fblog\u002Ffirst-post.md","First Post - Who Am I?",{"name":8,"website":9,"img":10},{"type":12,"value":8245,"toc":8280},[8246,8250,8253,8256,8259,8263,8266,8270,8273,8277],[15,8247,8249],{"id":8248},"just-starting","Just Starting",[20,8251,8252],{},"Hey, I am Vantol, I am a Jamaican - FullStack Developer - and Educator in the Jamaican school system. (I teach Math to kids! Help Me! Please!) LOL!",[20,8254,8255],{},"I have been coding for about 10 years, and I have experimented with most programming languages but I have come to love Javascript - Node.js, Vue.js, Nuxt.js, React, MongoDB\u002FPostgres in my stack. I have been playing with Django Rest Framework of recently and might make something with one day.",[20,8257,8258],{},"In 2021, my focused shifted to making me a concept of grow along with skills and ideas that can change the world.",[31,8260,8262],{"id":8261},"starting-a-new-path","Starting a new path",[20,8264,8265],{},"Basically moving forward in 2022 will be more about Open Source, Content Creation (from Youtube and Twitch Stream) and Npm packages.",[31,8267,8269],{"id":8268},"focus","Focus",[20,8271,8272],{},"'Evolve with Innovation' has always been a slogan for me, and what better way to evolve but to make myself better as a person, father and friend. Outreach and giving back is something I have always wanted to do, so i created Zhyjenae. Zhyjenae is about helping young persons (whether in Jamaica or worldwide) appreciate coding and the doors in which it can open.",[31,8274,8276],{"id":8275},"continued-faith","Continued Faith",[20,8278,8279],{},"It's important that I state I am a Christian and increasing my faith in the Father is important and I want to show that in my coding going forward. In times like these its important to my trust in Him so I can be better in every, shape or form.",{"title":55,"searchDepth":110,"depth":110,"links":8281},[8282,8283,8284],{"id":8261,"depth":113,"text":8262},{"id":8268,"depth":113,"text":8269},{"id":8275,"depth":113,"text":8276},"2021-11-14","Hey, I am Vantol, I am a Jamaican. Get to know me!",{"type":12,"value":8288},[8289,8291],[15,8290,8249],{"id":8248},[20,8292,8252],{},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1636919448\u002FDSC_0991_snlozn.jpg",[121,122],"Buy a coffee Meme",{},"\u002Fblog\u002Ffirst-post",{"title":8242,"description":8286},"blog\u002Ffirst-post","Me","gU8LLHpsi2enw1rOK7IKIn01SlAUqMESrO7y_S24NjY",{"id":8303,"title":8304,"author":8305,"body":8306,"canonical":115,"categories":115,"date":9321,"description":9322,"excerpt":9323,"extension":118,"img":9371,"keywords":9372,"language":3510,"meta":9375,"navigation":129,"ogImage":115,"path":9376,"rating":299,"readTime":132,"seo":9377,"stem":9378,"tag":9379,"__hash__":9380},"blog\u002Fblog\u002Ffood-truck-p1.md","Building a Real App with Nitro (Part 1): Foundations of a Food Truck API",{"name":8,"img":10,"website":535},{"type":12,"value":8307,"toc":9305},[8308,8310,8328,8335,8352,8358,8372,8378,8380,8384,8391,8395,8409,8412,8423,8425,8429,8432,8446,8451,8453,8457,8491,8494,8500,8503,8505,8509,8516,8521,8696,8699,8701,8705,8709,8763,8766,8772,8775,8782,8784,8788,8793,8876,8879,8881,8885,8888,8893,8955,8958,9002,9005,9007,9011,9015,9150,9157,9160,9162,9166,9172,9204,9207,9209,9213,9216,9232,9236,9252,9254,9258,9263,9280,9282,9284,9291,9299,9302],[15,8309,541],{"id":540},[20,8311,8312,8313,8316,8317,8320,8321,8323,8324,8327],{},"Most backend tutorials stop at ",[3587,8314,8315],{},"“Hello World”",". In this ",[546,8318,8319],{},"two-part series",", we’ll go further by using ",[546,8322,555],{}," to build an ",[546,8325,8326],{},"actual backend application"," — a food truck \u002F coffee shop API that could realistically power a real product.",[20,8329,8330,8331,8334],{},"In ",[546,8332,8333],{},"Part 1",", we’ll focus on:",[561,8336,8337,8340,8343,8346,8349],{},[564,8338,8339],{},"Project setup",[564,8341,8342],{},"Application structure",[564,8344,8345],{},"Core API routes (menu, orders, hours)",[564,8347,8348],{},"Runtime configuration",[564,8350,8351],{},"Local development",[20,8353,8330,8354,8357],{},[546,8355,8356],{},"Part 2",", we’ll expand this into:",[561,8359,8360,8363,8366,8369],{},[564,8361,8362],{},"Order creation and validation",[564,8364,8365],{},"Persistence (in-memory → storage)",[564,8367,8368],{},"Middleware and plugins",[564,8370,8371],{},"Deployment-ready architecture",[20,8373,8374,8375,2230],{},"This series assumes basic JavaScript\u002FTypeScript knowledge but ",[546,8376,8377],{},"no prior Nitro experience",[15,8379,748],{"id":747},[31,8381,8383],{"id":8382},"the-app-were-building","The App We’re Building",[20,8385,8386,8387,8390],{},"Our fictional app: ",[546,8388,8389],{},"BrewStop"," ☕🚚 — a mobile coffee truck.",[2459,8392,8394],{"id":8393},"core-features-backend","Core Features (Backend)",[561,8396,8397,8400,8403,8406],{},[564,8398,8399],{},"Fetch menu items",[564,8401,8402],{},"View opening hours",[564,8404,8405],{},"Place orders",[564,8407,8408],{},"Track order status",[20,8410,8411],{},"Nitro will serve as:",[561,8413,8414,8417,8420],{},[564,8415,8416],{},"The API server",[564,8418,8419],{},"The runtime abstraction layer",[564,8421,8422],{},"The deployment target (Node, serverless, edge)",[72,8424],{},[31,8426,8428],{"id":8427},"why-nitro-for-this-app","Why Nitro for This App?",[20,8430,8431],{},"Nitro is perfect for this use case because:",[561,8433,8434,8437,8440,8443],{},[564,8435,8436],{},"It’s lightweight and fast",[564,8438,8439],{},"It supports filesystem routing",[564,8441,8442],{},"It deploys anywhere",[564,8444,8445],{},"It works great with frontend frameworks later",[24,8447,8448],{"type":631},[20,8449,8450],{},"Nitro is the same server engine powering Nuxt — meaning anything we build here can later scale into a fullstack Nuxt app.",[72,8452],{},[31,8454,8456],{"id":8455},"step-1-create-the-nitro-project","Step 1: Create the Nitro Project",[47,8458,8460],{"className":758,"code":8459,"language":761,"meta":55,"style":55},"npx create-nitro-app brewstop-api\ncd brewstop-api\nnpm install\nnpm run dev\n",[39,8461,8462,8471,8477,8483],{"__ignoreMap":55},[250,8463,8464,8466,8468],{"class":252,"line":253},[250,8465,4200],{"class":774},[250,8467,4203],{"class":782},[250,8469,8470],{"class":782}," brewstop-api\n",[250,8472,8473,8475],{"class":252,"line":113},[250,8474,874],{"class":778},[250,8476,8470],{"class":782},[250,8478,8479,8481],{"class":252,"line":110},[250,8480,4226],{"class":774},[250,8482,896],{"class":782},[250,8484,8485,8487,8489],{"class":252,"line":269},[250,8486,4226],{"class":774},[250,8488,1707],{"class":782},[250,8490,1710],{"class":782},[20,8492,8493],{},"Your project structure will look like this:",[47,8495,8498],{"className":8496,"code":8497,"language":52},[50],"server\u002F\n  api\u002F\n  routes\u002F\n  plugins\u002F\nnitro.config.ts\n",[39,8499,8497],{"__ignoreMap":55},[20,8501,8502],{},"Nitro automatically wires everything together.",[72,8504],{},[31,8506,8508],{"id":8507},"step-2-define-the-menu-data","Step 2: Define the Menu Data",[20,8510,8511,8512,8515],{},"For now, we’ll start with ",[546,8513,8514],{},"in-memory data"," (we’ll improve this in Part 2).",[20,8517,1092,8518,1007],{},[39,8519,8520],{},"server\u002Fdata\u002Fmenu.ts",[47,8522,8524],{"className":1010,"code":8523,"language":1012,"meta":55,"style":55},"export interface MenuItem {\n  id: string\n  name: string\n  price: number\n  category: \"coffee\" | \"tea\" | \"food\"\n}\n\nexport const menu: MenuItem[] = [\n  { id: \"latte\", name: \"Latte\", price: 4.5, category: \"coffee\" },\n  { id: \"espresso\", name: \"Espresso\", price: 3, category: \"coffee\" },\n  { id: \"chai\", name: \"Chai Tea\", price: 4, category: \"tea\" },\n  { id: \"croissant\", name: \"Croissant\", price: 3.5, category: \"food\" }\n]\n",[39,8525,8526,8537,8546,8554,8563,8583,8587,8591,8610,8630,8650,8670,8691],{"__ignoreMap":55},[250,8527,8528,8530,8533,8535],{"class":252,"line":253},[250,8529,1019],{"class":786},[250,8531,8532],{"class":786}," interface",[250,8534,4977],{"class":774},[250,8536,1118],{"class":912},[250,8538,8539,8541,8543],{"class":252,"line":113},[250,8540,2490],{"class":1370},[250,8542,1007],{"class":786},[250,8544,8545],{"class":778}," string\n",[250,8547,8548,8550,8552],{"class":252,"line":110},[250,8549,2501],{"class":1370},[250,8551,1007],{"class":786},[250,8553,8545],{"class":778},[250,8555,8556,8558,8560],{"class":252,"line":269},[250,8557,2513],{"class":1370},[250,8559,1007],{"class":786},[250,8561,8562],{"class":778}," number\n",[250,8564,8565,8568,8570,8573,8575,8578,8580],{"class":252,"line":275},[250,8566,8567],{"class":1370},"  category",[250,8569,1007],{"class":786},[250,8571,8572],{"class":782}," \"coffee\"",[250,8574,787],{"class":786},[250,8576,8577],{"class":782}," \"tea\"",[250,8579,787],{"class":786},[250,8581,8582],{"class":782}," \"food\"\n",[250,8584,8585],{"class":252,"line":281},[250,8586,991],{"class":912},[250,8588,8589],{"class":252,"line":287},[250,8590,795],{"emptyLinePlaceholder":129},[250,8592,8593,8595,8597,8600,8602,8604,8606,8608],{"class":252,"line":293},[250,8594,1019],{"class":786},[250,8596,4438],{"class":786},[250,8598,8599],{"class":778}," menu",[250,8601,1007],{"class":786},[250,8603,4977],{"class":774},[250,8605,1413],{"class":912},[250,8607,1416],{"class":786},[250,8609,1190],{"class":912},[250,8611,8612,8614,8616,8618,8620,8622,8624,8626,8628],{"class":252,"line":299},[250,8613,1195],{"class":912},[250,8615,5412],{"class":782},[250,8617,1201],{"class":912},[250,8619,1204],{"class":782},[250,8621,1207],{"class":912},[250,8623,1210],{"class":778},[250,8625,1213],{"class":912},[250,8627,1216],{"class":782},[250,8629,1219],{"class":912},[250,8631,8632,8634,8636,8638,8640,8642,8644,8646,8648],{"class":252,"line":132},[250,8633,1195],{"class":912},[250,8635,5439],{"class":782},[250,8637,1201],{"class":912},[250,8639,1231],{"class":782},[250,8641,1207],{"class":912},[250,8643,1249],{"class":778},[250,8645,1213],{"class":912},[250,8647,1216],{"class":782},[250,8649,1219],{"class":912},[250,8651,8652,8654,8656,8658,8660,8662,8664,8666,8668],{"class":252,"line":310},[250,8653,1195],{"class":912},[250,8655,5519],{"class":782},[250,8657,1201],{"class":912},[250,8659,1278],{"class":782},[250,8661,1207],{"class":912},[250,8663,1273],{"class":778},[250,8665,1213],{"class":912},[250,8667,1288],{"class":782},[250,8669,1219],{"class":912},[250,8671,8672,8674,8676,8678,8680,8682,8684,8686,8688],{"class":252,"line":316},[250,8673,1195],{"class":912},[250,8675,5572],{"class":782},[250,8677,1201],{"class":912},[250,8679,1254],{"class":782},[250,8681,1207],{"class":912},[250,8683,1259],{"class":778},[250,8685,1213],{"class":912},[250,8687,1264],{"class":782},[250,8689,8690],{"class":912}," }\n",[250,8692,8693],{"class":252,"line":322},[250,8694,8695],{"class":912},"]\n",[20,8697,8698],{},"This shared file keeps our types and data clean.",[72,8700],{},[31,8702,8704],{"id":8703},"step-3-create-the-menu-api-route","Step 3: Create the Menu API Route",[20,8706,1092,8707,1007],{},[39,8708,5803],{},[47,8710,8712],{"className":1010,"code":8711,"language":1012,"meta":55,"style":55},"import { menu } from \"..\u002Fdata\u002Fmenu\"\n\nexport default defineEventHandler(() => {\n  return {\n    items: menu\n  }\n})\n",[39,8713,8714,8726,8730,8744,8750,8755,8759],{"__ignoreMap":55},[250,8715,8716,8718,8721,8723],{"class":252,"line":253},[250,8717,1763],{"class":786},[250,8719,8720],{"class":912}," { menu } ",[250,8722,1769],{"class":786},[250,8724,8725],{"class":782}," \"..\u002Fdata\u002Fmenu\"\n",[250,8727,8728],{"class":252,"line":113},[250,8729,795],{"emptyLinePlaceholder":129},[250,8731,8732,8734,8736,8738,8740,8742],{"class":252,"line":110},[250,8733,1019],{"class":786},[250,8735,1022],{"class":786},[250,8737,1109],{"class":774},[250,8739,1112],{"class":912},[250,8741,1115],{"class":786},[250,8743,1118],{"class":912},[250,8745,8746,8748],{"class":252,"line":269},[250,8747,1123],{"class":786},[250,8749,1118],{"class":912},[250,8751,8752],{"class":252,"line":275},[250,8753,8754],{"class":912},"    items: menu\n",[250,8756,8757],{"class":252,"line":281},[250,8758,986],{"class":912},[250,8760,8761],{"class":252,"line":287},[250,8762,474],{"class":912},[20,8764,8765],{},"Now visit:",[47,8767,8770],{"className":8768,"code":8769,"language":52},[50],"http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fmenu\n",[39,8771,8769],{"__ignoreMap":55},[20,8773,8774],{},"You’ll receive structured JSON instantly.",[20,8776,8777,8778,8781],{},"Filesystem routing means no router config, no boilerplate — your file structure ",[3587,8779,8780],{},"is"," your API.\n::",[72,8783],{},[31,8785,8787],{"id":8786},"step-4-add-business-hours","Step 4: Add Business Hours",[20,8789,1092,8790,1007],{},[39,8791,8792],{},"server\u002Fapi\u002Fhours.get.ts",[47,8794,8796],{"className":1010,"code":8795,"language":1012,"meta":55,"style":55},"export default defineEventHandler(() => {\n  return {\n    open: \"08:00\",\n    close: \"16:00\",\n    days: [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"]\n  }\n})\n",[39,8797,8798,8812,8818,8828,8838,8868,8872],{"__ignoreMap":55},[250,8799,8800,8802,8804,8806,8808,8810],{"class":252,"line":253},[250,8801,1019],{"class":786},[250,8803,1022],{"class":786},[250,8805,1109],{"class":774},[250,8807,1112],{"class":912},[250,8809,1115],{"class":786},[250,8811,1118],{"class":912},[250,8813,8814,8816],{"class":252,"line":113},[250,8815,1123],{"class":786},[250,8817,1118],{"class":912},[250,8819,8820,8823,8826],{"class":252,"line":110},[250,8821,8822],{"class":912},"    open: ",[250,8824,8825],{"class":782},"\"08:00\"",[250,8827,927],{"class":912},[250,8829,8830,8833,8836],{"class":252,"line":269},[250,8831,8832],{"class":912},"    close: ",[250,8834,8835],{"class":782},"\"16:00\"",[250,8837,927],{"class":912},[250,8839,8840,8843,8846,8848,8851,8853,8856,8858,8861,8863,8866],{"class":252,"line":275},[250,8841,8842],{"class":912},"    days: [",[250,8844,8845],{"class":782},"\"Monday\"",[250,8847,7128],{"class":912},[250,8849,8850],{"class":782},"\"Tuesday\"",[250,8852,7128],{"class":912},[250,8854,8855],{"class":782},"\"Wednesday\"",[250,8857,7128],{"class":912},[250,8859,8860],{"class":782},"\"Thursday\"",[250,8862,7128],{"class":912},[250,8864,8865],{"class":782},"\"Friday\"",[250,8867,8695],{"class":912},[250,8869,8870],{"class":252,"line":281},[250,8871,986],{"class":912},[250,8873,8874],{"class":252,"line":287},[250,8875,474],{"class":912},[20,8877,8878],{},"This allows the frontend to determine if orders are allowed.",[72,8880],{},[31,8882,8884],{"id":8883},"step-5-runtime-configuration","Step 5: Runtime Configuration",[20,8886,8887],{},"Let’s make the truck name configurable.",[20,8889,1003,8890,1007],{},[39,8891,8892],{},"nitro.config.ts",[47,8894,8896],{"className":1010,"code":8895,"language":1012,"meta":55,"style":55},"import { defineNitroConfig } from \"nitro\u002Fconfig\"\n\nexport default defineNitroConfig({\n  runtimeConfig: {\n    public: {\n      truckName: \"BrewStop Coffee\"\n    }\n  }\n})\n",[39,8897,8898,8910,8914,8925,8930,8935,8943,8947,8951],{"__ignoreMap":55},[250,8899,8900,8902,8905,8907],{"class":252,"line":253},[250,8901,1763],{"class":786},[250,8903,8904],{"class":912}," { defineNitroConfig } ",[250,8906,1769],{"class":786},[250,8908,8909],{"class":782}," \"nitro\u002Fconfig\"\n",[250,8911,8912],{"class":252,"line":113},[250,8913,795],{"emptyLinePlaceholder":129},[250,8915,8916,8918,8920,8923],{"class":252,"line":110},[250,8917,1019],{"class":786},[250,8919,1022],{"class":786},[250,8921,8922],{"class":774}," defineNitroConfig",[250,8924,1028],{"class":912},[250,8926,8927],{"class":252,"line":269},[250,8928,8929],{"class":912},"  runtimeConfig: {\n",[250,8931,8932],{"class":252,"line":275},[250,8933,8934],{"class":912},"    public: {\n",[250,8936,8937,8940],{"class":252,"line":281},[250,8938,8939],{"class":912},"      truckName: ",[250,8941,8942],{"class":782},"\"BrewStop Coffee\"\n",[250,8944,8945],{"class":252,"line":287},[250,8946,3684],{"class":912},[250,8948,8949],{"class":252,"line":293},[250,8950,986],{"class":912},[250,8952,8953],{"class":252,"line":299},[250,8954,474],{"class":912},[20,8956,8957],{},"Use it in an endpoint:",[47,8959,8961],{"className":1010,"code":8960,"language":1012,"meta":55,"style":55},"export default defineEventHandler(() => {\n  const config = useRuntimeConfig()\n  return { name: config.public.truckName }\n})\n",[39,8962,8963,8977,8991,8998],{"__ignoreMap":55},[250,8964,8965,8967,8969,8971,8973,8975],{"class":252,"line":253},[250,8966,1019],{"class":786},[250,8968,1022],{"class":786},[250,8970,1109],{"class":774},[250,8972,1112],{"class":912},[250,8974,1115],{"class":786},[250,8976,1118],{"class":912},[250,8978,8979,8981,8984,8986,8989],{"class":252,"line":113},[250,8980,1455],{"class":786},[250,8982,8983],{"class":778}," config",[250,8985,1187],{"class":786},[250,8987,8988],{"class":774}," useRuntimeConfig",[250,8990,4861],{"class":912},[250,8992,8993,8995],{"class":252,"line":110},[250,8994,1123],{"class":786},[250,8996,8997],{"class":912}," { name: config.public.truckName }\n",[250,8999,9000],{"class":252,"line":269},[250,9001,474],{"class":912},[20,9003,9004],{},"Environment overrides can be added later without code changes.",[72,9006],{},[31,9008,9010],{"id":9009},"step-6-create-orders-initial-version","Step 6: Create Orders (Initial Version)",[20,9012,1092,9013,1007],{},[39,9014,1353],{},[47,9016,9018],{"className":1010,"code":9017,"language":1012,"meta":55,"style":55},"let orders: any[] = []\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event)\n\n  const order = {\n    id: crypto.randomUUID(),\n    items: body.items,\n    status: \"pending\",\n    createdAt: Date.now()\n  }\n\n  orders.push(order)\n  return order\n})\n",[39,9019,9020,9037,9041,9063,9078,9082,9092,9100,9105,9113,9122,9126,9130,9139,9146],{"__ignoreMap":55},[250,9021,9022,9024,9026,9028,9030,9032,9034],{"class":252,"line":253},[250,9023,1949],{"class":786},[250,9025,1405],{"class":912},[250,9027,1007],{"class":786},[250,9029,1410],{"class":778},[250,9031,1413],{"class":912},[250,9033,1416],{"class":786},[250,9035,9036],{"class":912}," []\n",[250,9038,9039],{"class":252,"line":113},[250,9040,795],{"emptyLinePlaceholder":129},[250,9042,9043,9045,9047,9049,9051,9053,9055,9057,9059,9061],{"class":252,"line":110},[250,9044,1019],{"class":786},[250,9046,1022],{"class":786},[250,9048,1109],{"class":774},[250,9050,1434],{"class":912},[250,9052,1437],{"class":786},[250,9054,1440],{"class":912},[250,9056,1443],{"class":1370},[250,9058,1446],{"class":912},[250,9060,1115],{"class":786},[250,9062,1118],{"class":912},[250,9064,9065,9067,9069,9071,9073,9075],{"class":252,"line":269},[250,9066,1455],{"class":786},[250,9068,1458],{"class":778},[250,9070,1187],{"class":786},[250,9072,1463],{"class":786},[250,9074,1466],{"class":774},[250,9076,9077],{"class":912},"(event)\n",[250,9079,9080],{"class":252,"line":275},[250,9081,795],{"emptyLinePlaceholder":129},[250,9083,9084,9086,9088,9090],{"class":252,"line":281},[250,9085,1455],{"class":786},[250,9087,1604],{"class":778},[250,9089,1187],{"class":786},[250,9091,1118],{"class":912},[250,9093,9094,9096,9098],{"class":252,"line":287},[250,9095,1613],{"class":912},[250,9097,1616],{"class":774},[250,9099,1156],{"class":912},[250,9101,9102],{"class":252,"line":293},[250,9103,9104],{"class":912},"    items: body.items,\n",[250,9106,9107,9109,9111],{"class":252,"line":299},[250,9108,1628],{"class":912},[250,9110,1631],{"class":782},[250,9112,927],{"class":912},[250,9114,9115,9118,9120],{"class":252,"line":132},[250,9116,9117],{"class":912},"    createdAt: Date.",[250,9119,1153],{"class":774},[250,9121,4861],{"class":912},[250,9123,9124],{"class":252,"line":310},[250,9125,986],{"class":912},[250,9127,9128],{"class":252,"line":316},[250,9129,795],{"emptyLinePlaceholder":129},[250,9131,9132,9134,9136],{"class":252,"line":322},[250,9133,1665],{"class":912},[250,9135,1668],{"class":774},[250,9137,9138],{"class":912},"(order)\n",[250,9140,9141,9143],{"class":252,"line":328},[250,9142,1123],{"class":786},[250,9144,9145],{"class":912}," order\n",[250,9147,9148],{"class":252,"line":334},[250,9149,474],{"class":912},[20,9151,9152,9153,9156],{},"This gives us a basic order flow we’ll ",[546,9154,9155],{},"refactor and harden"," in Part 2.",[20,9158,9159],{},"This approach is fine for development — but not production. We’ll address persistence and validation next.\n::",[72,9161],{},[31,9163,9165],{"id":9164},"step-7-testing-the-api","Step 7: Testing the API",[20,9167,9168,9169,9171],{},"You can test with ",[39,9170,775],{},", Postman, or any frontend:",[47,9173,9175],{"className":758,"code":9174,"language":761,"meta":55,"style":55},"curl -X POST http:\u002F\u002Flocalhost:3000\u002Fapi\u002Forders \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"items\":[\"latte\",\"croissant\"]}'\n",[39,9176,9177,9189,9197],{"__ignoreMap":55},[250,9178,9179,9181,9183,9185,9187],{"class":252,"line":253},[250,9180,775],{"class":774},[250,9182,7895],{"class":778},[250,9184,7898],{"class":782},[250,9186,7937],{"class":782},[250,9188,7940],{"class":778},[250,9190,9191,9193,9195],{"class":252,"line":113},[250,9192,7945],{"class":778},[250,9194,7948],{"class":782},[250,9196,7940],{"class":778},[250,9198,9199,9201],{"class":252,"line":110},[250,9200,7955],{"class":778},[250,9202,9203],{"class":782}," '{\"items\":[\"latte\",\"croissant\"]}'\n",[20,9205,9206],{},"You’ll receive a created order response immediately.",[72,9208],{},[31,9210,9212],{"id":9211},"what-weve-built-so-far","What We’ve Built So Far",[20,9214,9215],{},"By the end of Part 1, we have:",[561,9217,9218,9221,9224,9226,9229],{},[564,9219,9220],{},"A working Nitro backend",[564,9222,9223],{},"Menu and hours endpoints",[564,9225,3346],{},[564,9227,9228],{},"Runtime config",[564,9230,9231],{},"Clean file structure",[2459,9233,9235],{"id":9234},"current-api-endpoints","Current API Endpoints",[561,9237,9238,9242,9247],{},[564,9239,3299,9240],{},[39,9241,8076],{},[564,9243,3299,9244],{},[39,9245,9246],{},"\u002Fapi\u002Fhours",[564,9248,3340,9249,9251],{},[39,9250,3343],{},"\n::",[72,9253],{},[15,9255,9257],{"id":9256},"whats-coming-in-part-2","What’s Coming in Part 2",[20,9259,8330,9260,9262],{},[546,9261,8356],{},", we’ll level this up:",[561,9264,9265,9268,9271,9274,9277],{},[564,9266,9267],{},"Input validation",[564,9269,9270],{},"Order status updates",[564,9272,9273],{},"Storage using UnJS tools",[564,9275,9276],{},"Middleware (logging & auth)",[564,9278,9279],{},"Deployment-ready output",[72,9281],{},[15,9283,3352],{"id":3351},[20,9285,9286,9287,9290],{},"Nitro makes it incredibly easy to go from ",[546,9288,9289],{},"idea → working backend"," with almost zero friction. In just a few files, we’ve built the foundation of a real food truck application — something that could power a production system with the right enhancements.",[20,9292,8330,9293,9295,9296,2230],{},[546,9294,8356],{},", we’ll turn this prototype into a ",[546,9297,9298],{},"robust, scalable backend",[20,9300,9301],{},"👉 Stay tuned — BrewStop is just getting started ☕🚀",[500,9303,9304],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":110,"depth":110,"links":9306},[9307,9310,9311,9312,9313,9314,9315,9316,9317,9318],{"id":8382,"depth":113,"text":8383,"children":9308},[9309],{"id":8393,"depth":110,"text":8394},{"id":8427,"depth":113,"text":8428},{"id":8455,"depth":113,"text":8456},{"id":8507,"depth":113,"text":8508},{"id":8703,"depth":113,"text":8704},{"id":8786,"depth":113,"text":8787},{"id":8883,"depth":113,"text":8884},{"id":9009,"depth":113,"text":9010},{"id":9164,"depth":113,"text":9165},{"id":9211,"depth":113,"text":9212,"children":9319},[9320],{"id":9234,"depth":110,"text":9235},"2026-01-21","Part 1 of a hands-on series where we use Nitro to build a real backend for a food truck \u002F coffee shop application — from project setup to core API routes.",{"type":12,"value":9324},[9325,9327,9337,9341,9353,9357,9367],[15,9326,541],{"id":540},[20,9328,8312,9329,8316,9331,8320,9333,8323,9335,8327],{},[3587,9330,8315],{},[546,9332,8319],{},[546,9334,555],{},[546,9336,8326],{},[20,9338,8330,9339,8334],{},[546,9340,8333],{},[561,9342,9343,9345,9347,9349,9351],{},[564,9344,8339],{},[564,9346,8342],{},[564,9348,8345],{},[564,9350,8348],{},[564,9352,8351],{},[20,9354,8330,9355,8357],{},[546,9356,8356],{},[561,9358,9359,9361,9363,9365],{},[564,9360,8362],{},[564,9362,8365],{},[564,9364,8368],{},[564,9366,8371],{},[20,9368,8374,9369,2230],{},[546,9370,8377],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1620589125156-fd5028c5e05b?q=80&w=3287&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",[3504,9373,3508,9374,3509,8234],"backend","food truck",{},"\u002Fblog\u002Ffood-truck-p1",{"title":8304,"description":9322},"blog\u002Ffood-truck-p1","Application Development","GxqdOxUneV8DH-GPzbVxo9BoNcHlG80DP35vcL5ShQ4",{"id":9382,"title":9383,"author":9384,"body":9385,"canonical":115,"categories":115,"date":9321,"description":10749,"excerpt":10750,"extension":118,"img":9371,"keywords":10782,"language":3510,"meta":10785,"navigation":129,"ogImage":115,"path":10786,"rating":132,"readTime":132,"seo":10787,"stem":10788,"tag":10789,"__hash__":10790},"blog\u002Fblog\u002Ffood-truck-p2.md","Building a Real App with Nitro (Part 2): Persistence, Validation, and Production Readiness",{"name":8,"img":10,"website":535},{"type":12,"value":9386,"toc":10730},[9387,9389,9400,9409,9424,9427,9429,9433,9436,9456,9463,9465,9469,9476,9480,9494,9498,9503,9572,9575,9586,9589,9591,9595,9599,9743,9746,9748,9752,9755,9760,9842,9845,9919,9922,9924,9928,9930,9934,10052,10054,10058,10240,10243,10248,10250,10254,10259,10370,10373,10375,10379,10382,10386,10421,10426,10563,10566,10568,10572,10575,10588,10595,10606,10618,10621,10623,10627,10631,10654,10657,10671,10673,10675,10684,10700,10707,10710,10724,10727],[15,9388,541],{"id":540},[20,9390,8330,9391,9393,9394,9396,9397,9399],{},[546,9392,8333],{},", we built the foundation of ",[546,9395,8389],{},", a food truck \u002F coffee shop backend powered by ",[546,9398,555],{},". We created menu endpoints, business hours, and a basic order flow.",[20,9401,8330,9402,9404,9405,9408],{},[546,9403,8356],{},", we’ll turn that prototype into something ",[546,9406,9407],{},"production-ready"," by adding:",[561,9410,9411,9413,9416,9418,9421],{},[564,9412,9267],{},[564,9414,9415],{},"Persistent storage (using UnJS tools)",[564,9417,9270],{},[564,9419,9420],{},"Middleware & plugins",[564,9422,9423],{},"Better structure for deployment",[20,9425,9426],{},"This is where Nitro really shines — small additions, big capability.",[15,9428,748],{"id":747},[31,9430,9432],{"id":9431},"recap-where-we-left-off","Recap: Where We Left Off",[20,9434,9435],{},"At the end of Part 1, we had:",[561,9437,9438,9443,9448,9453],{},[564,9439,9440],{},[39,9441,9442],{},"GET \u002Fapi\u002Fmenu",[564,9444,9445],{},[39,9446,9447],{},"GET \u002Fapi\u002Fhours",[564,9449,9450],{},[39,9451,9452],{},"POST \u002Fapi\u002Forders",[564,9454,9455],{},"In-memory order storage",[20,9457,9458,9459,9462],{},"The biggest limitation? ",[546,9460,9461],{},"Orders disappear on restart"," and inputs are not validated. Let’s fix that.",[72,9464],{},[31,9466,9468],{"id":9467},"step-1-add-persistent-storage-with-unstorage","Step 1: Add Persistent Storage with Unstorage",[20,9470,9471,9472,9475],{},"Nitro integrates beautifully with ",[546,9473,9474],{},"Unstorage",", a key-value storage system from the UnJS ecosystem.",[2459,9477,9479],{"id":9478},"install-unstorage","Install Unstorage",[47,9481,9483],{"className":758,"code":9482,"language":761,"meta":55,"style":55},"npm install unstorage\n",[39,9484,9485],{"__ignoreMap":55},[250,9486,9487,9489,9491],{"class":252,"line":253},[250,9488,4226],{"class":774},[250,9490,808],{"class":782},[250,9492,9493],{"class":782}," unstorage\n",[2459,9495,9497],{"id":9496},"create-a-storage-utility","Create a Storage Utility",[20,9499,1092,9500,1007],{},[39,9501,9502],{},"server\u002Futils\u002Fstorage.ts",[47,9504,9506],{"className":1010,"code":9505,"language":1012,"meta":55,"style":55},"import { createStorage } from \"unstorage\"\nimport fsDriver from \"unstorage\u002Fdrivers\u002Ffs\"\n\nexport const storage = createStorage({\n  driver: fsDriver({ base: \".\u002F.data\" })\n})\n",[39,9507,9508,9520,9532,9536,9552,9568],{"__ignoreMap":55},[250,9509,9510,9512,9515,9517],{"class":252,"line":253},[250,9511,1763],{"class":786},[250,9513,9514],{"class":912}," { createStorage } ",[250,9516,1769],{"class":786},[250,9518,9519],{"class":782}," \"unstorage\"\n",[250,9521,9522,9524,9527,9529],{"class":252,"line":113},[250,9523,1763],{"class":786},[250,9525,9526],{"class":912}," fsDriver ",[250,9528,1769],{"class":786},[250,9530,9531],{"class":782}," \"unstorage\u002Fdrivers\u002Ffs\"\n",[250,9533,9534],{"class":252,"line":110},[250,9535,795],{"emptyLinePlaceholder":129},[250,9537,9538,9540,9542,9545,9547,9550],{"class":252,"line":269},[250,9539,1019],{"class":786},[250,9541,4438],{"class":786},[250,9543,9544],{"class":778}," storage",[250,9546,1187],{"class":786},[250,9548,9549],{"class":774}," createStorage",[250,9551,1028],{"class":912},[250,9553,9554,9557,9560,9563,9566],{"class":252,"line":275},[250,9555,9556],{"class":912},"  driver: ",[250,9558,9559],{"class":774},"fsDriver",[250,9561,9562],{"class":912},"({ base: ",[250,9564,9565],{"class":782},"\".\u002F.data\"",[250,9567,4599],{"class":912},[250,9569,9570],{"class":252,"line":281},[250,9571,474],{"class":912},[20,9573,9574],{},"This gives us:",[561,9576,9577,9580,9583],{},[564,9578,9579],{},"Persistent storage",[564,9581,9582],{},"Zero database setup",[564,9584,9585],{},"Easy swap to Redis, Cloudflare KV, etc.",[20,9587,9588],{},"You can switch storage drivers without rewriting your application logic.\n::",[72,9590],{},[31,9592,9594],{"id":9593},"step-2-refactor-orders-to-use-storage","Step 2: Refactor Orders to Use Storage",[20,9596,1003,9597,1007],{},[39,9598,1353],{},[47,9600,9602],{"className":1010,"code":9601,"language":1012,"meta":55,"style":55},"import { storage } from \"..\u002Futils\u002Fstorage\"\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event)\n\n  const order = {\n    id: crypto.randomUUID(),\n    items: body.items,\n    status: \"pending\",\n    createdAt: Date.now()\n  }\n\n  await storage.setItem(`orders:${order.id}`, order)\n  return order\n})\n",[39,9603,9604,9616,9620,9642,9656,9660,9670,9678,9682,9690,9698,9702,9706,9733,9739],{"__ignoreMap":55},[250,9605,9606,9608,9611,9613],{"class":252,"line":253},[250,9607,1763],{"class":786},[250,9609,9610],{"class":912}," { storage } ",[250,9612,1769],{"class":786},[250,9614,9615],{"class":782}," \"..\u002Futils\u002Fstorage\"\n",[250,9617,9618],{"class":252,"line":113},[250,9619,795],{"emptyLinePlaceholder":129},[250,9621,9622,9624,9626,9628,9630,9632,9634,9636,9638,9640],{"class":252,"line":110},[250,9623,1019],{"class":786},[250,9625,1022],{"class":786},[250,9627,1109],{"class":774},[250,9629,1434],{"class":912},[250,9631,1437],{"class":786},[250,9633,1440],{"class":912},[250,9635,1443],{"class":1370},[250,9637,1446],{"class":912},[250,9639,1115],{"class":786},[250,9641,1118],{"class":912},[250,9643,9644,9646,9648,9650,9652,9654],{"class":252,"line":269},[250,9645,1455],{"class":786},[250,9647,1458],{"class":778},[250,9649,1187],{"class":786},[250,9651,1463],{"class":786},[250,9653,1466],{"class":774},[250,9655,9077],{"class":912},[250,9657,9658],{"class":252,"line":275},[250,9659,795],{"emptyLinePlaceholder":129},[250,9661,9662,9664,9666,9668],{"class":252,"line":281},[250,9663,1455],{"class":786},[250,9665,1604],{"class":778},[250,9667,1187],{"class":786},[250,9669,1118],{"class":912},[250,9671,9672,9674,9676],{"class":252,"line":287},[250,9673,1613],{"class":912},[250,9675,1616],{"class":774},[250,9677,1156],{"class":912},[250,9679,9680],{"class":252,"line":293},[250,9681,9104],{"class":912},[250,9683,9684,9686,9688],{"class":252,"line":299},[250,9685,1628],{"class":912},[250,9687,1631],{"class":782},[250,9689,927],{"class":912},[250,9691,9692,9694,9696],{"class":252,"line":132},[250,9693,9117],{"class":912},[250,9695,1153],{"class":774},[250,9697,4861],{"class":912},[250,9699,9700],{"class":252,"line":310},[250,9701,986],{"class":912},[250,9703,9704],{"class":252,"line":316},[250,9705,795],{"emptyLinePlaceholder":129},[250,9707,9708,9710,9713,9716,9718,9721,9723,9725,9728,9730],{"class":252,"line":322},[250,9709,1565],{"class":786},[250,9711,9712],{"class":912}," storage.",[250,9714,9715],{"class":774},"setItem",[250,9717,1434],{"class":912},[250,9719,9720],{"class":782},"`orders:${",[250,9722,7710],{"class":912},[250,9724,2230],{"class":782},[250,9726,9727],{"class":912},"id",[250,9729,2355],{"class":782},[250,9731,9732],{"class":912},", order)\n",[250,9734,9735,9737],{"class":252,"line":328},[250,9736,1123],{"class":786},[250,9738,9145],{"class":912},[250,9740,9741],{"class":252,"line":334},[250,9742,474],{"class":912},[20,9744,9745],{},"Now orders persist across restarts.",[72,9747],{},[31,9749,9751],{"id":9750},"step-3-input-validation","Step 3: Input Validation",[20,9753,9754],{},"Never trust user input — even for coffee ☕.",[20,9756,1092,9757,1007],{},[39,9758,9759],{},"server\u002Futils\u002Fvalidation.ts",[47,9761,9763],{"className":1010,"code":9762,"language":1012,"meta":55,"style":55},"export function validateOrder(body: any) {\n  if (!body?.items || !Array.isArray(body.items)) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Invalid order format\"\n    })\n  }\n}\n",[39,9764,9765,9785,9807,9815,9823,9830,9834,9838],{"__ignoreMap":55},[250,9766,9767,9769,9771,9774,9776,9779,9781,9783],{"class":252,"line":253},[250,9768,1019],{"class":786},[250,9770,1845],{"class":786},[250,9772,9773],{"class":774}," validateOrder",[250,9775,1434],{"class":912},[250,9777,9778],{"class":1370},"body",[250,9780,1007],{"class":786},[250,9782,1410],{"class":778},[250,9784,1512],{"class":912},[250,9786,9787,9789,9791,9793,9796,9798,9800,9802,9804],{"class":252,"line":113},[250,9788,1486],{"class":786},[250,9790,1440],{"class":912},[250,9792,1491],{"class":786},[250,9794,9795],{"class":912},"body?.items ",[250,9797,1497],{"class":786},[250,9799,6286],{"class":786},[250,9801,6289],{"class":912},[250,9803,6292],{"class":774},[250,9805,9806],{"class":912},"(body.items)) {\n",[250,9808,9809,9811,9813],{"class":252,"line":110},[250,9810,1517],{"class":786},[250,9812,1520],{"class":774},[250,9814,1028],{"class":912},[250,9816,9817,9819,9821],{"class":252,"line":269},[250,9818,1527],{"class":912},[250,9820,1530],{"class":778},[250,9822,927],{"class":912},[250,9824,9825,9827],{"class":252,"line":275},[250,9826,1537],{"class":912},[250,9828,9829],{"class":782},"\"Invalid order format\"\n",[250,9831,9832],{"class":252,"line":281},[250,9833,7485],{"class":912},[250,9835,9836],{"class":252,"line":287},[250,9837,986],{"class":912},[250,9839,9840],{"class":252,"line":293},[250,9841,991],{"class":912},[20,9843,9844],{},"Use it in your endpoint:",[47,9846,9848],{"className":1010,"code":9847,"language":1012,"meta":55,"style":55},"import { validateOrder } from \"..\u002Futils\u002Fvalidation\"\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event)\n  validateOrder(body)\n  \u002F\u002F continue logic\n})\n",[39,9849,9850,9862,9866,9888,9902,9910,9915],{"__ignoreMap":55},[250,9851,9852,9854,9857,9859],{"class":252,"line":253},[250,9853,1763],{"class":786},[250,9855,9856],{"class":912}," { validateOrder } ",[250,9858,1769],{"class":786},[250,9860,9861],{"class":782}," \"..\u002Futils\u002Fvalidation\"\n",[250,9863,9864],{"class":252,"line":113},[250,9865,795],{"emptyLinePlaceholder":129},[250,9867,9868,9870,9872,9874,9876,9878,9880,9882,9884,9886],{"class":252,"line":110},[250,9869,1019],{"class":786},[250,9871,1022],{"class":786},[250,9873,1109],{"class":774},[250,9875,1434],{"class":912},[250,9877,1437],{"class":786},[250,9879,1440],{"class":912},[250,9881,1443],{"class":1370},[250,9883,1446],{"class":912},[250,9885,1115],{"class":786},[250,9887,1118],{"class":912},[250,9889,9890,9892,9894,9896,9898,9900],{"class":252,"line":269},[250,9891,1455],{"class":786},[250,9893,1458],{"class":778},[250,9895,1187],{"class":786},[250,9897,1463],{"class":786},[250,9899,1466],{"class":774},[250,9901,9077],{"class":912},[250,9903,9904,9907],{"class":252,"line":275},[250,9905,9906],{"class":774},"  validateOrder",[250,9908,9909],{"class":912},"(body)\n",[250,9911,9912],{"class":252,"line":281},[250,9913,9914],{"class":768},"  \u002F\u002F continue logic\n",[250,9916,9917],{"class":252,"line":287},[250,9918,474],{"class":912},[20,9920,9921],{},"Validation protects your API from malformed requests and accidental misuse.\n::",[72,9923],{},[31,9925,9927],{"id":9926},"step-4-fetch-orders-update-status","Step 4: Fetch Orders & Update Status",[2459,9929,7570],{"id":7569},[20,9931,1092,9932,1007],{},[39,9933,7575],{},[47,9935,9937],{"className":1010,"code":9936,"language":1012,"meta":55,"style":55},"import { storage } from \"..\u002Futils\u002Fstorage\"\n\nexport default defineEventHandler(async () => {\n  const keys = await storage.getKeys(\"orders:\")\n  const orders = await Promise.all(\n    keys.map((key) => storage.getItem(key))\n  )\n  return orders\n})\n",[39,9938,9939,9949,9953,9971,9994,10012,10036,10041,10048],{"__ignoreMap":55},[250,9940,9941,9943,9945,9947],{"class":252,"line":253},[250,9942,1763],{"class":786},[250,9944,9610],{"class":912},[250,9946,1769],{"class":786},[250,9948,9615],{"class":782},[250,9950,9951],{"class":252,"line":113},[250,9952,795],{"emptyLinePlaceholder":129},[250,9954,9955,9957,9959,9961,9963,9965,9967,9969],{"class":252,"line":110},[250,9956,1019],{"class":786},[250,9958,1022],{"class":786},[250,9960,1109],{"class":774},[250,9962,1434],{"class":912},[250,9964,1437],{"class":786},[250,9966,2015],{"class":912},[250,9968,1115],{"class":786},[250,9970,1118],{"class":912},[250,9972,9973,9975,9978,9980,9982,9984,9987,9989,9992],{"class":252,"line":269},[250,9974,1455],{"class":786},[250,9976,9977],{"class":778}," keys",[250,9979,1187],{"class":786},[250,9981,1463],{"class":786},[250,9983,9712],{"class":912},[250,9985,9986],{"class":774},"getKeys",[250,9988,1434],{"class":912},[250,9990,9991],{"class":782},"\"orders:\"",[250,9993,4852],{"class":912},[250,9995,9996,9998,10000,10002,10004,10006,10008,10010],{"class":252,"line":275},[250,9997,1455],{"class":786},[250,9999,1405],{"class":778},[250,10001,1187],{"class":786},[250,10003,1463],{"class":786},[250,10005,1571],{"class":778},[250,10007,2230],{"class":912},[250,10009,2233],{"class":774},[250,10011,1982],{"class":912},[250,10013,10014,10017,10019,10021,10024,10026,10028,10030,10033],{"class":252,"line":281},[250,10015,10016],{"class":912},"    keys.",[250,10018,2820],{"class":774},[250,10020,1574],{"class":912},[250,10022,10023],{"class":1370},"key",[250,10025,1446],{"class":912},[250,10027,1115],{"class":786},[250,10029,9712],{"class":912},[250,10031,10032],{"class":774},"getItem",[250,10034,10035],{"class":912},"(key))\n",[250,10037,10038],{"class":252,"line":287},[250,10039,10040],{"class":912},"  )\n",[250,10042,10043,10045],{"class":252,"line":293},[250,10044,1123],{"class":786},[250,10046,10047],{"class":912}," orders\n",[250,10049,10050],{"class":252,"line":299},[250,10051,474],{"class":912},[2459,10053,7060],{"id":7059},[20,10055,1092,10056,1007],{},[39,10057,7065],{},[47,10059,10061],{"className":1010,"code":10060,"language":1012,"meta":55,"style":55},"import { storage } from \"..\u002F..\u002Futils\u002Fstorage\"\n\nexport default defineEventHandler(async (event) => {\n  const id = event.context.params?.id\n  const body = await readBody(event)\n\n  const order = await storage.getItem(`orders:${id}`)\n  if (!order) {\n    throw createError({ statusCode: 404, statusMessage: \"Order not found\" })\n  }\n\n  const updated = { ...order, status: body.status }\n  await storage.setItem(`orders:${id}`, updated)\n\n  return updated\n})\n",[39,10062,10063,10074,10078,10100,10111,10125,10129,10153,10164,10182,10186,10190,10206,10225,10229,10236],{"__ignoreMap":55},[250,10064,10065,10067,10069,10071],{"class":252,"line":253},[250,10066,1763],{"class":786},[250,10068,9610],{"class":912},[250,10070,1769],{"class":786},[250,10072,10073],{"class":782}," \"..\u002F..\u002Futils\u002Fstorage\"\n",[250,10075,10076],{"class":252,"line":113},[250,10077,795],{"emptyLinePlaceholder":129},[250,10079,10080,10082,10084,10086,10088,10090,10092,10094,10096,10098],{"class":252,"line":110},[250,10081,1019],{"class":786},[250,10083,1022],{"class":786},[250,10085,1109],{"class":774},[250,10087,1434],{"class":912},[250,10089,1437],{"class":786},[250,10091,1440],{"class":912},[250,10093,1443],{"class":1370},[250,10095,1446],{"class":912},[250,10097,1115],{"class":786},[250,10099,1118],{"class":912},[250,10101,10102,10104,10106,10108],{"class":252,"line":269},[250,10103,1455],{"class":786},[250,10105,5964],{"class":778},[250,10107,1187],{"class":786},[250,10109,10110],{"class":912}," event.context.params?.id\n",[250,10112,10113,10115,10117,10119,10121,10123],{"class":252,"line":275},[250,10114,1455],{"class":786},[250,10116,1458],{"class":778},[250,10118,1187],{"class":786},[250,10120,1463],{"class":786},[250,10122,1466],{"class":774},[250,10124,9077],{"class":912},[250,10126,10127],{"class":252,"line":281},[250,10128,795],{"emptyLinePlaceholder":129},[250,10130,10131,10133,10135,10137,10139,10141,10143,10145,10147,10149,10151],{"class":252,"line":287},[250,10132,1455],{"class":786},[250,10134,1604],{"class":778},[250,10136,1187],{"class":786},[250,10138,1463],{"class":786},[250,10140,9712],{"class":912},[250,10142,10032],{"class":774},[250,10144,1434],{"class":912},[250,10146,9720],{"class":782},[250,10148,9727],{"class":912},[250,10150,2355],{"class":782},[250,10152,4852],{"class":912},[250,10154,10155,10157,10159,10161],{"class":252,"line":293},[250,10156,1486],{"class":786},[250,10158,1440],{"class":912},[250,10160,1491],{"class":786},[250,10162,10163],{"class":912},"order) {\n",[250,10165,10166,10168,10170,10173,10175,10178,10180],{"class":252,"line":299},[250,10167,1517],{"class":786},[250,10169,1520],{"class":774},[250,10171,10172],{"class":912},"({ statusCode: ",[250,10174,6094],{"class":778},[250,10176,10177],{"class":912},", statusMessage: ",[250,10179,7421],{"class":782},[250,10181,4599],{"class":912},[250,10183,10184],{"class":252,"line":132},[250,10185,986],{"class":912},[250,10187,10188],{"class":252,"line":310},[250,10189,795],{"emptyLinePlaceholder":129},[250,10191,10192,10194,10197,10199,10201,10203],{"class":252,"line":316},[250,10193,1455],{"class":786},[250,10195,10196],{"class":778}," updated",[250,10198,1187],{"class":786},[250,10200,7768],{"class":912},[250,10202,7771],{"class":786},[250,10204,10205],{"class":912},"order, status: body.status }\n",[250,10207,10208,10210,10212,10214,10216,10218,10220,10222],{"class":252,"line":322},[250,10209,1565],{"class":786},[250,10211,9712],{"class":912},[250,10213,9715],{"class":774},[250,10215,1434],{"class":912},[250,10217,9720],{"class":782},[250,10219,9727],{"class":912},[250,10221,2355],{"class":782},[250,10223,10224],{"class":912},", updated)\n",[250,10226,10227],{"class":252,"line":328},[250,10228,795],{"emptyLinePlaceholder":129},[250,10230,10231,10233],{"class":252,"line":334},[250,10232,1123],{"class":786},[250,10234,10235],{"class":912}," updated\n",[250,10237,10238],{"class":252,"line":340},[250,10239,474],{"class":912},[20,10241,10242],{},"Now BrewStop supports a real workflow:",[561,10244,10245],{},[564,10246,10247],{},"pending → preparing → ready → completed",[72,10249],{},[31,10251,10253],{"id":10252},"step-5-add-middleware-logging","Step 5: Add Middleware (Logging)",[20,10255,1092,10256,1007],{},[39,10257,10258],{},"server\u002Fplugins\u002Flogger.ts",[47,10260,10262],{"className":1010,"code":10261,"language":1012,"meta":55,"style":55},"export default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook(\"request\", (event) => {\n    console.log(\n      `[${new Date().toISOString()}] ${event.method} ${event.path}`\n    )\n  })\n})\n",[39,10263,10264,10284,10308,10317,10356,10361,10366],{"__ignoreMap":55},[250,10265,10266,10268,10270,10273,10275,10278,10280,10282],{"class":252,"line":253},[250,10267,1019],{"class":786},[250,10269,1022],{"class":786},[250,10271,10272],{"class":774}," defineNitroPlugin",[250,10274,1574],{"class":912},[250,10276,10277],{"class":1370},"nitroApp",[250,10279,1446],{"class":912},[250,10281,1115],{"class":786},[250,10283,1118],{"class":912},[250,10285,10286,10289,10292,10294,10297,10300,10302,10304,10306],{"class":252,"line":113},[250,10287,10288],{"class":912},"  nitroApp.hooks.",[250,10290,10291],{"class":774},"hook",[250,10293,1434],{"class":912},[250,10295,10296],{"class":782},"\"request\"",[250,10298,10299],{"class":912},", (",[250,10301,1443],{"class":1370},[250,10303,1446],{"class":912},[250,10305,1115],{"class":786},[250,10307,1118],{"class":912},[250,10309,10310,10313,10315],{"class":252,"line":110},[250,10311,10312],{"class":912},"    console.",[250,10314,1859],{"class":774},[250,10316,1982],{"class":912},[250,10318,10319,10322,10324,10326,10328,10330,10333,10336,10338,10340,10343,10346,10348,10350,10353],{"class":252,"line":269},[250,10320,10321],{"class":782},"      `[${",[250,10323,1641],{"class":786},[250,10325,1644],{"class":774},[250,10327,1647],{"class":782},[250,10329,1650],{"class":774},[250,10331,10332],{"class":782},"()",[250,10334,10335],{"class":782},"}] ${",[250,10337,1443],{"class":912},[250,10339,2230],{"class":782},[250,10341,10342],{"class":912},"method",[250,10344,10345],{"class":782},"} ${",[250,10347,1443],{"class":912},[250,10349,2230],{"class":782},[250,10351,10352],{"class":912},"path",[250,10354,10355],{"class":782},"}`\n",[250,10357,10358],{"class":252,"line":275},[250,10359,10360],{"class":912},"    )\n",[250,10362,10363],{"class":252,"line":281},[250,10364,10365],{"class":912},"  })\n",[250,10367,10368],{"class":252,"line":287},[250,10369,474],{"class":912},[20,10371,10372],{},"This gives you centralized request logging without cluttering endpoints.",[72,10374],{},[31,10376,10378],{"id":10377},"step-6-simple-api-key-protection","Step 6: Simple API Key Protection",[20,10380,10381],{},"Let’s protect order updates.",[20,10383,1003,10384,1007],{},[39,10385,8892],{},[47,10387,10389],{"className":1010,"code":10388,"language":1012,"meta":55,"style":55},"export default defineNitroConfig({\n  runtimeConfig: {\n    apiKey: \"super-secret-key\"\n  }\n})\n",[39,10390,10391,10401,10405,10413,10417],{"__ignoreMap":55},[250,10392,10393,10395,10397,10399],{"class":252,"line":253},[250,10394,1019],{"class":786},[250,10396,1022],{"class":786},[250,10398,8922],{"class":774},[250,10400,1028],{"class":912},[250,10402,10403],{"class":252,"line":113},[250,10404,8929],{"class":912},[250,10406,10407,10410],{"class":252,"line":110},[250,10408,10409],{"class":912},"    apiKey: ",[250,10411,10412],{"class":782},"\"super-secret-key\"\n",[250,10414,10415],{"class":252,"line":269},[250,10416,986],{"class":912},[250,10418,10419],{"class":252,"line":275},[250,10420,474],{"class":912},[20,10422,1092,10423,1007],{},[39,10424,10425],{},"server\u002Fplugins\u002Fauth.ts",[47,10427,10429],{"className":1010,"code":10428,"language":1012,"meta":55,"style":55},"export default defineNitroPlugin(() => {\n  addEventHandler((event) => {\n    if (event.path.startsWith(\"\u002Fapi\u002Forders\") && event.method !== \"GET\") {\n      const key = event.headers.get(\"x-api-key\")\n      if (key !== useRuntimeConfig().apiKey) {\n        throw createError({ statusCode: 401, statusMessage: \"Unauthorized\" })\n      }\n    }\n  })\n})\n",[39,10430,10431,10445,10460,10491,10512,10527,10546,10551,10555,10559],{"__ignoreMap":55},[250,10432,10433,10435,10437,10439,10441,10443],{"class":252,"line":253},[250,10434,1019],{"class":786},[250,10436,1022],{"class":786},[250,10438,10272],{"class":774},[250,10440,1112],{"class":912},[250,10442,1115],{"class":786},[250,10444,1118],{"class":912},[250,10446,10447,10450,10452,10454,10456,10458],{"class":252,"line":113},[250,10448,10449],{"class":774},"  addEventHandler",[250,10451,1574],{"class":912},[250,10453,1443],{"class":1370},[250,10455,1446],{"class":912},[250,10457,1115],{"class":786},[250,10459,1118],{"class":912},[250,10461,10462,10464,10467,10470,10472,10475,10477,10480,10483,10486,10489],{"class":252,"line":110},[250,10463,6463],{"class":786},[250,10465,10466],{"class":912}," (event.path.",[250,10468,10469],{"class":774},"startsWith",[250,10471,1434],{"class":912},[250,10473,10474],{"class":782},"\"\u002Fapi\u002Forders\"",[250,10476,1446],{"class":912},[250,10478,10479],{"class":786},"&&",[250,10481,10482],{"class":912}," event.method ",[250,10484,10485],{"class":786},"!==",[250,10487,10488],{"class":782}," \"GET\"",[250,10490,1512],{"class":912},[250,10492,10493,10495,10498,10500,10503,10505,10507,10510],{"class":252,"line":269},[250,10494,7721],{"class":786},[250,10496,10497],{"class":778}," key",[250,10499,1187],{"class":786},[250,10501,10502],{"class":912}," event.headers.",[250,10504,6062],{"class":774},[250,10506,1434],{"class":912},[250,10508,10509],{"class":782},"\"x-api-key\"",[250,10511,4852],{"class":912},[250,10513,10514,10517,10520,10522,10524],{"class":252,"line":275},[250,10515,10516],{"class":786},"      if",[250,10518,10519],{"class":912}," (key ",[250,10521,10485],{"class":786},[250,10523,8988],{"class":774},[250,10525,10526],{"class":912},"().apiKey) {\n",[250,10528,10529,10532,10534,10536,10539,10541,10544],{"class":252,"line":281},[250,10530,10531],{"class":786},"        throw",[250,10533,1520],{"class":774},[250,10535,10172],{"class":912},[250,10537,10538],{"class":778},"401",[250,10540,10177],{"class":912},[250,10542,10543],{"class":782},"\"Unauthorized\"",[250,10545,4599],{"class":912},[250,10547,10548],{"class":252,"line":287},[250,10549,10550],{"class":912},"      }\n",[250,10552,10553],{"class":252,"line":293},[250,10554,3684],{"class":912},[250,10556,10557],{"class":252,"line":299},[250,10558,10365],{"class":912},[250,10560,10561],{"class":252,"line":132},[250,10562,474],{"class":912},[20,10564,10565],{},"This is intentionally simple — Nitro plugins scale well to JWT, OAuth, or third-party auth later.\n::",[72,10567],{},[31,10569,10571],{"id":10570},"step-7-deployment-readiness","Step 7: Deployment Readiness",[20,10573,10574],{},"Build your app:",[47,10576,10578],{"className":758,"code":10577,"language":761,"meta":55,"style":55},"npm run build\n",[39,10579,10580],{"__ignoreMap":55},[250,10581,10582,10584,10586],{"class":252,"line":253},[250,10583,4226],{"class":774},[250,10585,1707],{"class":782},[250,10587,3234],{"class":782},[20,10589,10590,10591,10594],{},"Nitro outputs a ",[39,10592,10593],{},".output"," directory that can run on:",[561,10596,10597,10600,10603],{},[564,10598,10599],{},"Node.js servers",[564,10601,10602],{},"Serverless platforms",[564,10604,10605],{},"Edge runtimes",[47,10607,10609],{"className":758,"code":10608,"language":761,"meta":55,"style":55},"node .output\u002Fserver\u002Findex.mjs\n",[39,10610,10611],{"__ignoreMap":55},[250,10612,10613,10616],{"class":252,"line":253},[250,10614,10615],{"class":774},"node",[250,10617,3243],{"class":782},[20,10619,10620],{},"No changes needed.",[72,10622],{},[31,10624,10626],{"id":10625},"final-api-overview","Final API Overview",[2459,10628,10630],{"id":10629},"brewstop-api-final","BrewStop API (Final)",[561,10632,10633,10637,10641,10645,10649],{},[564,10634,3299,10635],{},[39,10636,8076],{},[564,10638,3299,10639],{},[39,10640,9246],{},[564,10642,3299,10643],{},[39,10644,3343],{},[564,10646,3340,10647],{},[39,10648,3343],{},[564,10650,10651,10652,9251],{},"PATCH ",[39,10653,8124],{},[20,10655,10656],{},"This backend can now realistically power:",[561,10658,10659,10662,10665,10668],{},[564,10660,10661],{},"A POS system",[564,10663,10664],{},"A mobile app",[564,10666,10667],{},"A Nuxt frontend",[564,10669,10670],{},"An admin dashboard",[72,10672],{},[15,10674,3352],{"id":3351},[20,10676,10677,10678,10681,10682,1007],{},"In just ",[546,10679,10680],{},"two parts",", we’ve built a real backend using ",[546,10683,555],{},[561,10685,10686,10688,10691,10694,10697],{},[564,10687,9579],{},[564,10689,10690],{},"Validation",[564,10692,10693],{},"Middleware",[564,10695,10696],{},"Secure endpoints",[564,10698,10699],{},"Multi-runtime deployment",[20,10701,10702,10703,10706],{},"Nitro proves that you don’t need heavy frameworks or complex infrastructure to build ",[546,10704,10705],{},"serious applications",". With composable UnJS tools and clean architecture, you can ship fast — and scale later.",[20,10708,10709],{},"Next steps?",[561,10711,10712,10715,10718,10721],{},[564,10713,10714],{},"Add a frontend (Nuxt or Vite)",[564,10716,10717],{},"Add payments",[564,10719,10720],{},"Deploy to edge",[564,10722,10723],{},"Replace storage with a database",[20,10725,10726],{},"BrewStop is production-ready — and this is only the beginning. ☕🚀",[500,10728,10729],{},"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 .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":55,"searchDepth":110,"depth":110,"links":10731},[10732,10733,10737,10738,10739,10743,10744,10745,10746],{"id":9431,"depth":113,"text":9432},{"id":9467,"depth":113,"text":9468,"children":10734},[10735,10736],{"id":9478,"depth":110,"text":9479},{"id":9496,"depth":110,"text":9497},{"id":9593,"depth":113,"text":9594},{"id":9750,"depth":113,"text":9751},{"id":9926,"depth":113,"text":9927,"children":10740},[10741,10742],{"id":7569,"depth":110,"text":7570},{"id":7059,"depth":110,"text":7060},{"id":10252,"depth":113,"text":10253},{"id":10377,"depth":113,"text":10378},{"id":10570,"depth":113,"text":10571},{"id":10625,"depth":113,"text":10626,"children":10747},[10748],{"id":10629,"depth":110,"text":10630},"Part 2 of our Nitro series where we level up the BrewStop food truck backend with validation, storage, middleware, and deployment-ready architecture.",{"type":12,"value":10751},[10752,10754,10762,10768,10780],[15,10753,541],{"id":540},[20,10755,8330,10756,9393,10758,9396,10760,9399],{},[546,10757,8333],{},[546,10759,8389],{},[546,10761,555],{},[20,10763,8330,10764,9404,10766,9408],{},[546,10765,8356],{},[546,10767,9407],{},[561,10769,10770,10772,10774,10776,10778],{},[564,10771,9267],{},[564,10773,9415],{},[564,10775,9270],{},[564,10777,9420],{},[564,10779,9423],{},[20,10781,9426],{},[3504,9373,3508,10783,10784,9374],"unjs","serverless",{},"\u002Fblog\u002Ffood-truck-p2",{"title":9383,"description":10749},"blog\u002Ffood-truck-p2","“Application Development”","prrsHwI_79_BIGLnC3EEU-7AfHq-Js5POFW1zkdLKVc",{"id":10792,"title":10793,"author":10794,"body":10795,"canonical":115,"categories":115,"date":10971,"description":10972,"excerpt":10973,"extension":118,"img":10984,"keywords":10985,"language":3510,"meta":10991,"navigation":129,"ogImage":115,"path":10992,"rating":275,"readTime":281,"seo":10993,"stem":10994,"tag":10995,"__hash__":10996},"blog\u002Fblog\u002Fmps-new-begins.md","Mashed Potato Studios: Crafting Digital Experiences That Actually Work",{"name":8,"img":10,"website":535},{"type":12,"value":10796,"toc":10963},[10797,10799,10812,10814,10818,10821,10826,10830,10833,10854,10857,10861,10868,10882,10887,10891,10894,10960],[15,10798,541],{"id":540},[20,10800,10801,10802,10805,10806,10811],{},"At ",[546,10803,10804],{},"Mashed Potato Studios",", we believe great digital products should be simple, effective, and memorable—just like comfort food done right. Our website, ",[203,10807,10810],{"href":10808,"rel":10809},"https:\u002F\u002Fmashedpotatostudios.com",[207],"mashedpotatostudios.com",", reflects who we are: a creative digital studio focused on building solutions that make sense for real people and real businesses.",[15,10813,748],{"id":747},[31,10815,10817],{"id":10816},"who-we-are","Who We Are",[20,10819,10820],{},"Mashed Potato Studios is a creative and technology-driven studio that helps businesses transform ideas into polished digital experiences. From concept to launch, we focus on clarity, usability, and performance—cutting out the unnecessary fluff and delivering what actually matters.",[24,10822,10823],{"type":631},[20,10824,10825],{},"Mashed Potato Studios works with startups, growing businesses, and established brands looking to level up their digital presence.",[31,10827,10829],{"id":10828},"what-we-do","What We Do",[20,10831,10832],{},"Our services are designed to meet clients where they are, whether they’re starting from scratch or refining an existing product.",[10834,10835,10836,10840],"blog-card",{},[2459,10837,10839],{"id":10838},"core-focus-areas","Core Focus Areas",[561,10841,10842,10845,10848,10851],{},[564,10843,10844],{},"Website design & development",[564,10846,10847],{},"Web applications & SaaS platforms",[564,10849,10850],{},"Branding & digital identity",[564,10852,10853],{},"Performance, scalability, and user experience",[20,10855,10856],{},"We combine clean design with modern development practices to ensure every project is fast, accessible, and future-ready.",[31,10858,10860],{"id":10859},"why-the-website-matters","Why the Website Matters",[20,10862,10863,10864,10867],{},"Your website is often the ",[546,10865,10866],{},"first impression"," of your brand. At Mashed Potato Studios, we design websites that:",[561,10869,10870,10873,10876,10879],{},[564,10871,10872],{},"Communicate value clearly",[564,10874,10875],{},"Load fast and work across all devices",[564,10877,10878],{},"Convert visitors into customers",[564,10880,10881],{},"Grow with your business",[24,10883,10884],{"type":26},[20,10885,10886],{},"A slow, cluttered, or outdated website can cost you credibility—and customers.",[31,10888,10890],{"id":10889},"our-approach-to-development","Our Approach to Development",[20,10892,10893],{},"We build with modern tools and best practices, focusing on maintainability and long-term success.",[47,10895,10898],{"className":1010,"code":10896,"filename":10897,"language":1012,"meta":55,"style":55},"const studioPhilosophy = {\n  design: \"Clean and purposeful\",\n  code: \"Scalable and maintainable\",\n  clients: \"Partners, not just projects\",\n};\n\nconsole.log(studioPhilosophy);\n","philosophy.ts",[39,10899,10900,10911,10921,10931,10941,10946,10950],{"__ignoreMap":55},[250,10901,10902,10904,10907,10909],{"class":252,"line":253},[250,10903,1181],{"class":786},[250,10905,10906],{"class":778}," studioPhilosophy",[250,10908,1187],{"class":786},[250,10910,1118],{"class":912},[250,10912,10913,10916,10919],{"class":252,"line":113},[250,10914,10915],{"class":912},"  design: ",[250,10917,10918],{"class":782},"\"Clean and purposeful\"",[250,10920,927],{"class":912},[250,10922,10923,10926,10929],{"class":252,"line":110},[250,10924,10925],{"class":912},"  code: ",[250,10927,10928],{"class":782},"\"Scalable and maintainable\"",[250,10930,927],{"class":912},[250,10932,10933,10936,10939],{"class":252,"line":269},[250,10934,10935],{"class":912},"  clients: ",[250,10937,10938],{"class":782},"\"Partners, not just projects\"",[250,10940,927],{"class":912},[250,10942,10943],{"class":252,"line":275},[250,10944,10945],{"class":912},"};\n",[250,10947,10948],{"class":252,"line":281},[250,10949,795],{"emptyLinePlaceholder":129},[250,10951,10952,10955,10957],{"class":252,"line":287},[250,10953,10954],{"class":912},"console.",[250,10956,1859],{"class":774},[250,10958,10959],{"class":912},"(studioPhilosophy);\n",[500,10961,10962],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":55,"searchDepth":110,"depth":110,"links":10964},[10965,10966,10969,10970],{"id":10816,"depth":113,"text":10817},{"id":10828,"depth":113,"text":10829,"children":10967},[10968],{"id":10838,"depth":110,"text":10839},{"id":10859,"depth":113,"text":10860},{"id":10889,"depth":113,"text":10890},"2026-01-04","An inside look at Mashed Potato Studios—our mission, services, and how we help brands turn ideas into powerful digital products.",{"type":12,"value":10974},[10975,10977],[15,10976,541],{"id":540},[20,10978,10801,10979,10805,10981,10811],{},[546,10980,10804],{},[203,10982,10810],{"href":10808,"rel":10983},[207],"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1553877522-43269d4ea984",[10986,10987,10988,10989,10990],"web development","branding","digital studio","startups","saas",{},"\u002Fblog\u002Fmps-new-begins",{"title":10793,"description":10972},"blog\u002Fmps-new-begins","Business","RTbMI38IFrp9Zg8xRFdCHiPkiqz_jlaEe9outeJD4n0",{"id":10998,"title":10999,"author":11000,"body":11001,"canonical":115,"categories":115,"date":11046,"description":11047,"excerpt":11048,"extension":118,"img":521,"keywords":11054,"language":524,"meta":11055,"navigation":129,"ogImage":115,"path":11056,"rating":11057,"readTime":110,"seo":11058,"stem":11059,"tag":11060,"__hash__":11061},"blog\u002Fblog\u002Fnew-vue-default.md","The New Vue Default",{"name":8,"website":9,"img":10},{"type":12,"value":11002,"toc":11044},[11003,11006,11009,11015,11018,11038,11041],[15,11004,10999],{"id":11005},"the-new-vue-default",[20,11007,11008],{},"Important notice: Vue will become default version on February 7, 2022.",[11010,11011,11012],"note",{},[20,11013,11014],{},"This was a major milestone for the Vue ecosystem, shifting from a library-first to a framework-first mindset.",[20,11016,11017],{},"I am actually excited about the current direction and vision that Vue is headed. Being a progressive framework means that implementation of how code is written is paramount for developer experience (DX). Look at how the new vue is implemented.",[161,11019,11022],{"icon":11020,"title":11021},"⚡️","Quick Install",[47,11023,11025],{"className":758,"code":11024,"language":761,"meta":55,"style":55},"npm install init vue@latest\n",[39,11026,11027],{"__ignoreMap":55},[250,11028,11029,11031,11033,11035],{"class":252,"line":253},[250,11030,4226],{"class":774},[250,11032,808],{"class":782},[250,11034,862],{"class":782},[250,11036,11037],{"class":782}," vue@latest\n",[20,11039,11040],{},"This provides a refreshing CLI experience that runs on Vite tooling under the hood. Integrating all the relevant tools from the community make the experience worth while..... just wish there was an turn off the bloatware (for more experienced persons who wanna get up and running quickly).",[500,11042,11043],{},"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);}",{"title":55,"searchDepth":110,"depth":110,"links":11045},[],"2022-02-01","From a library to a Framework",{"type":12,"value":11049},[11050,11052],[15,11051,10999],{"id":11005},[20,11053,11008],{},[121,122,123,124,523,126],{},"\u002Fblog\u002Fnew-vue-default",4.8,{"title":10999,"description":11047},"blog\u002Fnew-vue-default","Framework","_ciURD2dpRkcxF78RbONV7kr3yG4Lj1VuIUZBl4WBf8",{"id":11063,"title":11064,"author":11065,"body":11066,"canonical":115,"categories":115,"date":11098,"description":11099,"excerpt":11100,"extension":118,"img":119,"keywords":11106,"language":524,"meta":11107,"navigation":129,"ogImage":115,"path":11108,"rating":131,"readTime":275,"seo":11109,"stem":11110,"tag":11111,"__hash__":11112},"blog\u002Fblog\u002Fnew-website.md","My New Website",{"name":8,"website":9,"img":10},{"type":12,"value":11067,"toc":11094},[11068,11071,11074,11077,11082,11085,11089],[31,11069,11070],{"id":3506},"Performance",[20,11072,11073],{},"Nuxt.js provides some unique advantages which allowed for it to be the main choice when creating my website.",[20,11075,11076],{},"Vue.js is my framework of choice in most cases. Nuxt.js provides an \"intutitve\" developer experience (DX).",[172,11078,11079],{},[20,11080,11081],{},"Nuxt.js has zero configuration, allowing for file-system routing, components auto-import and seo friendly for indexing.",[20,11083,11084],{},"Paramount to this application using the power modules- Content, that allows for my web app to using MDX for this blog section.",[31,11086,11088],{"id":11087},"future-updates","Future Updates",[10834,11090,11091],{},[20,11092,11093],{},"Addition of Youtube videos section will added shortly, Integration of Twitch API....",{"title":55,"searchDepth":110,"depth":110,"links":11095},[11096,11097],{"id":3506,"depth":113,"text":11070},{"id":11087,"depth":113,"text":11088},"2021-12-01","Built with Nuxt.js 2",{"type":12,"value":11101},[11102,11104],[31,11103,11070],{"id":3506},[20,11105,11073],{},[121,122,123,124,523,126],{},"\u002Fblog\u002Fnew-website",{"title":11064,"description":11099},"blog\u002Fnew-website","New Stack","QZONtmh4tVLWktddB0aVeaOkILpE6S43GCANap-Q3KM",{"id":11114,"title":11115,"author":11116,"body":11117,"canonical":115,"categories":115,"date":11328,"description":11329,"excerpt":115,"extension":118,"img":11330,"keywords":11331,"language":3510,"meta":11336,"navigation":129,"ogImage":115,"path":11337,"rating":275,"readTime":275,"seo":11338,"stem":11339,"tag":3515,"__hash__":11340},"blog\u002Fblog\u002Fnew-year-new-code.md","New Year, New Stack: Embracing TanStack Start & AI Integrations in 2026",{"name":8,"img":10,"website":535},{"type":12,"value":11118,"toc":11320},[11119,11121,11136,11138,11142,11148,11151,11156,11160,11165,11168,11182,11199,11202,11206,11209,11212,11226,11233,11236,11240,11250,11318],[15,11120,541],{"id":540},[20,11122,11123,11124,11127,11128,11131,11132,11135],{},"A new year always brings fresh energy—and in tech, that energy often shows up as better tools, smarter workflows, and new ways of thinking. As we step into ",[546,11125,11126],{},"2026",", this is the year of embracing modern frameworks like ",[546,11129,11130],{},"TanStack Start"," and leaning fully into ",[546,11133,11134],{},"AI integrations"," to build faster, more intelligent digital experiences.",[15,11137,748],{"id":747},[31,11139,11141],{"id":11140},"why-a-new-stack-matters","Why a New Stack Matters",[20,11143,11144,11145,2230],{},"The web is evolving quickly. Users expect instant feedback, seamless navigation, and personalized experiences. To meet those expectations, developers need tools that are ",[546,11146,11147],{},"performant, flexible, and future-proof",[20,11149,11150],{},"That’s where modern frameworks come in.",[24,11152,11153],{"type":631},[20,11154,11155],{},"Choosing the right framework isn’t about hype—it’s about long-term maintainability and developer experience.",[31,11157,11159],{"id":11158},"tanstack-start-a-fresh-way-to-build","TanStack Start: A Fresh Way to Build",[20,11161,11162,11164],{},[546,11163,11130],{}," represents a shift toward a more unified, type-safe, and scalable approach to building full-stack applications. It brings together ideas we already love—routing, data fetching, and server-first thinking—into a cohesive system.",[20,11166,11167],{},"Why it’s exciting:",[561,11169,11170,11173,11176,11179],{},[564,11171,11172],{},"End-to-end type safety",[564,11174,11175],{},"Powerful data management with TanStack Query",[564,11177,11178],{},"Server-first architecture without unnecessary complexity",[564,11180,11181],{},"Freedom from heavy abstractions",[10834,11183,11184,11188],{},[2459,11185,11187],{"id":11186},"what-tanstack-start-encourages","What TanStack Start Encourages",[561,11189,11190,11193,11196],{},[564,11191,11192],{},"Thinking in data, not just pages",[564,11194,11195],{},"Clear separation of concerns",[564,11197,11198],{},"Performance by default",[20,11200,11201],{},"It’s less about fighting the framework and more about building with confidence.",[31,11203,11205],{"id":11204},"ai-integrations-from-nice-to-have-to-essential","AI Integrations: From “Nice-to-Have” to Essential",[20,11207,11208],{},"AI is no longer experimental—it’s becoming foundational.",[20,11210,11211],{},"In 2026, AI integrations are helping teams:",[561,11213,11214,11217,11220,11223],{},[564,11215,11216],{},"Automate repetitive workflows",[564,11218,11219],{},"Enhance user experiences with personalization",[564,11221,11222],{},"Provide smarter search and recommendations",[564,11224,11225],{},"Improve developer productivity",[161,11227,11230],{"icon":11228,"title":11229},"🤖","AI as a Teammate",[20,11231,11232],{},"The best AI tools don’t replace developers—they amplify what developers can do.",[20,11234,11235],{},"From intelligent chat assistants to backend automation, AI is reshaping how products are built and how users interact with them.",[31,11237,11239],{"id":11238},"building-smarter-not-harder","Building Smarter, Not Harder",[20,11241,11242,11243,11246,11247,2230],{},"The real power comes from combining ",[546,11244,11245],{},"modern frameworks"," with ",[546,11248,11249],{},"AI-driven features",[47,11251,11254],{"className":1010,"code":11252,"filename":11253,"language":1012,"meta":55,"style":55},"const newYearStack = {\n  framework: \"TanStack Start\",\n  ai: \"Integrated at every layer\",\n  goal: \"Faster builds, smarter products\",\n};\n\nconsole.log(\"Welcome to 2026 🚀\");\n","future.ts",[39,11255,11256,11267,11277,11287,11297,11301,11305],{"__ignoreMap":55},[250,11257,11258,11260,11263,11265],{"class":252,"line":253},[250,11259,1181],{"class":786},[250,11261,11262],{"class":778}," newYearStack",[250,11264,1187],{"class":786},[250,11266,1118],{"class":912},[250,11268,11269,11272,11275],{"class":252,"line":113},[250,11270,11271],{"class":912},"  framework: ",[250,11273,11274],{"class":782},"\"TanStack Start\"",[250,11276,927],{"class":912},[250,11278,11279,11282,11285],{"class":252,"line":110},[250,11280,11281],{"class":912},"  ai: ",[250,11283,11284],{"class":782},"\"Integrated at every layer\"",[250,11286,927],{"class":912},[250,11288,11289,11292,11295],{"class":252,"line":269},[250,11290,11291],{"class":912},"  goal: ",[250,11293,11294],{"class":782},"\"Faster builds, smarter products\"",[250,11296,927],{"class":912},[250,11298,11299],{"class":252,"line":275},[250,11300,10945],{"class":912},[250,11302,11303],{"class":252,"line":281},[250,11304,795],{"emptyLinePlaceholder":129},[250,11306,11307,11309,11311,11313,11316],{"class":252,"line":287},[250,11308,10954],{"class":912},[250,11310,1859],{"class":774},[250,11312,1434],{"class":912},[250,11314,11315],{"class":782},"\"Welcome to 2026 🚀\"",[250,11317,1885],{"class":912},[500,11319,10962],{},{"title":55,"searchDepth":110,"depth":110,"links":11321},[11322,11323,11326,11327],{"id":11140,"depth":113,"text":11141},{"id":11158,"depth":113,"text":11159,"children":11324},[11325],{"id":11186,"depth":110,"text":11187},{"id":11204,"depth":113,"text":11205},{"id":11238,"depth":113,"text":11239},"2026-01-01","A New Year reflection on adopting modern frameworks like TanStack Start and integrating AI to build faster, smarter digital products.","https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1767533051\u002FPXL_20251114_022510096_kq4fyh.jpg",[11332,11333,11334,10986,11335],"tanstack","tanstack start","ai integration",2026,{},"\u002Fblog\u002Fnew-year-new-code",{"title":11115,"description":11329},"blog\u002Fnew-year-new-code","HRNYSokixOaSOra7wi-C5D-PN0FTgyqYLz-TF3johDs",{"id":11342,"title":11343,"author":11344,"body":11345,"canonical":115,"categories":115,"date":12010,"description":12011,"excerpt":12012,"extension":118,"img":12028,"keywords":12029,"language":3510,"meta":12030,"navigation":129,"ogImage":115,"path":12031,"rating":275,"readTime":132,"seo":12032,"stem":12033,"tag":3515,"__hash__":12034},"blog\u002Fblog\u002Fnitro-build.md","How to Use Nitro: Build and Deploy Modern Servers Anywhere",{"name":8,"img":10,"website":535},{"type":12,"value":11346,"toc":11990},[11347,11349,11361,11368,11370,11374,11379,11407,11414,11421,11423,11427,11431,11436,11462,11465,11471,11479,11483,11486,11498,11508,11510,11514,11525,11529,11535,11569,11579,11588,11590,11594,11603,11607,11672,11678,11680,11684,11692,11696,11748,11751,11787,11797,11799,11803,11815,11822,11824,11828,11835,11847,11856,11859,11886,11892,11894,11898,11909,11912,11914,11918,11930,11933,11944,11946,11948,11953,11985,11988],[15,11348,541],{"id":540},[20,11350,11351,11352,11355,11356,11358,11359],{},"Modern web applications increasingly require flexible, performant backends that can run ",[546,11353,11354],{},"anywhere from edge servers to traditional Node hosts",". That’s where ",[546,11357,555],{}," comes in — a lightweight, runtime-agnostic server toolkit that lets you build APIs, server logic, and backend functionality with minimal configuration and deploy it across platforms seamlessly. Nitro works standalone or as the server engine under frameworks like Nuxt and Vite-based apps. ",[3540,11360,3543],{"index":3542},[20,11362,11363,11364,11367],{},"In this post, we’ll explore how to ",[546,11365,11366],{},"use Nitro",", walk through practical examples, and show you how to build and deploy real server-side logic using this powerful tool.",[15,11369,748],{"id":747},[31,11371,11373],{"id":11372},"what-is-nitro-and-why-use-it","What Is Nitro and Why Use It?",[20,11375,3555,11376,11378],{},[546,11377,555],{}," is a server engine and framework designed to make backend development simple, portable, and efficient. It gives you:",[561,11380,11381,11387,11393,11399,11402],{},[564,11382,11383,11386],{},[546,11384,11385],{},"Out-of-the-box server routing"," with filesystem-based handlers",[564,11388,11389,11392],{},[546,11390,11391],{},"Multi-runtime support"," — Node, Bun, Deno, and more",[564,11394,11395,11398],{},[546,11396,11397],{},"Zero-config deployment"," for many platforms",[564,11400,11401],{},"Hot reloading and developer experience conveniences",[564,11403,11404,11405],{},"Minimal overhead — compiled output is very small ",[3540,11406,3570],{"index":1198},[20,11408,11409,11410,11413],{},"Instead of wrestling with server setups or environment differences, Nitro lets you focus on your ",[546,11411,11412],{},"handlers and business logic"," while it handles the rest.",[24,11415,11416],{"type":631},[20,11417,11418,11419],{},"Nitro works both as a standalone server toolkit and as the server engine powering full-stack frameworks like Nuxt — giving you flexibility to choose how you build your backend. ",[3540,11420,3582],{"index":1226},[72,11422],{},[31,11424,11426],{"id":11425},"getting-started-with-nitro","Getting Started with Nitro",[2459,11428,11430],{"id":11429},"step-1-create-a-new-nitro-project","Step 1: Create a New Nitro Project",[20,11432,11433,11434],{},"Nitro provides a starter template to help you bootstrap quickly (and you can even try it in your browser with an online playground). ",[3540,11435,3630],{"index":1249},[47,11437,11439],{"className":758,"code":11438,"language":761,"meta":55,"style":55},"npx create-nitro-app nitro-app\ncd nitro-app\nnpm install\n",[39,11440,11441,11450,11456],{"__ignoreMap":55},[250,11442,11443,11445,11447],{"class":252,"line":253},[250,11444,4200],{"class":774},[250,11446,4203],{"class":782},[250,11448,11449],{"class":782}," nitro-app\n",[250,11451,11452,11454],{"class":252,"line":113},[250,11453,874],{"class":778},[250,11455,11449],{"class":782},[250,11457,11458,11460],{"class":252,"line":110},[250,11459,4226],{"class":774},[250,11461,896],{"class":782},[20,11463,11464],{},"Once installed, you’ll have a Nitro project with a directory structure like:",[47,11466,11469],{"className":11467,"code":11468,"language":52},[50],"server\u002Froutes\u002F\nserver\u002Fapi\u002F\nserver\u002Futils\u002F\nserver\u002Fplugins\u002F\nnitro.config.ts\n",[39,11470,11468],{"__ignoreMap":55},[20,11472,11473,11474,2390],{},"These folders are where you’ll place your routes, logic, utilities, and plugins. (",[203,11475,555],{"href":11476,"rel":11477,"title":11478},"https:\u002F\u002Fnitro.build\u002Fguide?utm_source=chatgpt.com",[207],"Docs - Nitro",[2459,11480,11482],{"id":11481},"step-2-run-the-development-server","Step 2: Run the Development Server",[20,11484,11485],{},"Nitro comes with a built-in development server that supports hot reload:",[47,11487,11488],{"className":758,"code":196,"language":761,"meta":55,"style":55},[39,11489,11490],{"__ignoreMap":55},[250,11491,11492,11494,11496],{"class":252,"line":253},[250,11493,4226],{"class":774},[250,11495,1707],{"class":782},[250,11497,1710],{"class":782},[20,11499,11500,11501,11504,11505,2390],{},"By default, Nitro starts on ",[39,11502,11503],{},"http:\u002F\u002Flocalhost:3000\u002F",". You’ll see your handlers and static files served automatically. (",[203,11506,555],{"href":11476,"rel":11507,"title":11478},[207],[72,11509],{},[31,11511,11513],{"id":11512},"filesystem-routing-api-routes-handlers","Filesystem Routing: API Routes & Handlers",[20,11515,11516,11517,11520,11521,11524],{},"Just like many modern server frameworks, Nitro uses ",[546,11518,11519],{},"filesystem routing",": files you create under ",[39,11522,11523],{},"server\u002Froutes\u002F"," automatically become endpoints.",[2459,11526,11528],{"id":11527},"example-create-a-simple-api-route","Example: Create a Simple API Route",[20,11530,11531,11532,1007],{},"Create a file named ",[39,11533,11534],{},"server\u002Fapi\u002Fhello.ts",[47,11536,11538],{"className":1010,"code":11537,"language":1012,"meta":55,"style":55},"export default defineEventHandler(() => {\n  return { message: \"Hello from Nitro!\" }\n})\n",[39,11539,11540,11554,11565],{"__ignoreMap":55},[250,11541,11542,11544,11546,11548,11550,11552],{"class":252,"line":253},[250,11543,1019],{"class":786},[250,11545,1022],{"class":786},[250,11547,1109],{"class":774},[250,11549,1112],{"class":912},[250,11551,1115],{"class":786},[250,11553,1118],{"class":912},[250,11555,11556,11558,11560,11563],{"class":252,"line":113},[250,11557,1123],{"class":786},[250,11559,5773],{"class":912},[250,11561,11562],{"class":782},"\"Hello from Nitro!\"",[250,11564,8690],{"class":912},[250,11566,11567],{"class":252,"line":110},[250,11568,474],{"class":912},[20,11570,11571,11572,11575,11576,2390],{},"Visit ",[39,11573,11574],{},"http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fhello"," in the browser to see the JSON response. Nitro does the routing for you based on file paths. (",[203,11577,555],{"href":11476,"rel":11578,"title":11478},[207],[20,11580,11581,11582,11584,11585,3698],{},"Nitro routes can be nested — create folders within ",[39,11583,11523],{}," to structure your API and handlers naturally. (",[203,11586,555],{"href":11476,"rel":11587,"title":11478},[207],[72,11589],{},[31,11591,11593],{"id":11592},"using-utility-functions","Using Utility Functions",[20,11595,11596,11597,2390],{},"Nitro auto-imports useful utilities that help you build more expressive handlers without boilerplate. For example, parsing query parameters, reading cookies, or handling headers can be done with helpers from h3 (Nitro’s HTTP utility library under the hood). (",[203,11598,11602],{"href":11599,"rel":11600,"title":11601},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F3.x\u002Fguide\u002Fconcepts\u002Fserver-engine?utm_source=chatgpt.com",[207],"Server Engine · Nuxt Concepts v3","Nuxt",[2459,11604,11606],{"id":11605},"example-reading-query-parameters","Example: Reading Query Parameters",[47,11608,11610],{"className":1010,"code":11609,"language":1012,"meta":55,"style":55},"export default defineEventHandler((event) => {\n  const { name } = getQuery(event)\n  return { greeting: `Hello ${name ?? \"World\"}` }\n})\n",[39,11611,11612,11630,11648,11668],{"__ignoreMap":55},[250,11613,11614,11616,11618,11620,11622,11624,11626,11628],{"class":252,"line":253},[250,11615,1019],{"class":786},[250,11617,1022],{"class":786},[250,11619,1109],{"class":774},[250,11621,1574],{"class":912},[250,11623,1443],{"class":1370},[250,11625,1446],{"class":912},[250,11627,1115],{"class":786},[250,11629,1118],{"class":912},[250,11631,11632,11634,11636,11638,11641,11643,11646],{"class":252,"line":113},[250,11633,1455],{"class":786},[250,11635,7768],{"class":912},[250,11637,6563],{"class":778},[250,11639,11640],{"class":912}," } ",[250,11642,1416],{"class":786},[250,11644,11645],{"class":774}," getQuery",[250,11647,9077],{"class":912},[250,11649,11650,11652,11655,11658,11660,11663,11666],{"class":252,"line":110},[250,11651,1123],{"class":786},[250,11653,11654],{"class":912}," { greeting: ",[250,11656,11657],{"class":782},"`Hello ${",[250,11659,6563],{"class":912},[250,11661,11662],{"class":786}," ??",[250,11664,11665],{"class":782}," \"World\"}`",[250,11667,8690],{"class":912},[250,11669,11670],{"class":252,"line":269},[250,11671,474],{"class":912},[20,11673,11571,11674,11677],{},[39,11675,11676],{},"\u002Fapi\u002Fhello?name=Vantol"," and Nitro will handle parsing automatically.",[72,11679],{},[31,11681,11683],{"id":11682},"configuration-with-nitroconfigts","Configuration with nitro.config.ts",[20,11685,11686,11687,2390],{},"Nitro can be customized via a configuration file. You might want to set runtime config values or adjust build behavior. (",[203,11688,555],{"href":11689,"rel":11690,"title":11691},"https:\u002F\u002Fnitro.build\u002Fguide\u002Fconfiguration\u002F?utm_source=chatgpt.com",[207],"Configuration - Nitro",[2459,11693,11695],{"id":11694},"example-runtime-config","Example: Runtime Config",[47,11697,11699],{"className":1010,"code":11698,"language":1012,"meta":55,"style":55},"import { defineNitroConfig } from \"nitro\u002Fconfig\";\n\nexport default defineNitroConfig({\n  runtimeConfig: {\n    apiToken: \"dev_token\"\n  }\n});\n",[39,11700,11701,11714,11718,11728,11732,11740,11744],{"__ignoreMap":55},[250,11702,11703,11705,11707,11709,11712],{"class":252,"line":253},[250,11704,1763],{"class":786},[250,11706,8904],{"class":912},[250,11708,1769],{"class":786},[250,11710,11711],{"class":782}," \"nitro\u002Fconfig\"",[250,11713,1379],{"class":912},[250,11715,11716],{"class":252,"line":113},[250,11717,795],{"emptyLinePlaceholder":129},[250,11719,11720,11722,11724,11726],{"class":252,"line":110},[250,11721,1019],{"class":786},[250,11723,1022],{"class":786},[250,11725,8922],{"class":774},[250,11727,1028],{"class":912},[250,11729,11730],{"class":252,"line":269},[250,11731,8929],{"class":912},[250,11733,11734,11737],{"class":252,"line":275},[250,11735,11736],{"class":912},"    apiToken: ",[250,11738,11739],{"class":782},"\"dev_token\"\n",[250,11741,11742],{"class":252,"line":281},[250,11743,986],{"class":912},[250,11745,11746],{"class":252,"line":287},[250,11747,1077],{"class":912},[20,11749,11750],{},"Then, within handlers you can access this config:",[47,11752,11754],{"className":1010,"code":11753,"language":1012,"meta":55,"style":55},"export default defineEventHandler((event) => {\n  return useRuntimeConfig().apiToken;\n});\n",[39,11755,11756,11774,11783],{"__ignoreMap":55},[250,11757,11758,11760,11762,11764,11766,11768,11770,11772],{"class":252,"line":253},[250,11759,1019],{"class":786},[250,11761,1022],{"class":786},[250,11763,1109],{"class":774},[250,11765,1574],{"class":912},[250,11767,1443],{"class":1370},[250,11769,1446],{"class":912},[250,11771,1115],{"class":786},[250,11773,1118],{"class":912},[250,11775,11776,11778,11780],{"class":252,"line":113},[250,11777,1123],{"class":786},[250,11779,8988],{"class":774},[250,11781,11782],{"class":912},"().apiToken;\n",[250,11784,11785],{"class":252,"line":110},[250,11786,1077],{"class":912},[20,11788,11789,11790,11793,11794,2390],{},"You can override these values with environment variables prefixed with ",[39,11791,11792],{},"NITRO_"," for different environments (development, staging, production). (",[203,11795,555],{"href":11689,"rel":11796,"title":11691},[207],[72,11798],{},[31,11800,11802],{"id":11801},"serving-static-files-and-custom-renderers","Serving Static Files and Custom Renderers",[20,11804,11805,11806,11809,11810,2390],{},"Nitro can serve static files like HTML, images, and assets from unconfigured folders. It also supports fallback renderers — for example serving an ",[39,11807,11808],{},"index.html"," for all non-API routes in single-page applications. (",[203,11811,555],{"href":11812,"rel":11813,"title":11814},"https:\u002F\u002Fv3.nitro.build\u002Fdocs\u002Frenderer?utm_source=chatgpt.com",[207],"Nitro Renderer - Nitro",[20,11816,11817,11818,11821],{},"This makes Nitro useful for ",[546,11819,11820],{},"hybrid applications"," that combine server APIs with frontend PWAs or SPAs.",[72,11823],{},[31,11825,11827],{"id":11826},"deploying-your-nitro-app","Deploying Your Nitro App",[20,11829,11830,11831,11834],{},"One of Nitro’s strengths is its ability to ",[546,11832,11833],{},"deploy to multiple environments with minimal changes",". After building your app:",[47,11836,11837],{"className":758,"code":10577,"language":761,"meta":55,"style":55},[39,11838,11839],{"__ignoreMap":55},[250,11840,11841,11843,11845],{"class":252,"line":253},[250,11842,4226],{"class":774},[250,11844,1707],{"class":782},[250,11846,3234],{"class":782},[20,11848,11849,11850,11852,11853,2390],{},"Nitro outputs a production-ready server in the ",[39,11851,10593],{}," directory that can run on various targets. (",[203,11854,555],{"href":11476,"rel":11855,"title":11478},[207],[20,11857,11858],{},"You can deploy to:",[561,11860,11861,11869,11875],{},[564,11862,11863,11865,11866],{},[546,11864,10599],{}," — run ",[39,11867,11868],{},".output\u002Fserver\u002Findex.mjs",[564,11870,11871,11874],{},[546,11872,11873],{},"Edge platforms"," — Cloudflare Workers, Deno Deploy with presets",[564,11876,11877,11880,11881,2390],{},[546,11878,11879],{},"Serverless providers"," — AWS Lambda, Vercel, Netlify, etc. (",[203,11882,555],{"href":11883,"rel":11884,"title":11885},"https:\u002F\u002Fnitro.build\u002Fdeploy?utm_source=chatgpt.com",[207],"Deploy - Nitro",[20,11887,11888,11889,2390],{},"Nitro often autodetects the hosting provider and configures itself accordingly — meaning fewer environment-specific tweaks. (",[203,11890,555],{"href":11883,"rel":11891,"title":11885},[207],[72,11893],{},[31,11895,11897],{"id":11896},"advanced-plugins-middleware","Advanced: Plugins & Middleware",[20,11899,11900,11901,11904,11905,11908],{},"If you need to extend Nitro’s behavior, you can create your own ",[546,11902,11903],{},"plugins"," in ",[39,11906,11907],{},"server\u002Fplugins\u002F",". These let you hook into the lifecycle of requests, register middleware, or augment server behavior in powerful ways.",[20,11910,11911],{},"This pattern helps modularize cross-cutting concerns like authentication, logging, or error reporting.",[72,11913],{},[31,11915,11917],{"id":11916},"example-full-api-frontend-integration","Example: Full API + Frontend Integration",[20,11919,11920,11921,11924,11925,2390],{},"You can integrate Nitro with frontend frameworks like Vite to create ",[546,11922,11923],{},"full-stack apps"," where your UI and backend live in one project. Nitro handles server APIs and static assets, while Vite serves HMR and frontend bundling. (",[203,11926,555],{"href":11927,"rel":11928,"title":11929},"https:\u002F\u002Fv3.nitro.build\u002Fdocs\u002Fquick-start?utm_source=chatgpt.com",[207],"Quick Start - Nitro",[20,11931,11932],{},"This setup enables:",[561,11934,11935,11938,11941],{},[564,11936,11937],{},"Server APIs without CORS complexity",[564,11939,11940],{},"Sharing code between backend and frontend",[564,11942,11943],{},"Fast development workflows with hot reload",[72,11945],{},[15,11947,3352],{"id":3351},[20,11949,11950,11952],{},[546,11951,555],{}," is an incredibly flexible and powerful tool for modern backend development. Whether you’re building APIs, hybrid apps, or full-stack projects, Nitro offers:",[561,11954,11955,11960,11965,11970,11975],{},[564,11956,11957],{},[546,11958,11959],{},"Filesystem routing and simple handlers",[564,11961,11962],{},[546,11963,11964],{},"Configurable runtime environments",[564,11966,11967],{},[546,11968,11969],{},"Cross-runtime deployment",[564,11971,11972],{},[546,11973,11974],{},"Out-of-the-box utility functions and developer experience",[564,11976,11977,1440,11980,2390],{},[546,11978,11979],{},"Easy integration with frontend frameworks",[203,11981,555],{"href":11982,"rel":11983,"title":11984},"https:\u002F\u002Fnitro.build\u002F?utm_source=chatgpt.com",[207],"Nitro - Next Generation Server Toolkit",[20,11986,11987],{},"With these capabilities, Nitro enables developers to build fast, scalable, and portable server apps without sacrificing simplicity — making it a strong choice for teams building modern web applications. 🚀",[500,11989,9304],{},{"title":55,"searchDepth":110,"depth":110,"links":11991},[11992,11993,11997,12000,12003,12006,12007,12008,12009],{"id":11372,"depth":113,"text":11373},{"id":11425,"depth":113,"text":11426,"children":11994},[11995,11996],{"id":11429,"depth":110,"text":11430},{"id":11481,"depth":110,"text":11482},{"id":11512,"depth":113,"text":11513,"children":11998},[11999],{"id":11527,"depth":110,"text":11528},{"id":11592,"depth":113,"text":11593,"children":12001},[12002],{"id":11605,"depth":110,"text":11606},{"id":11682,"depth":113,"text":11683,"children":12004},[12005],{"id":11694,"depth":110,"text":11695},{"id":11801,"depth":113,"text":11802},{"id":11826,"depth":113,"text":11827},{"id":11896,"depth":113,"text":11897},{"id":11916,"depth":113,"text":11917},"2026-01-20","An in-depth look at Nitro — what it is, how to use it to build servers and APIs, and practical steps to get started with real examples.",{"type":12,"value":12013},[12014,12016,12024],[15,12015,541],{"id":540},[20,12017,11351,12018,11355,12020,11358,12022],{},[546,12019,11354],{},[546,12021,555],{},[3540,12023,3543],{"index":3542},[20,12025,11363,12026,11367],{},[546,12027,11366],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085",[3504,10784,126,3509,9373],{},"\u002Fblog\u002Fnitro-build",{"title":11343,"description":12011},"blog\u002Fnitro-build","rDn6LRPhkhACMYyhkv_Kcexsf6uRlCOFgdqKwauBfhg",{"id":12036,"title":12037,"author":12038,"body":12039,"canonical":115,"categories":115,"date":12640,"description":12641,"excerpt":12642,"extension":118,"img":12662,"keywords":12663,"language":3510,"meta":12665,"navigation":129,"ogImage":115,"path":12666,"rating":275,"readTime":293,"seo":12667,"stem":12668,"tag":3515,"__hash__":12669},"blog\u002Fblog\u002Fnitro-plugins.md","Extending Nitro with Plugins: How to Build and Ideas for Real World Use",{"name":8,"img":10,"website":535},{"type":12,"value":12040,"toc":12622},[12041,12043,12052,12055,12066,12068,12072,12080,12084,12094,12097,12142,12150,12154,12163,12166,12251,12254,12341,12345,12348,12355,12358,12369,12372,12374,12381,12384,12492,12495,12497,12504,12507,12510,12513,12524,12526,12533,12536,12539,12577,12579,12586,12589,12592,12594,12598,12603,12605,12607,12610,12613,12619],[15,12042,541],{"id":540},[20,12044,12045,12046,12049,12050],{},"Nitro is a lightweight, runtime-agnostic server framework that lets you build fast APIs and backends deployable anywhere. But what happens when you need more than basic routes? That’s where ",[546,12047,12048],{},"Nitro plugins"," come in — a powerful way to hook into Nitro’s runtime and extend its behavior.:contentReference",[250,12051,3570],{"index":1198},[20,12053,12054],{},"In this post we’ll cover:",[561,12056,12057,12060,12063],{},[564,12058,12059],{},"What Nitro plugins are",[564,12061,12062],{},"How to create one",[564,12064,12065],{},"Useful plugin ideas you can build for real applications",[15,12067,748],{"id":747},[31,12069,12071],{"id":12070},"what-are-nitro-plugins","What Are Nitro Plugins?",[20,12073,12074,12075,12077,12078],{},"Nitro plugins allow you to extend Nitro’s runtime behavior in a modular and reusable way. They’re executed when the server starts and can hook into internal lifecycle events, letting you react to incoming requests, errors, responses, and more. Nitro registers plugins automatically from your ",[39,12076,11907],{}," directory or ones you list in the Nitro config.:contentReference",[250,12079,3582],{"index":1226},[31,12081,12083],{"id":12082},"how-to-create-a-simple-nitro-plugin","How to Create a Simple Nitro Plugin",[20,12085,12086,12087,12090,12091,12093],{},"Creating a Nitro plugin starts with the ",[39,12088,12089],{},"defineNitroPlugin"," function. Plugins receive the ",[39,12092,10277],{}," context — the runtime environment you can interact with.",[20,12095,12096],{},"For example, a simple plugin that logs when the server starts could look like:",[47,12098,12100],{"className":1010,"code":12099,"language":1012,"meta":55,"style":55},"\u002F\u002F server\u002Fplugins\u002Flogger.ts\nexport default defineNitroPlugin((nitroApp) => {\n  console.log(\"Nitro server initialized!\")\n})\n",[39,12101,12102,12107,12125,12138],{"__ignoreMap":55},[250,12103,12104],{"class":252,"line":253},[250,12105,12106],{"class":768},"\u002F\u002F server\u002Fplugins\u002Flogger.ts\n",[250,12108,12109,12111,12113,12115,12117,12119,12121,12123],{"class":252,"line":113},[250,12110,1019],{"class":786},[250,12112,1022],{"class":786},[250,12114,10272],{"class":774},[250,12116,1574],{"class":912},[250,12118,10277],{"class":1370},[250,12120,1446],{"class":912},[250,12122,1115],{"class":786},[250,12124,1118],{"class":912},[250,12126,12127,12129,12131,12133,12136],{"class":252,"line":110},[250,12128,1856],{"class":912},[250,12130,1859],{"class":774},[250,12132,1434],{"class":912},[250,12134,12135],{"class":782},"\"Nitro server initialized!\"",[250,12137,4852],{"class":912},[250,12139,12140],{"class":252,"line":269},[250,12141,474],{"class":912},[20,12143,12144,12145,12147,12148,2390],{},"Nitro runs your plugin as part of server initialization. You can even register plugins from custom directories by adding them to ",[39,12146,8892],{},".([nitro.build]",[250,12149,1226],{},[31,12151,12153],{"id":12152},"using-nitro-lifecycle-hooks","Using Nitro Lifecycle Hooks",[20,12155,12156,12157,12160,12161,2390],{},"Plugins become especially powerful when you use ",[546,12158,12159],{},"lifecycle hooks",". Nitro exposes several event hooks that let you react to server behavior — from incoming requests to errors and responses.([nitro.build]",[250,12162,1226],{},[20,12164,12165],{},"Here’s a plugin that logs every request URL:",[47,12167,12169],{"className":1010,"code":12168,"language":1012,"meta":55,"style":55},"\u002F\u002F server\u002Fplugins\u002Frequest-logger.ts\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook(\"request\", (event) => {\n    console.log(`[Request] ${event.method} ${event.path}`)\n  })\n})\n",[39,12170,12171,12176,12194,12214,12243,12247],{"__ignoreMap":55},[250,12172,12173],{"class":252,"line":253},[250,12174,12175],{"class":768},"\u002F\u002F server\u002Fplugins\u002Frequest-logger.ts\n",[250,12177,12178,12180,12182,12184,12186,12188,12190,12192],{"class":252,"line":113},[250,12179,1019],{"class":786},[250,12181,1022],{"class":786},[250,12183,10272],{"class":774},[250,12185,1574],{"class":912},[250,12187,10277],{"class":1370},[250,12189,1446],{"class":912},[250,12191,1115],{"class":786},[250,12193,1118],{"class":912},[250,12195,12196,12198,12200,12202,12204,12206,12208,12210,12212],{"class":252,"line":110},[250,12197,10288],{"class":912},[250,12199,10291],{"class":774},[250,12201,1434],{"class":912},[250,12203,10296],{"class":782},[250,12205,10299],{"class":912},[250,12207,1443],{"class":1370},[250,12209,1446],{"class":912},[250,12211,1115],{"class":786},[250,12213,1118],{"class":912},[250,12215,12216,12218,12220,12222,12225,12227,12229,12231,12233,12235,12237,12239,12241],{"class":252,"line":269},[250,12217,10312],{"class":912},[250,12219,1859],{"class":774},[250,12221,1434],{"class":912},[250,12223,12224],{"class":782},"`[Request] ${",[250,12226,1443],{"class":912},[250,12228,2230],{"class":782},[250,12230,10342],{"class":912},[250,12232,10345],{"class":782},[250,12234,1443],{"class":912},[250,12236,2230],{"class":782},[250,12238,10352],{"class":912},[250,12240,2355],{"class":782},[250,12242,4852],{"class":912},[250,12244,12245],{"class":252,"line":275},[250,12246,10365],{"class":912},[250,12248,12249],{"class":252,"line":281},[250,12250,474],{"class":912},[20,12252,12253],{},"And you can also hook into errors to capture and log them:",[47,12255,12257],{"className":1010,"code":12256,"language":1012,"meta":55,"style":55},"\u002F\u002F server\u002Fplugins\u002Ferror-catcher.ts\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook(\"error\", (error, { event }) => {\n    console.error(`Error at ${event.path}:`, error)\n  })\n})\n",[39,12258,12259,12264,12282,12310,12333,12337],{"__ignoreMap":55},[250,12260,12261],{"class":252,"line":253},[250,12262,12263],{"class":768},"\u002F\u002F server\u002Fplugins\u002Ferror-catcher.ts\n",[250,12265,12266,12268,12270,12272,12274,12276,12278,12280],{"class":252,"line":113},[250,12267,1019],{"class":786},[250,12269,1022],{"class":786},[250,12271,10272],{"class":774},[250,12273,1574],{"class":912},[250,12275,10277],{"class":1370},[250,12277,1446],{"class":912},[250,12279,1115],{"class":786},[250,12281,1118],{"class":912},[250,12283,12284,12286,12288,12290,12293,12295,12298,12301,12303,12306,12308],{"class":252,"line":110},[250,12285,10288],{"class":912},[250,12287,10291],{"class":774},[250,12289,1434],{"class":912},[250,12291,12292],{"class":782},"\"error\"",[250,12294,10299],{"class":912},[250,12296,12297],{"class":1370},"error",[250,12299,12300],{"class":912},", { ",[250,12302,1443],{"class":1370},[250,12304,12305],{"class":912}," }) ",[250,12307,1115],{"class":786},[250,12309,1118],{"class":912},[250,12311,12312,12314,12316,12318,12321,12323,12325,12327,12330],{"class":252,"line":269},[250,12313,10312],{"class":912},[250,12315,12297],{"class":774},[250,12317,1434],{"class":912},[250,12319,12320],{"class":782},"`Error at ${",[250,12322,1443],{"class":912},[250,12324,2230],{"class":782},[250,12326,10352],{"class":912},[250,12328,12329],{"class":782},"}:`",[250,12331,12332],{"class":912},", error)\n",[250,12334,12335],{"class":252,"line":275},[250,12336,10365],{"class":912},[250,12338,12339],{"class":252,"line":281},[250,12340,474],{"class":912},[31,12342,12344],{"id":12343},"plugin-ideas-you-can-build-today","Plugin Ideas You Can Build Today",[20,12346,12347],{},"Here are a handful of practical Nitro plugin ideas you could build into your app — especially handy for real projects like an e-commerce backend, food truck API, or admin dashboard API.",[2459,12349,12351,12352],{"id":12350},"_1-request-metrics-analytics-plugin","📊 1. ",[546,12353,12354],{},"Request Metrics & Analytics Plugin",[20,12356,12357],{},"Track performance of your endpoints in real time.",[561,12359,12360,12363,12366],{},[564,12361,12362],{},"Count hits per route",[564,12364,12365],{},"Record timing and latency",[564,12367,12368],{},"Write structured logs or push to analytics back end",[20,12370,12371],{},"Example benefit: track how many orders per hour your API gets and surface performance bottlenecks.",[72,12373],{},[2459,12375,12377,12378],{"id":12376},"_2-api-key-token-validation-plugin","🔐 2. ",[546,12379,12380],{},"API Key \u002F Token Validation Plugin",[20,12382,12383],{},"Centralize API key checks before your route handlers run.",[47,12385,12387],{"className":1010,"code":12386,"language":1012,"meta":55,"style":55},"\u002F\u002F server\u002Fplugins\u002Fapi-auth.ts\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook(\"request\", (event) => {\n    const key = event.headers.get(\"x-api-key\")\n    if (!isValidKey(key)) {\n      throw createError({ statusCode: 401, statusMessage: \"Unauthorized\" })\n    }\n  })\n})\n",[39,12388,12389,12394,12412,12432,12450,12464,12480,12484,12488],{"__ignoreMap":55},[250,12390,12391],{"class":252,"line":253},[250,12392,12393],{"class":768},"\u002F\u002F server\u002Fplugins\u002Fapi-auth.ts\n",[250,12395,12396,12398,12400,12402,12404,12406,12408,12410],{"class":252,"line":113},[250,12397,1019],{"class":786},[250,12399,1022],{"class":786},[250,12401,10272],{"class":774},[250,12403,1574],{"class":912},[250,12405,10277],{"class":1370},[250,12407,1446],{"class":912},[250,12409,1115],{"class":786},[250,12411,1118],{"class":912},[250,12413,12414,12416,12418,12420,12422,12424,12426,12428,12430],{"class":252,"line":110},[250,12415,10288],{"class":912},[250,12417,10291],{"class":774},[250,12419,1434],{"class":912},[250,12421,10296],{"class":782},[250,12423,10299],{"class":912},[250,12425,1443],{"class":1370},[250,12427,1446],{"class":912},[250,12429,1115],{"class":786},[250,12431,1118],{"class":912},[250,12433,12434,12436,12438,12440,12442,12444,12446,12448],{"class":252,"line":269},[250,12435,6403],{"class":786},[250,12437,10497],{"class":778},[250,12439,1187],{"class":786},[250,12441,10502],{"class":912},[250,12443,6062],{"class":774},[250,12445,1434],{"class":912},[250,12447,10509],{"class":782},[250,12449,4852],{"class":912},[250,12451,12452,12454,12456,12458,12461],{"class":252,"line":275},[250,12453,6463],{"class":786},[250,12455,1440],{"class":912},[250,12457,1491],{"class":786},[250,12459,12460],{"class":774},"isValidKey",[250,12462,12463],{"class":912},"(key)) {\n",[250,12465,12466,12468,12470,12472,12474,12476,12478],{"class":252,"line":281},[250,12467,6475],{"class":786},[250,12469,1520],{"class":774},[250,12471,10172],{"class":912},[250,12473,10538],{"class":778},[250,12475,10177],{"class":912},[250,12477,10543],{"class":782},[250,12479,4599],{"class":912},[250,12481,12482],{"class":252,"line":287},[250,12483,3684],{"class":912},[250,12485,12486],{"class":252,"line":293},[250,12487,10365],{"class":912},[250,12489,12490],{"class":252,"line":299},[250,12491,474],{"class":912},[20,12493,12494],{},"This saves you from adding auth logic inside each route and ensures consistent security.",[72,12496],{},[2459,12498,12500,12501],{"id":12499},"_3-response-caching-plugin","📦 3. ",[546,12502,12503],{},"Response Caching Plugin",[20,12505,12506],{},"A plugin that caches successful GET responses in memory or Redis to speed up repeat calls.",[20,12508,12509],{},"Useful for endpoints like menus or business hours that don’t change often.",[20,12511,12512],{},"Example concept:",[561,12514,12515,12518,12521],{},[564,12516,12517],{},"Check cache on request",[564,12519,12520],{},"Bypass expensive data work if present",[564,12522,12523],{},"Store responses with TTL",[72,12525],{},[2459,12527,12529,12530],{"id":12528},"_4-request-body-sanitizer-plugin","📥 4. ",[546,12531,12532],{},"Request Body Sanitizer Plugin",[20,12534,12535],{},"Automatically sanitize or validate JSON bodies before they hit route handlers.",[20,12537,12538],{},"This helps enforce stricter API contracts and cleaner data at the router level.",[47,12540,12542],{"className":1010,"code":12541,"language":1012,"meta":55,"style":55},"nitroApp.hooks.hook(\"request\", (event) => {\n  sanitize(event.body)\n})\n",[39,12543,12544,12565,12573],{"__ignoreMap":55},[250,12545,12546,12549,12551,12553,12555,12557,12559,12561,12563],{"class":252,"line":253},[250,12547,12548],{"class":912},"nitroApp.hooks.",[250,12550,10291],{"class":774},[250,12552,1434],{"class":912},[250,12554,10296],{"class":782},[250,12556,10299],{"class":912},[250,12558,1443],{"class":1370},[250,12560,1446],{"class":912},[250,12562,1115],{"class":786},[250,12564,1118],{"class":912},[250,12566,12567,12570],{"class":252,"line":113},[250,12568,12569],{"class":774},"  sanitize",[250,12571,12572],{"class":912},"(event.body)\n",[250,12574,12575],{"class":252,"line":110},[250,12576,474],{"class":912},[72,12578],{},[2459,12580,12582,12583],{"id":12581},"_5-feature-flag-config-plugin","🛠 5. ",[546,12584,12585],{},"Feature Flag & Config Plugin",[20,12587,12588],{},"Load feature flags or custom runtime config from environment, remote store, or a file, and broadcast them server-wide.",[20,12590,12591],{},"Example: enable\u002Fdisable special holiday menus, seasonal pricing, or debug logging without code changes.",[72,12593],{},[31,12595,12597],{"id":12596},"when-plugins-run","When Plugins Run",[20,12599,12600,12601,2390],{},"Nitro plugins execute once during server startup and the hooks you register can fire at various points during request processing — giving you centralized control over behavior, logging, auth, or data flow.([v3.nitro.build]",[250,12602,1198],{},[72,12604],{},[15,12606,3352],{"id":3351},[20,12608,12609],{},"Nitro’s plugin system gives you the flexibility to extend your server logic beyond basic routes — letting you implement logging, auth, caching, monitoring, and more in reusable packages.",[20,12611,12612],{},"If you’re building an API that needs observability, security, or business logic centralized in one place, plugins make Nitro even more powerful without complicating your routes.🚀",[20,12614,12615,12616,1491],{},"Let me know if you want ",[546,12617,12618],{},"tutorial examples for those plugin ideas",[500,12620,12621],{},"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 .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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}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}",{"title":55,"searchDepth":110,"depth":110,"links":12623},[12624,12625,12626,12627,12639],{"id":12070,"depth":113,"text":12071},{"id":12082,"depth":113,"text":12083},{"id":12152,"depth":113,"text":12153},{"id":12343,"depth":113,"text":12344,"children":12628},[12629,12631,12633,12635,12637],{"id":12350,"depth":110,"text":12630},"📊 1. Request Metrics & Analytics Plugin",{"id":12376,"depth":110,"text":12632},"🔐 2. API Key \u002F Token Validation Plugin",{"id":12499,"depth":110,"text":12634},"📦 3. Response Caching Plugin",{"id":12528,"depth":110,"text":12636},"📥 4. Request Body Sanitizer Plugin",{"id":12581,"depth":110,"text":12638},"🛠 5. Feature Flag & Config Plugin",{"id":12596,"depth":113,"text":12597},"2026-01-29","Learn how to create Nitro plugins to extend your server’s behavior, with examples and practical plugin ideas you can build into your application.",{"type":12,"value":12643},[12644,12646,12652,12654],[15,12645,541],{"id":540},[20,12647,12045,12648,12049,12650],{},[546,12649,12048],{},[250,12651,3570],{"index":1198},[20,12653,12054],{},[561,12655,12656,12658,12660],{},[564,12657,12059],{},[564,12659,12062],{},[564,12661,12065],{},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1769836111\u002FNitroFull_ww4pbg.png",[3504,12664,3507,3509,8234],"nitro plugin",{},"\u002Fblog\u002Fnitro-plugins",{"title":12037,"description":12641},"blog\u002Fnitro-plugins","1TtyjRpEqgljjXADT7cjszOkC3kzSLiBPCJnttW7QoY",{"id":12671,"title":12672,"author":12673,"body":12674,"canonical":115,"categories":115,"date":12959,"description":12960,"excerpt":12961,"extension":118,"img":12662,"keywords":12989,"language":3510,"meta":12990,"navigation":129,"ogImage":115,"path":12991,"rating":275,"readTime":316,"seo":12992,"stem":12993,"tag":3515,"__hash__":12994},"blog\u002Fblog\u002Fnitro-tutorial.md","Building Real Nitro Plugins: Step-by-Step Tutorials You Can Use Today",{"name":8,"img":10,"website":535},{"type":12,"value":12675,"toc":12948},[12676,12678,12689,12692,12706,12716,12720,12723,12765,12769,12772,12775,12781,12784,12788,12791,12794,12797,12800,12803,12806,12810,12813,12819,12822,12828,12830,12834,12837,12840,12843,12847,12850,12853,12859,12862,12865,12871,12873,12877,12880,12883,12886,12890,12893,12896,12899,12903,12906,12909,12912,12916,12919,12922,12926,12929,12932,12935,12938,12940,12943,12946],[15,12677,541],{"id":540},[20,12679,12680,12681,12684,12685,12688],{},"In the previous post, we explored ",[546,12682,12683],{},"what Nitro plugins are"," and why they’re one of Nitro’s most powerful features. In this tutorial-focused follow-up, we’ll ",[546,12686,12687],{},"build real Nitro plugins step by step"," — the kind you’d actually use in production.",[20,12690,12691],{},"By the end, you’ll know how to create plugins for:",[561,12693,12694,12697,12700,12703],{},[564,12695,12696],{},"Request logging",[564,12698,12699],{},"API key authentication",[564,12701,12702],{},"Response caching",[564,12704,12705],{},"Feature flags and runtime configuration",[20,12707,12708,12709,12711,12712,12715],{},"All examples use ",[546,12710,3510],{}," and work in ",[546,12713,12714],{},"Nuxt + Nitro"," or standalone Nitro apps.",[15,12717,12719],{"id":12718},"project-setup","Project Setup",[20,12721,12722],{},"Assuming a Nitro or Nuxt project, your folder structure should include:",[47,12724,12728],{"className":12725,"code":12726,"language":12727,"meta":55,"style":55},"language-txt shiki shiki-themes github-light github-dark","server\u002F\n  plugins\u002F\n    logger.ts\n    auth.ts\n    cache.ts\n    feature-flags.ts\nNitro automatically loads plugins from server\u002Fplugins\u002F.\n","txt",[39,12729,12730,12735,12740,12745,12750,12755,12760],{"__ignoreMap":55},[250,12731,12732],{"class":252,"line":253},[250,12733,12734],{},"server\u002F\n",[250,12736,12737],{"class":252,"line":113},[250,12738,12739],{},"  plugins\u002F\n",[250,12741,12742],{"class":252,"line":110},[250,12743,12744],{},"    logger.ts\n",[250,12746,12747],{"class":252,"line":269},[250,12748,12749],{},"    auth.ts\n",[250,12751,12752],{"class":252,"line":275},[250,12753,12754],{},"    cache.ts\n",[250,12756,12757],{"class":252,"line":281},[250,12758,12759],{},"    feature-flags.ts\n",[250,12761,12762],{"class":252,"line":287},[250,12763,12764],{},"Nitro automatically loads plugins from server\u002Fplugins\u002F.\n",[15,12766,12768],{"id":12767},"tutorial-1-request-logger-plugin","Tutorial 1: Request Logger Plugin",[20,12770,12771],{},"Goal\nLog every incoming request with method, path, and timing.",[20,12773,12774],{},"Step 1: Create the Plugin\n\u002F\u002F server\u002Fplugins\u002Flogger.ts\nexport default defineNitroPlugin((nitroApp) => {\nnitroApp.hooks.hook(\"request\", (event) => {\nconst start = Date.now()",[47,12776,12779],{"className":12777,"code":12778,"language":52},[50],"event.node.res.on(\"finish\", () => {\n  const duration = Date.now() - start\n  console.log(\n    `[${event.method}] ${event.path} - ${duration}ms`\n  )\n})\n",[39,12780,12778],{"__ignoreMap":55},[20,12782,12783],{},"})\n})",[31,12785,12787],{"id":12786},"what-this-does","What This Does",[20,12789,12790],{},"Hooks into every request",[20,12792,12793],{},"Measures request duration",[20,12795,12796],{},"Logs after the response finishes",[20,12798,12799],{},"When to Use\nDebugging slow endpoints",[20,12801,12802],{},"Monitoring API usage",[20,12804,12805],{},"Lightweight analytics",[31,12807,12809],{"id":12808},"tutorial-2-api-key-authentication-plugin","Tutorial 2: API Key Authentication Plugin",[20,12811,12812],{},"Goal\nProtect your API by validating an API key before routes run.",[20,12814,12815,12816,2390],{},"Step 1: Define a Validator\nconst VALID_KEYS = new Set(",[250,12817,12818],{},"\"dev-key-123\", \"prod-key-456\"",[20,12820,12821],{},"function isValidKey(key?: string | null) {\nreturn key && VALID_KEYS.has(key)\n}\nStep 2: Create the Plugin\n\u002F\u002F server\u002Fplugins\u002Fauth.ts\nexport default defineNitroPlugin((nitroApp) => {\nnitroApp.hooks.hook(\"request\", (event) => {\nconst apiKey = event.headers.get(\"x-api-key\")",[47,12823,12826],{"className":12824,"code":12825,"language":52},[50],"if (!isValidKey(apiKey)) {\n  throw createError({\n    statusCode: 401,\n    statusMessage: \"Invalid API Key\"\n  })\n}\n",[39,12827,12825],{"__ignoreMap":55},[20,12829,12783],{},[31,12831,12833],{"id":12832},"why-this-is-powerful","Why This Is Powerful",[20,12835,12836],{},"No auth logic in individual routes",[20,12838,12839],{},"Centralized, reusable security",[20,12841,12842],{},"Easy to extend with JWT or OAuth later",[31,12844,12846],{"id":12845},"tutorial-3-simple-response-caching-plugin","Tutorial 3: Simple Response Caching Plugin",[20,12848,12849],{},"Goal\nCache GET responses for frequently accessed endpoints (menus, products, settings).",[20,12851,12852],{},"Step 1: Create an In-Memory Cache\nconst cache = new Map\u003Cstring, { value: any; expires: number }>()\nconst TTL = 60_000 \u002F\u002F 60 seconds\nStep 2: Build the Plugin\n\u002F\u002F server\u002Fplugins\u002Fcache.ts\nexport default defineNitroPlugin((nitroApp) => {\nnitroApp.hooks.hook(\"request\", async (event) => {\nif (event.method !== \"GET\") return",[47,12854,12857],{"className":12855,"code":12856,"language":52},[50],"const key = event.path\nconst cached = cache.get(key)\n\nif (cached && cached.expires > Date.now()) {\n  return cached.value\n}\n",[39,12858,12856],{"__ignoreMap":55},[20,12860,12861],{},"})",[20,12863,12864],{},"nitroApp.hooks.hook(\"afterResponse\", (event, response) => {\nif (event.method !== \"GET\") return",[47,12866,12869],{"className":12867,"code":12868,"language":52},[50],"cache.set(event.path, {\n  value: response,\n  expires: Date.now() + TTL\n})\n",[39,12870,12868],{"__ignoreMap":55},[20,12872,12783],{},[31,12874,12876],{"id":12875},"real-world-use-case","Real-World Use Case",[20,12878,12879],{},"Food truck menu API",[20,12881,12882],{},"Business hours endpoint",[20,12884,12885],{},"Pricing data",[31,12887,12889],{"id":12888},"tutorial-4-feature-flags-plugin","Tutorial 4: Feature Flags Plugin",[20,12891,12892],{},"Goal\nEnable or disable features at runtime without touching routes.",[20,12894,12895],{},"Step 1: Define Flags\nconst flags = {\nseasonalMenu: true,\nenableDiscounts: false\n}\nStep 2: Attach Flags to Runtime\n\u002F\u002F server\u002Fplugins\u002Ffeature-flags.ts\nexport default defineNitroPlugin((nitroApp) => {\nnitroApp.hooks.hook(\"request\", (event) => {\nevent.context.features = flags\n})\n})\nStep 3: Use in a Route\nexport default defineEventHandler((event) => {\nif (event.context.features.seasonalMenu) {\nreturn { menu: \"Winter Specials\" }\n}",[20,12897,12898],{},"return { menu: \"Standard Menu\" }\n})",[31,12900,12902],{"id":12901},"why-this-matters","Why This Matters",[20,12904,12905],{},"Toggle features instantly",[20,12907,12908],{},"Safe rollouts",[20,12910,12911],{},"Environment-based behavior",[31,12913,12915],{"id":12914},"combining-plugins-for-a-real-app","Combining Plugins for a Real App",[20,12917,12918],{},"For a coffee shop or food truck API, you might use:",[20,12920,12921],{},"Plugin\tPurpose\nLogger\tTrack traffic & performance\nAuth\tSecure admin endpoints\nCache\tSpeed up menu reads\nFeature Flags\tEnable promotions\nAll without bloating your route handlers.",[31,12923,12925],{"id":12924},"best-practices","Best Practices",[20,12927,12928],{},"Keep plugins focused on one responsibility",[20,12930,12931],{},"Avoid heavy computation in request hooks",[20,12933,12934],{},"Use plugins for cross-cutting concerns, not business logic",[20,12936,12937],{},"Prefer plugins over middleware duplication\n::",[15,12939,3352],{"id":3351},[20,12941,12942],{},"Nitro plugins give you framework-level power without framework-level complexity. Instead of repeating logic in routes, plugins let you build reusable, centralized behaviors that scale with your app.",[20,12944,12945],{},"If you’re serious about building maintainable APIs — whether for Nuxt apps, serverless deployments, or edge runtimes — mastering Nitro plugins is a game changer. 🚀",[500,12947,502],{},{"title":55,"searchDepth":110,"depth":110,"links":12949},[12950,12951,12952,12953,12954,12955,12956,12957,12958],{"id":12786,"depth":113,"text":12787},{"id":12808,"depth":113,"text":12809},{"id":12832,"depth":113,"text":12833},{"id":12845,"depth":113,"text":12846},{"id":12875,"depth":113,"text":12876},{"id":12888,"depth":113,"text":12889},{"id":12901,"depth":113,"text":12902},{"id":12914,"depth":113,"text":12915},{"id":12924,"depth":113,"text":12925},"2026-01-30","Hands-on Nitro plugin tutorials showing how to build logging, authentication, caching, and feature flag plugins for real-world applications.",{"type":12,"value":12962},[12963,12965,12971,12973,12983],[15,12964,541],{"id":540},[20,12966,12680,12967,12684,12969,12688],{},[546,12968,12683],{},[546,12970,12687],{},[20,12972,12691],{},[561,12974,12975,12977,12979,12981],{},[564,12976,12696],{},[564,12978,12699],{},[564,12980,12702],{},[564,12982,12705],{},[20,12984,12708,12985,12711,12987,12715],{},[546,12986,3510],{},[546,12988,12714],{},[3504,11903,3507,3508,8234],{},"\u002Fblog\u002Fnitro-tutorial",{"title":12672,"description":12960},"blog\u002Fnitro-tutorial","i4pPWumhRzJriakSE9zevlb2qtVUOftePtjEXoFGaY0",{"id":12996,"title":12997,"author":12998,"body":12999,"canonical":115,"categories":115,"date":13728,"description":13729,"excerpt":13730,"extension":118,"img":12028,"keywords":13744,"language":3510,"meta":13749,"navigation":129,"ogImage":115,"path":13750,"rating":275,"readTime":132,"seo":13751,"stem":13752,"tag":3515,"__hash__":13753},"blog\u002Fblog\u002Fnuxt-42-steady-movements-to-5.md","Evaluating Nuxt 4.2: How the Latest Stable Release Empowers Modern Developers",{"name":8,"img":10,"website":535},{"type":12,"value":13000,"toc":13707},[13001,13003,13014,13020,13022,13026,13033,13047,13050,13055,13057,13061,13071,13074,13076,13087,13091,13215,13218,13220,13224,13227,13243,13246,13249,13251,13255,13258,13265,13269,13280,13284,13295,13298,13300,13304,13311,13347,13350,13361,13364,13366,13370,13376,13387,13390,13392,13396,13403,13407,13418,13452,13455,13457,13461,13464,13467,13638,13641,13652,13655,13657,13661,13664,13684,13687,13689,13691,13694,13701,13704],[15,13002,541],{"id":540},[20,13004,13005,13006,13009,13010,13013],{},"Nuxt has consistently positioned itself as one of the most developer-friendly frameworks in the Vue ecosystem. With the release of ",[546,13007,13008],{},"Nuxt 4",", the framework doubled down on clarity, performance, and full-stack flexibility. The latest stable release, ",[546,13011,13012],{},"Nuxt 4.2",", continues that trajectory—not by reinventing the framework, but by polishing the parts developers interact with every single day.",[20,13015,13016,13017,2230],{},"This post evaluates Nuxt 4.2 from a practical standpoint: what’s new, why it matters, and how these changes help developers build ",[546,13018,13019],{},"faster, more resilient, and more maintainable applications",[15,13021,748],{"id":747},[31,13023,13025],{"id":13024},"nuxt-42-in-context","Nuxt 4.2 in Context",[20,13027,13028,13029,13032],{},"Nuxt 4.2 is best understood as a ",[546,13030,13031],{},"developer-experience release",". Rather than introducing breaking changes or radical APIs, it focuses on:",[561,13034,13035,13038,13041,13044],{},[564,13036,13037],{},"More control over async behavior",[564,13039,13040],{},"Better debugging ergonomics",[564,13042,13043],{},"Smarter performance optimizations",[564,13045,13046],{},"Stronger alignment with Vite and Nitro",[20,13048,13049],{},"These improvements target real-world pain points that surface as applications grow.",[24,13051,13052],{"type":631},[20,13053,13054],{},"Nuxt 4.2 is a stable minor release, meaning it’s safe to adopt for production apps already running on Nuxt 4.",[72,13056],{},[31,13058,13060],{"id":13059},"abortable-data-fetching-a-real-world-necessity","Abortable Data Fetching: A Real-World Necessity",[20,13062,13063,13064,13067,13068,2230],{},"One of the most impactful additions in Nuxt 4.2 is ",[546,13065,13066],{},"native support for aborting async data requests"," using ",[39,13069,13070],{},"AbortController",[20,13072,13073],{},"In dynamic interfaces—search inputs, filters, route transitions—users often trigger multiple requests in quick succession. Without cancellation, older requests can overwrite newer state.",[2459,13075,12902],{"id":12901},[561,13077,13078,13081,13084],{},[564,13079,13080],{},"Prevents race conditions",[564,13082,13083],{},"Eliminates unnecessary network traffic",[564,13085,13086],{},"Keeps UI state predictable",[31,13088,13090],{"id":13089},"code-example","Code Example",[47,13092,13095],{"className":1010,"code":13093,"filename":13094,"language":1012,"meta":55,"style":55},"\u003Cscript setup lang=\"ts\">\nconst controller = new AbortController()\n\nconst { data } = await useAsyncData('users', () =>\n  $fetch('\u002Fapi\u002Fusers', {\n    signal: controller.signal\n  })\n)\n\n\u002F\u002F Cancel the request if the user navigates away\ncontroller.abort()\n\u003C\u002Fscript>\n","abortable-fetch.ts",[39,13096,13097,13112,13128,13132,13161,13173,13178,13182,13186,13190,13195,13205],{"__ignoreMap":55},[250,13098,13099,13101,13104,13106,13109],{"class":252,"line":253},[250,13100,1962],{"class":786},[250,13102,13103],{"class":912},"script setup lang",[250,13105,1416],{"class":786},[250,13107,13108],{"class":782},"\"ts\"",[250,13110,13111],{"class":786},">\n",[250,13113,13114,13116,13119,13121,13123,13126],{"class":252,"line":113},[250,13115,1181],{"class":786},[250,13117,13118],{"class":778}," controller",[250,13120,1187],{"class":786},[250,13122,1568],{"class":786},[250,13124,13125],{"class":774}," AbortController",[250,13127,4861],{"class":912},[250,13129,13130],{"class":252,"line":110},[250,13131,795],{"emptyLinePlaceholder":129},[250,13133,13134,13136,13138,13141,13143,13145,13147,13150,13152,13155,13158],{"class":252,"line":269},[250,13135,1181],{"class":786},[250,13137,7768],{"class":912},[250,13139,13140],{"class":778},"data",[250,13142,11640],{"class":912},[250,13144,1416],{"class":786},[250,13146,1463],{"class":786},[250,13148,13149],{"class":774}," useAsyncData",[250,13151,1434],{"class":912},[250,13153,13154],{"class":782},"'users'",[250,13156,13157],{"class":912},", () ",[250,13159,13160],{"class":786},"=>\n",[250,13162,13163,13166,13168,13171],{"class":252,"line":275},[250,13164,13165],{"class":774},"  $fetch",[250,13167,1434],{"class":912},[250,13169,13170],{"class":782},"'\u002Fapi\u002Fusers'",[250,13172,4454],{"class":912},[250,13174,13175],{"class":252,"line":281},[250,13176,13177],{"class":912},"    signal: controller.signal\n",[250,13179,13180],{"class":252,"line":287},[250,13181,10365],{"class":912},[250,13183,13184],{"class":252,"line":293},[250,13185,4852],{"class":912},[250,13187,13188],{"class":252,"line":299},[250,13189,795],{"emptyLinePlaceholder":129},[250,13191,13192],{"class":252,"line":132},[250,13193,13194],{"class":768},"\u002F\u002F Cancel the request if the user navigates away\n",[250,13196,13197,13200,13203],{"class":252,"line":310},[250,13198,13199],{"class":912},"controller.",[250,13201,13202],{"class":774},"abort",[250,13204,4861],{"class":912},[250,13206,13207,13210,13213],{"class":252,"line":316},[250,13208,13209],{"class":786},"\u003C\u002F",[250,13211,13212],{"class":912},"script",[250,13214,13111],{"class":786},[20,13216,13217],{},"This feature brings Nuxt’s data handling closer to native browser behavior—something developers have wanted for a long time.",[72,13219],{},[31,13221,13223],{"id":13222},"improved-error-handling-during-development","Improved Error Handling During Development",[20,13225,13226],{},"Debugging is a daily activity, and Nuxt 4.2 makes it less disruptive. When an error occurs during development, Nuxt now displays:",[561,13228,13229,13236],{},[564,13230,13231,13232,13235],{},"Your ",[546,13233,13234],{},"custom error page"," (what users would see)",[564,13237,13238,13239,13242],{},"A ",[546,13240,13241],{},"toggleable technical overlay"," with stack traces and diagnostics",[20,13244,13245],{},"This dual-view approach keeps developers grounded in the user experience while still providing deep technical insight.",[20,13247,13248],{},"Poor error visibility often leads to longer debugging sessions and fragile fixes—Nuxt 4.2 directly addresses this.\n::",[72,13250],{},[31,13252,13254],{"id":13253},"performance-improvements-that-scale","Performance Improvements That Scale",[20,13256,13257],{},"Performance optimizations in Nuxt 4.2 are subtle but powerful, especially for production-grade applications.",[20,13259,13260,13261,13264],{},"One standout improvement is ",[546,13262,13263],{},"async data handler extraction"," (experimental). Nuxt can now move certain async logic into build-time chunks, preventing unnecessary JavaScript from being shipped to the browser.",[2459,13266,13268],{"id":13267},"developer-impact","Developer Impact",[561,13270,13271,13274,13277],{},[564,13272,13273],{},"Smaller client bundles",[564,13275,13276],{},"Faster initial page loads",[564,13278,13279],{},"Better SEO and Lighthouse scores",[2459,13281,13283],{"id":13282},"performance-wins-in-practice","Performance Wins in Practice",[561,13285,13286,13289,13292],{},[564,13287,13288],{},"Reduced client-side JavaScript",[564,13290,13291],{},"Faster cold starts",[564,13293,13294],{},"Improved perceived performance for users\n::",[20,13296,13297],{},"These gains matter most at scale—when milliseconds start adding up across thousands of users.",[72,13299],{},[31,13301,13303],{"id":13302},"vite-environment-api-preparing-for-the-future","Vite Environment API: Preparing for the Future",[20,13305,13306,13307,13310],{},"Nuxt 4.2 introduces optional support for Vite’s new ",[546,13308,13309],{},"Environment API",", allowing more control over environment-specific behavior.",[47,13312,13314],{"className":1010,"code":13313,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  experimental: {\n    viteEnvironmentApi: true\n  }\n})\n",[39,13315,13316,13326,13331,13339,13343],{"__ignoreMap":55},[250,13317,13318,13320,13322,13324],{"class":252,"line":253},[250,13319,1019],{"class":786},[250,13321,1022],{"class":786},[250,13323,1025],{"class":774},[250,13325,1028],{"class":912},[250,13327,13328],{"class":252,"line":113},[250,13329,13330],{"class":912},"  experimental: {\n",[250,13332,13333,13336],{"class":252,"line":110},[250,13334,13335],{"class":912},"    viteEnvironmentApi: ",[250,13337,13338],{"class":778},"true\n",[250,13340,13341],{"class":252,"line":269},[250,13342,986],{"class":912},[250,13344,13345],{"class":252,"line":275},[250,13346,474],{"class":912},[20,13348,13349],{},"This is particularly valuable for teams managing:",[561,13351,13352,13355,13358],{},[564,13353,13354],{},"Multiple deployment stages",[564,13356,13357],{},"Complex environment variables",[564,13359,13360],{},"Shared infrastructure across apps",[20,13362,13363],{},"While still experimental, it signals Nuxt’s commitment to evolving alongside Vite rather than lagging behind it.",[72,13365],{},[31,13367,13369],{"id":13368},"a-more-modular-nitro-architecture","A More Modular Nitro Architecture",[20,13371,13372,13373,13375],{},"Behind the scenes, Nuxt 4.2 improves how ",[546,13374,555],{},"—Nuxt’s server engine—is integrated. By extracting server integration into a dedicated package, Nuxt gains:",[561,13377,13378,13381,13384],{},[564,13379,13380],{},"Cleaner separation between frontend and backend concerns",[564,13382,13383],{},"More flexibility for future runtime targets",[564,13385,13386],{},"Improved long-term maintainability",[20,13388,13389],{},"Most developers won’t notice this day to day, but it lays the groundwork for future innovation without breaking existing apps.",[72,13391],{},[31,13393,13395],{"id":13394},"typescript-tooling-improvements","TypeScript Tooling Improvements",[20,13397,13398,13399,13402],{},"TypeScript users benefit from experimental tooling enhancements in Nuxt 4.2. These improvements focus on ",[546,13400,13401],{},"editor intelligence",", making large codebases easier to navigate.",[2459,13404,13406],{"id":13405},"what-developers-gain","What Developers Gain",[561,13408,13409,13412,13415],{},[564,13410,13411],{},"Better go-to-definition support",[564,13413,13414],{},"Smarter component renaming",[564,13416,13417],{},"Improved navigation between server routes and client fetches",[47,13419,13421],{"className":1010,"code":13420,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  experimental: {\n    typescriptPlugin: true\n  }\n})\n",[39,13422,13423,13433,13437,13444,13448],{"__ignoreMap":55},[250,13424,13425,13427,13429,13431],{"class":252,"line":253},[250,13426,1019],{"class":786},[250,13428,1022],{"class":786},[250,13430,1025],{"class":774},[250,13432,1028],{"class":912},[250,13434,13435],{"class":252,"line":113},[250,13436,13330],{"class":912},[250,13438,13439,13442],{"class":252,"line":110},[250,13440,13441],{"class":912},"    typescriptPlugin: ",[250,13443,13338],{"class":778},[250,13445,13446],{"class":252,"line":269},[250,13447,986],{"class":912},[250,13449,13450],{"class":252,"line":275},[250,13451,474],{"class":912},[20,13453,13454],{},"For teams working in TypeScript-first environments, these changes reduce cognitive overhead and make refactoring safer.",[72,13456],{},[31,13458,13460],{"id":13459},"practical-pattern-search-with-request-cancellation","Practical Pattern: Search With Request Cancellation",[20,13462,13463],{},"Here’s a real-world pattern enabled by Nuxt 4.2’s abortable requests:",[31,13465,13090],{"id":13466},"code-example-1",[47,13468,13471],{"className":1010,"code":13469,"filename":13470,"language":1012,"meta":55,"style":55},"\u003Cscript setup lang=\"ts\">\nconst query = ref('')\nlet controller = new AbortController()\n\nwatch(query, async () => {\n  controller.abort()\n  controller = new AbortController()\n\n  await useAsyncData(\n    ['search', query.value],\n    () =>\n      $fetch(`\u002Fapi\u002Fsearch?q=${query.value}`, {\n        signal: controller.signal\n      })\n  )\n})\n\u003C\u002Fscript>\n","search-pattern.ts",[39,13472,13473,13485,13504,13519,13523,13539,13548,13561,13565,13573,13584,13591,13613,13618,13622,13626,13630],{"__ignoreMap":55},[250,13474,13475,13477,13479,13481,13483],{"class":252,"line":253},[250,13476,1962],{"class":786},[250,13478,13103],{"class":912},[250,13480,1416],{"class":786},[250,13482,13108],{"class":782},[250,13484,13111],{"class":786},[250,13486,13487,13489,13492,13494,13497,13499,13502],{"class":252,"line":113},[250,13488,1181],{"class":786},[250,13490,13491],{"class":778}," query",[250,13493,1187],{"class":786},[250,13495,13496],{"class":774}," ref",[250,13498,1434],{"class":912},[250,13500,13501],{"class":782},"''",[250,13503,4852],{"class":912},[250,13505,13506,13508,13511,13513,13515,13517],{"class":252,"line":110},[250,13507,1949],{"class":786},[250,13509,13510],{"class":912}," controller ",[250,13512,1416],{"class":786},[250,13514,1568],{"class":786},[250,13516,13125],{"class":774},[250,13518,4861],{"class":912},[250,13520,13521],{"class":252,"line":269},[250,13522,795],{"emptyLinePlaceholder":129},[250,13524,13525,13528,13531,13533,13535,13537],{"class":252,"line":275},[250,13526,13527],{"class":774},"watch",[250,13529,13530],{"class":912},"(query, ",[250,13532,1437],{"class":786},[250,13534,2015],{"class":912},[250,13536,1115],{"class":786},[250,13538,1118],{"class":912},[250,13540,13541,13544,13546],{"class":252,"line":281},[250,13542,13543],{"class":912},"  controller.",[250,13545,13202],{"class":774},[250,13547,4861],{"class":912},[250,13549,13550,13553,13555,13557,13559],{"class":252,"line":287},[250,13551,13552],{"class":912},"  controller ",[250,13554,1416],{"class":786},[250,13556,1568],{"class":786},[250,13558,13125],{"class":774},[250,13560,4861],{"class":912},[250,13562,13563],{"class":252,"line":293},[250,13564,795],{"emptyLinePlaceholder":129},[250,13566,13567,13569,13571],{"class":252,"line":299},[250,13568,1565],{"class":786},[250,13570,13149],{"class":774},[250,13572,1982],{"class":912},[250,13574,13575,13578,13581],{"class":252,"line":132},[250,13576,13577],{"class":912},"    [",[250,13579,13580],{"class":782},"'search'",[250,13582,13583],{"class":912},", query.value],\n",[250,13585,13586,13589],{"class":252,"line":310},[250,13587,13588],{"class":912},"    () ",[250,13590,13160],{"class":786},[250,13592,13593,13596,13598,13601,13604,13606,13609,13611],{"class":252,"line":316},[250,13594,13595],{"class":774},"      $fetch",[250,13597,1434],{"class":912},[250,13599,13600],{"class":782},"`\u002Fapi\u002Fsearch?q=${",[250,13602,13603],{"class":912},"query",[250,13605,2230],{"class":782},[250,13607,13608],{"class":912},"value",[250,13610,2355],{"class":782},[250,13612,4454],{"class":912},[250,13614,13615],{"class":252,"line":322},[250,13616,13617],{"class":912},"        signal: controller.signal\n",[250,13619,13620],{"class":252,"line":328},[250,13621,2204],{"class":912},[250,13623,13624],{"class":252,"line":334},[250,13625,10040],{"class":912},[250,13627,13628],{"class":252,"line":340},[250,13629,474],{"class":912},[250,13631,13632,13634,13636],{"class":252,"line":346},[250,13633,13209],{"class":786},[250,13635,13212],{"class":912},[250,13637,13111],{"class":786},[20,13639,13640],{},"This approach:",[561,13642,13643,13646,13649],{},[564,13644,13645],{},"Cancels outdated requests automatically",[564,13647,13648],{},"Keeps results in sync with user input",[564,13650,13651],{},"Improves perceived responsiveness",[20,13653,13654],{},"It’s a small API change with a huge real-world payoff.",[72,13656],{},[31,13658,13660],{"id":13659},"who-benefits-most-from-nuxt-42","Who Benefits Most From Nuxt 4.2?",[20,13662,13663],{},"Nuxt 4.2 shines for:",[561,13665,13666,13672,13678,13681],{},[564,13667,13668,13669],{},"Teams building ",[546,13670,13671],{},"interactive, data-driven UIs",[564,13673,13674,13675],{},"Developers optimizing for ",[546,13676,13677],{},"performance and SEO",[564,13679,13680],{},"TypeScript-heavy projects",[564,13682,13683],{},"Full-stack Nuxt apps using Nitro",[20,13685,13686],{},"If you’re already on Nuxt 4, upgrading to 4.2 is a low-risk way to gain immediate DX and performance benefits.\n::",[72,13688],{},[31,13690,3352],{"id":3351},[20,13692,13693],{},"Nuxt 4.2 is a thoughtful, developer-focused release. It doesn’t chase trends—it solves real problems. By improving async control, debugging clarity, performance, and tooling, Nuxt 4.2 makes everyday development smoother and production applications more robust.",[20,13695,13696,13697,13700],{},"For developers who value ",[546,13698,13699],{},"clarity, performance, and long-term maintainability",", Nuxt 4.2 is not just an upgrade—it’s a refinement of everything that makes Nuxt a pleasure to use.",[20,13702,13703],{},"If you’re building serious Vue applications in 2026, Nuxt 4.2 deserves a place at the center of your stack.",[500,13705,13706],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":55,"searchDepth":110,"depth":110,"links":13708},[13709,13710,13713,13714,13715,13719,13720,13721,13724,13725,13726,13727],{"id":13024,"depth":113,"text":13025},{"id":13059,"depth":113,"text":13060,"children":13711},[13712],{"id":12901,"depth":110,"text":12902},{"id":13089,"depth":113,"text":13090},{"id":13222,"depth":113,"text":13223},{"id":13253,"depth":113,"text":13254,"children":13716},[13717,13718],{"id":13267,"depth":110,"text":13268},{"id":13282,"depth":110,"text":13283},{"id":13302,"depth":113,"text":13303},{"id":13368,"depth":113,"text":13369},{"id":13394,"depth":113,"text":13395,"children":13722},[13723],{"id":13405,"depth":110,"text":13406},{"id":13459,"depth":113,"text":13460},{"id":13466,"depth":113,"text":13090},{"id":13659,"depth":113,"text":13660},{"id":3351,"depth":113,"text":3352},"2026-01-09","A deep evaluation of Nuxt 4.2, exploring new features, performance improvements, and why this release makes building modern Vue applications faster and more reliable.",{"type":12,"value":13731},[13732,13734,13740],[15,13733,541],{"id":540},[20,13735,13005,13736,13009,13738,13013],{},[546,13737,13008],{},[546,13739,13012],{},[20,13741,13016,13742,2230],{},[546,13743,13019],{},[13745,13746,13747,3504,126,13748],"nuxt 4","nuxt 4.2","vue","web performance",{},"\u002Fblog\u002Fnuxt-42-steady-movements-to-5",{"title":12997,"description":13729},"blog\u002Fnuxt-42-steady-movements-to-5","xF7X0JRedqolAzpj1780Epatp6IDaI6ADDC3FG4FqCQ",{"id":13755,"title":13756,"author":13757,"body":13758,"canonical":115,"categories":115,"date":3470,"description":18676,"excerpt":18677,"extension":118,"img":3502,"keywords":18705,"language":3510,"meta":18712,"navigation":129,"ogImage":115,"path":18713,"rating":275,"readTime":334,"seo":18714,"stem":18715,"tag":3515,"__hash__":18716},"blog\u002Fblog\u002Fnuxt-auth-guide.md","Complete Guide to Authentication in Nuxt 4: From Basics to Production",{"name":8,"img":10,"website":535},{"type":12,"value":13759,"toc":18657},[13760,13762,13765,13770,13793,13796,13798,13802,13805,13873,13878,13880,13882,13885,13913,13916,13947,13962,13964,13968,13971,13975,14103,14111,14118,14141,14143,14147,14150,14155,14630,14636,14638,14642,14645,14650,15042,15047,15206,15208,15212,15216,15221,15593,15597,15602,15898,15902,15907,15959,15963,15968,16257,16259,16263,16266,16270,16624,16630,16632,16636,16639,16646,16651,16676,16680,16808,16813,16912,16914,16918,16923,17580,17585,18166,18168,18172,18175,18427,18429,18433,18436,18486,18488,18492,18566,18568,18570,18573,18605,18608,18634,18637,18651,18654],[15,13761,541],{"id":540},[20,13763,13764],{},"Every production application needs authentication. Yet it's one of the most commonly botched parts of web development—poorly implemented auth leads to security vulnerabilities, frustrated users, and late-night debugging sessions.",[20,13766,13767,13768,1007],{},"In this comprehensive guide, we'll cover everything you need to know about authentication in ",[546,13769,13008],{},[561,13771,13772,13775,13778,13781,13784,13787,13790],{},[564,13773,13774],{},"Authentication strategies and when to use each",[564,13776,13777],{},"Implementing session-based auth",[564,13779,13780],{},"JWT authentication flow",[564,13782,13783],{},"OAuth with GitHub and Google",[564,13785,13786],{},"Protecting API routes",[564,13788,13789],{},"Secure password handling",[564,13791,13792],{},"Type-safe auth with TypeScript",[20,13794,13795],{},"Let's build a complete auth system for our BrewStop application.",[15,13797,748],{"id":747},[31,13799,13801],{"id":13800},"understanding-authentication-strategies","Understanding Authentication Strategies",[20,13803,13804],{},"Before we write code, let's understand the three main authentication strategies:",[645,13806,13807,13823],{},[648,13808,13809],{},[651,13810,13811,13814,13817,13820],{},[654,13812,13813],{},"Strategy",[654,13815,13816],{},"Best For",[654,13818,13819],{},"Pros",[654,13821,13822],{},"Cons",[666,13824,13825,13841,13857],{},[651,13826,13827,13832,13835,13838],{},[671,13828,13829],{},[546,13830,13831],{},"Session",[671,13833,13834],{},"Traditional web apps",[671,13836,13837],{},"Simple, familiar UX",[671,13839,13840],{},"CSRF concerns, server state",[651,13842,13843,13848,13851,13854],{},[671,13844,13845],{},[546,13846,13847],{},"JWT",[671,13849,13850],{},"SPAs, APIs, mobile",[671,13852,13853],{},"Stateless, scalable",[671,13855,13856],{},"Token management complexity",[651,13858,13859,13864,13867,13870],{},[671,13860,13861],{},[546,13862,13863],{},"OAuth",[671,13865,13866],{},"Social login",[671,13868,13869],{},"Frictionless, trusted",[671,13871,13872],{},"Third-party dependency",[24,13874,13875],{"type":631},[20,13876,13877],{},"For most Nuxt applications, a hybrid approach works best: JWT for API authentication, OAuth for social login, and session-like behavior via cookies.",[72,13879],{},[31,13881,4182],{"id":4181},[20,13883,13884],{},"Let's create a fresh Nuxt project with authentication in mind.",[47,13886,13888],{"className":758,"code":13887,"filename":760,"language":761,"meta":55,"style":55},"npx nuxi@latest init brewstop-auth\ncd brewstop-auth\nnpm install\n",[39,13889,13890,13901,13907],{"__ignoreMap":55},[250,13891,13892,13894,13896,13898],{"class":252,"line":253},[250,13893,4200],{"class":774},[250,13895,859],{"class":782},[250,13897,862],{"class":782},[250,13899,13900],{"class":782}," brewstop-auth\n",[250,13902,13903,13905],{"class":252,"line":113},[250,13904,874],{"class":778},[250,13906,13900],{"class":782},[250,13908,13909,13911],{"class":252,"line":110},[250,13910,4226],{"class":774},[250,13912,896],{"class":782},[20,13914,13915],{},"We'll need some additional packages:",[47,13917,13919],{"className":758,"code":13918,"filename":760,"language":761,"meta":55,"style":55},"npm install @sidebase\u002Fnuxt-auth next-auth@beta jose\nnpm install -D @types\u002Fnode\n",[39,13920,13921,13936],{"__ignoreMap":55},[250,13922,13923,13925,13927,13930,13933],{"class":252,"line":253},[250,13924,4226],{"class":774},[250,13926,808],{"class":782},[250,13928,13929],{"class":782}," @sidebase\u002Fnuxt-auth",[250,13931,13932],{"class":782}," next-auth@beta",[250,13934,13935],{"class":782}," jose\n",[250,13937,13938,13940,13942,13944],{"class":252,"line":113},[250,13939,4226],{"class":774},[250,13941,808],{"class":782},[250,13943,4243],{"class":778},[250,13945,13946],{"class":782}," @types\u002Fnode\n",[161,13948,13951],{"icon":13949,"title":13950},"🔐","Security First",[20,13952,13953,13954,13957,13958,13961],{},"We're using ",[39,13955,13956],{},"@sidebase\u002Fnuxt-auth"," which provides first-class support for NextAuth.js in Nuxt, and ",[39,13959,13960],{},"jose"," for JWT operations.",[72,13963],{},[31,13965,13967],{"id":13966},"step-2-configure-nuxt-auth","Step 2: Configure Nuxt Auth",[20,13969,13970],{},"Add the auth module to your Nuxt configuration.",[20,13972,1092,13973,1007],{},[39,13974,1006],{},[47,13976,13978],{"className":1010,"code":13977,"filename":1006,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  modules: [\"@sidebase\u002Fnuxt-auth\"],\n  \n  auth: {\n    provider: {\n      type: \"authjs\",\n      defaultProvider: \"credentials\",\n    },\n    globalAppMiddleware: true,\n  },\n  \n  runtimeConfig: {\n    authSecret: process.env.AUTH_SECRET,\n    public: {\n      authOrigin: process.env.AUTH_ORIGIN || \"http:\u002F\u002Flocalhost:3000\",\n    },\n  },\n});\n",[39,13979,13980,13990,14001,14005,14010,14015,14025,14035,14040,14049,14053,14057,14061,14071,14075,14091,14095,14099],{"__ignoreMap":55},[250,13981,13982,13984,13986,13988],{"class":252,"line":253},[250,13983,1019],{"class":786},[250,13985,1022],{"class":786},[250,13987,1025],{"class":774},[250,13989,1028],{"class":912},[250,13991,13992,13995,13998],{"class":252,"line":113},[250,13993,13994],{"class":912},"  modules: [",[250,13996,13997],{"class":782},"\"@sidebase\u002Fnuxt-auth\"",[250,13999,14000],{"class":912},"],\n",[250,14002,14003],{"class":252,"line":110},[250,14004,1053],{"class":912},[250,14006,14007],{"class":252,"line":269},[250,14008,14009],{"class":912},"  auth: {\n",[250,14011,14012],{"class":252,"line":275},[250,14013,14014],{"class":912},"    provider: {\n",[250,14016,14017,14020,14023],{"class":252,"line":281},[250,14018,14019],{"class":912},"      type: ",[250,14021,14022],{"class":782},"\"authjs\"",[250,14024,927],{"class":912},[250,14026,14027,14030,14033],{"class":252,"line":287},[250,14028,14029],{"class":912},"      defaultProvider: ",[250,14031,14032],{"class":782},"\"credentials\"",[250,14034,927],{"class":912},[250,14036,14037],{"class":252,"line":293},[250,14038,14039],{"class":912},"    },\n",[250,14041,14042,14045,14047],{"class":252,"line":299},[250,14043,14044],{"class":912},"    globalAppMiddleware: ",[250,14046,1066],{"class":778},[250,14048,927],{"class":912},[250,14050,14051],{"class":252,"line":132},[250,14052,1048],{"class":912},[250,14054,14055],{"class":252,"line":310},[250,14056,1053],{"class":912},[250,14058,14059],{"class":252,"line":316},[250,14060,8929],{"class":912},[250,14062,14063,14066,14069],{"class":252,"line":322},[250,14064,14065],{"class":912},"    authSecret: process.env.",[250,14067,14068],{"class":778},"AUTH_SECRET",[250,14070,927],{"class":912},[250,14072,14073],{"class":252,"line":328},[250,14074,8934],{"class":912},[250,14076,14077,14080,14083,14086,14089],{"class":252,"line":334},[250,14078,14079],{"class":912},"      authOrigin: process.env.",[250,14081,14082],{"class":778},"AUTH_ORIGIN",[250,14084,14085],{"class":786}," ||",[250,14087,14088],{"class":782}," \"http:\u002F\u002Flocalhost:3000\"",[250,14090,927],{"class":912},[250,14092,14093],{"class":252,"line":340},[250,14094,14039],{"class":912},[250,14096,14097],{"class":252,"line":346},[250,14098,1048],{"class":912},[250,14100,14101],{"class":252,"line":352},[250,14102,1077],{"class":912},[24,14104,14105],{"type":26},[20,14106,14107,14108,14110],{},"Never commit your ",[39,14109,14068],{},". Use environment variables for all secrets.",[20,14112,14113,14114,14117],{},"Create a ",[39,14115,14116],{},".env"," file:",[47,14119,14121],{"className":758,"code":14120,"filename":14116,"language":761,"meta":55,"style":55},"AUTH_SECRET=your-super-secret-key-change-in-production\nAUTH_ORIGIN=http:\u002F\u002Flocalhost:3000\n",[39,14122,14123,14132],{"__ignoreMap":55},[250,14124,14125,14127,14129],{"class":252,"line":253},[250,14126,14068],{"class":912},[250,14128,1416],{"class":786},[250,14130,14131],{"class":782},"your-super-secret-key-change-in-production\n",[250,14133,14134,14136,14138],{"class":252,"line":113},[250,14135,14082],{"class":912},[250,14137,1416],{"class":786},[250,14139,14140],{"class":782},"http:\u002F\u002Flocalhost:3000\n",[72,14142],{},[31,14144,14146],{"id":14145},"step-3-create-the-authentication-backend","Step 3: Create the Authentication Backend",[20,14148,14149],{},"We'll build a credentials-based auth system with proper password hashing.",[20,14151,1092,14152,1007],{},[39,14153,14154],{},"server\u002Futils\u002Fauth.ts",[47,14156,14158],{"className":1010,"code":14157,"filename":14154,"language":1012,"meta":55,"style":55},"import { SignJWT, jwtVerify } from \"jose\";\nimport { hash, verify } from \"@node-rs\u002Fargon2\";\n\nconst secret = new TextEncoder().encode(\n  process.env.AUTH_SECRET || \"fallback-secret\"\n);\n\nexport async function hashPassword(password: string): Promise\u003Cstring> {\n  return hash(password, {\n    memoryCost: 19456,\n    timeCost: 2,\n    outputLen: 32,\n    parallelism: 1,\n  });\n}\n\nexport async function verifyPassword(hash: string, password: string): Promise\u003Cboolean> {\n  return verify(hash, password);\n}\n\nexport async function createToken(userId: string, email: string): Promise\u003Cstring> {\n  return new SignJWT({ userId, email })\n    .setProtectedHeader({ alg: \"HS256\" })\n    .setIssuedAt()\n    .setExpirationTime(\"7d\")\n    .sign(secret);\n}\n\nexport async function verifyToken(token: string): Promise\u003C{ userId: string; email: string } | null> {\n  try {\n    const { payload } = await jwtVerify(token, secret);\n    return payload as { userId: string; email: string };\n  } catch {\n    return null;\n  }\n}\n",[39,14159,14160,14174,14188,14192,14213,14225,14229,14233,14267,14277,14287,14296,14306,14315,14319,14323,14327,14368,14378,14382,14386,14427,14439,14454,14463,14477,14487,14491,14495,14549,14556,14577,14605,14614,14622,14626],{"__ignoreMap":55},[250,14161,14162,14164,14167,14169,14172],{"class":252,"line":253},[250,14163,1763],{"class":786},[250,14165,14166],{"class":912}," { SignJWT, jwtVerify } ",[250,14168,1769],{"class":786},[250,14170,14171],{"class":782}," \"jose\"",[250,14173,1379],{"class":912},[250,14175,14176,14178,14181,14183,14186],{"class":252,"line":113},[250,14177,1763],{"class":786},[250,14179,14180],{"class":912}," { hash, verify } ",[250,14182,1769],{"class":786},[250,14184,14185],{"class":782}," \"@node-rs\u002Fargon2\"",[250,14187,1379],{"class":912},[250,14189,14190],{"class":252,"line":110},[250,14191,795],{"emptyLinePlaceholder":129},[250,14193,14194,14196,14199,14201,14203,14206,14208,14211],{"class":252,"line":269},[250,14195,1181],{"class":786},[250,14197,14198],{"class":778}," secret",[250,14200,1187],{"class":786},[250,14202,1568],{"class":786},[250,14204,14205],{"class":774}," TextEncoder",[250,14207,1647],{"class":912},[250,14209,14210],{"class":774},"encode",[250,14212,1982],{"class":912},[250,14214,14215,14218,14220,14222],{"class":252,"line":275},[250,14216,14217],{"class":912},"  process.env.",[250,14219,14068],{"class":778},[250,14221,14085],{"class":786},[250,14223,14224],{"class":782}," \"fallback-secret\"\n",[250,14226,14227],{"class":252,"line":281},[250,14228,1885],{"class":912},[250,14230,14231],{"class":252,"line":287},[250,14232,795],{"emptyLinePlaceholder":129},[250,14234,14235,14237,14239,14241,14244,14246,14249,14251,14253,14255,14257,14259,14261,14264],{"class":252,"line":293},[250,14236,1019],{"class":786},[250,14238,2012],{"class":786},[250,14240,1845],{"class":786},[250,14242,14243],{"class":774}," hashPassword",[250,14245,1434],{"class":912},[250,14247,14248],{"class":1370},"password",[250,14250,1007],{"class":786},[250,14252,2506],{"class":778},[250,14254,2390],{"class":912},[250,14256,1007],{"class":786},[250,14258,1571],{"class":774},[250,14260,1962],{"class":912},[250,14262,14263],{"class":778},"string",[250,14265,14266],{"class":912},"> {\n",[250,14268,14269,14271,14274],{"class":252,"line":299},[250,14270,1123],{"class":786},[250,14272,14273],{"class":774}," hash",[250,14275,14276],{"class":912},"(password, {\n",[250,14278,14279,14282,14285],{"class":252,"line":132},[250,14280,14281],{"class":912},"    memoryCost: ",[250,14283,14284],{"class":778},"19456",[250,14286,927],{"class":912},[250,14288,14289,14292,14294],{"class":252,"line":310},[250,14290,14291],{"class":912},"    timeCost: ",[250,14293,1226],{"class":778},[250,14295,927],{"class":912},[250,14297,14298,14301,14304],{"class":252,"line":316},[250,14299,14300],{"class":912},"    outputLen: ",[250,14302,14303],{"class":778},"32",[250,14305,927],{"class":912},[250,14307,14308,14311,14313],{"class":252,"line":322},[250,14309,14310],{"class":912},"    parallelism: ",[250,14312,1198],{"class":778},[250,14314,927],{"class":912},[250,14316,14317],{"class":252,"line":328},[250,14318,6749],{"class":912},[250,14320,14321],{"class":252,"line":334},[250,14322,991],{"class":912},[250,14324,14325],{"class":252,"line":340},[250,14326,795],{"emptyLinePlaceholder":129},[250,14328,14329,14331,14333,14335,14338,14340,14343,14345,14347,14349,14351,14353,14355,14357,14359,14361,14363,14366],{"class":252,"line":346},[250,14330,1019],{"class":786},[250,14332,2012],{"class":786},[250,14334,1845],{"class":786},[250,14336,14337],{"class":774}," verifyPassword",[250,14339,1434],{"class":912},[250,14341,14342],{"class":1370},"hash",[250,14344,1007],{"class":786},[250,14346,2506],{"class":778},[250,14348,7128],{"class":912},[250,14350,14248],{"class":1370},[250,14352,1007],{"class":786},[250,14354,2506],{"class":778},[250,14356,2390],{"class":912},[250,14358,1007],{"class":786},[250,14360,1571],{"class":774},[250,14362,1962],{"class":912},[250,14364,14365],{"class":778},"boolean",[250,14367,14266],{"class":912},[250,14369,14370,14372,14375],{"class":252,"line":352},[250,14371,1123],{"class":786},[250,14373,14374],{"class":774}," verify",[250,14376,14377],{"class":912},"(hash, password);\n",[250,14379,14380],{"class":252,"line":358},[250,14381,991],{"class":912},[250,14383,14384],{"class":252,"line":364},[250,14385,795],{"emptyLinePlaceholder":129},[250,14387,14388,14390,14392,14394,14397,14399,14402,14404,14406,14408,14411,14413,14415,14417,14419,14421,14423,14425],{"class":252,"line":370},[250,14389,1019],{"class":786},[250,14391,2012],{"class":786},[250,14393,1845],{"class":786},[250,14395,14396],{"class":774}," createToken",[250,14398,1434],{"class":912},[250,14400,14401],{"class":1370},"userId",[250,14403,1007],{"class":786},[250,14405,2506],{"class":778},[250,14407,7128],{"class":912},[250,14409,14410],{"class":1370},"email",[250,14412,1007],{"class":786},[250,14414,2506],{"class":778},[250,14416,2390],{"class":912},[250,14418,1007],{"class":786},[250,14420,1571],{"class":774},[250,14422,1962],{"class":912},[250,14424,14263],{"class":778},[250,14426,14266],{"class":912},[250,14428,14429,14431,14433,14436],{"class":252,"line":376},[250,14430,1123],{"class":786},[250,14432,1568],{"class":786},[250,14434,14435],{"class":774}," SignJWT",[250,14437,14438],{"class":912},"({ userId, email })\n",[250,14440,14441,14443,14446,14449,14452],{"class":252,"line":382},[250,14442,4604],{"class":912},[250,14444,14445],{"class":774},"setProtectedHeader",[250,14447,14448],{"class":912},"({ alg: ",[250,14450,14451],{"class":782},"\"HS256\"",[250,14453,4599],{"class":912},[250,14455,14456,14458,14461],{"class":252,"line":388},[250,14457,4604],{"class":912},[250,14459,14460],{"class":774},"setIssuedAt",[250,14462,4861],{"class":912},[250,14464,14465,14467,14470,14472,14475],{"class":252,"line":393},[250,14466,4604],{"class":912},[250,14468,14469],{"class":774},"setExpirationTime",[250,14471,1434],{"class":912},[250,14473,14474],{"class":782},"\"7d\"",[250,14476,4852],{"class":912},[250,14478,14479,14481,14484],{"class":252,"line":399},[250,14480,4604],{"class":912},[250,14482,14483],{"class":774},"sign",[250,14485,14486],{"class":912},"(secret);\n",[250,14488,14489],{"class":252,"line":405},[250,14490,991],{"class":912},[250,14492,14493],{"class":252,"line":410},[250,14494,795],{"emptyLinePlaceholder":129},[250,14496,14497,14499,14501,14503,14506,14508,14511,14513,14515,14517,14519,14521,14524,14526,14528,14530,14533,14535,14537,14539,14541,14544,14547],{"class":252,"line":415},[250,14498,1019],{"class":786},[250,14500,2012],{"class":786},[250,14502,1845],{"class":786},[250,14504,14505],{"class":774}," verifyToken",[250,14507,1434],{"class":912},[250,14509,14510],{"class":1370},"token",[250,14512,1007],{"class":786},[250,14514,2506],{"class":778},[250,14516,2390],{"class":912},[250,14518,1007],{"class":786},[250,14520,1571],{"class":774},[250,14522,14523],{"class":912},"\u003C{ ",[250,14525,14401],{"class":1370},[250,14527,1007],{"class":786},[250,14529,2506],{"class":778},[250,14531,14532],{"class":912},"; ",[250,14534,14410],{"class":1370},[250,14536,1007],{"class":786},[250,14538,2506],{"class":778},[250,14540,11640],{"class":912},[250,14542,14543],{"class":786},"|",[250,14545,14546],{"class":778}," null",[250,14548,14266],{"class":912},[250,14550,14551,14554],{"class":252,"line":420},[250,14552,14553],{"class":786},"  try",[250,14555,1118],{"class":912},[250,14557,14558,14560,14562,14565,14567,14569,14571,14574],{"class":252,"line":426},[250,14559,6403],{"class":786},[250,14561,7768],{"class":912},[250,14563,14564],{"class":778},"payload",[250,14566,11640],{"class":912},[250,14568,1416],{"class":786},[250,14570,1463],{"class":786},[250,14572,14573],{"class":774}," jwtVerify",[250,14575,14576],{"class":912},"(token, secret);\n",[250,14578,14579,14582,14585,14587,14589,14591,14593,14595,14597,14599,14601,14603],{"class":252,"line":431},[250,14580,14581],{"class":786},"    return",[250,14583,14584],{"class":912}," payload ",[250,14586,1472],{"class":786},[250,14588,7768],{"class":912},[250,14590,14401],{"class":1370},[250,14592,1007],{"class":786},[250,14594,2506],{"class":778},[250,14596,14532],{"class":912},[250,14598,14410],{"class":1370},[250,14600,1007],{"class":786},[250,14602,2506],{"class":778},[250,14604,5784],{"class":912},[250,14606,14607,14610,14612],{"class":252,"line":436},[250,14608,14609],{"class":912},"  } ",[250,14611,2164],{"class":786},[250,14613,1118],{"class":912},[250,14615,14616,14618,14620],{"class":252,"line":442},[250,14617,14581],{"class":786},[250,14619,14546],{"class":778},[250,14621,1379],{"class":912},[250,14623,14624],{"class":252,"line":447},[250,14625,986],{"class":912},[250,14627,14628],{"class":252,"line":453},[250,14629,991],{"class":912},[161,14631,14633],{"icon":5036,"title":14632},"Password Security",[20,14634,14635],{},"We're using Argon2id—the winner of the Password Hashing Competition. It's memory-hard and resistant to GPU attacks.",[72,14637],{},[31,14639,14641],{"id":14640},"step-4-create-users-database","Step 4: Create Users Database",[20,14643,14644],{},"For simplicity, we'll use a file-based approach (replace with Drizzle\u002FPrisma in production).",[20,14646,1092,14647,1007],{},[39,14648,14649],{},"server\u002Futils\u002Fdb.ts",[47,14651,14653],{"className":1010,"code":14652,"filename":14649,"language":1012,"meta":55,"style":55},"import { db } from \".\u002Fdb\";\nimport { users } from \".\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\nimport { hashPassword, verifyPassword } from \".\u002Fauth\";\n\ninterface CreateUserInput {\n  email: string;\n  password: string;\n  name: string;\n}\n\nexport async function createUser(input: CreateUserInput) {\n  const hashedPassword = await hashPassword(input.password);\n  \n  await db.insert(users).values({\n    id: crypto.randomUUID(),\n    email: input.email,\n    password: hashedPassword,\n    name: input.name,\n  });\n}\n\nexport async function findUserByEmail(email: string) {\n  return db.select().from(users).where(eq(users.email, email)).get();\n}\n\nexport async function validateUserCredentials(email: string, password: string) {\n  const user = await findUserByEmail(email);\n  \n  if (!user) {\n    return null;\n  }\n  \n  const isValid = await verifyPassword(user.password, password);\n  \n  if (!isValid) {\n    return null;\n  }\n  \n  return { id: user.id, email: user.email, name: user.name };\n}\n",[39,14654,14655,14668,14681,14693,14707,14711,14720,14731,14742,14752,14756,14760,14782,14798,14802,14817,14825,14830,14835,14840,14844,14848,14852,14873,14900,14904,14908,14937,14953,14957,14968,14976,14980,14984,15000,15004,15015,15023,15027,15031,15038],{"__ignoreMap":55},[250,14656,14657,14659,14661,14663,14666],{"class":252,"line":253},[250,14658,1763],{"class":786},[250,14660,5369],{"class":912},[250,14662,1769],{"class":786},[250,14664,14665],{"class":782}," \".\u002Fdb\"",[250,14667,1379],{"class":912},[250,14669,14670,14672,14675,14677,14679],{"class":252,"line":113},[250,14671,1763],{"class":786},[250,14673,14674],{"class":912}," { users } ",[250,14676,1769],{"class":786},[250,14678,5105],{"class":782},[250,14680,1379],{"class":912},[250,14682,14683,14685,14687,14689,14691],{"class":252,"line":110},[250,14684,1763],{"class":786},[250,14686,6176],{"class":912},[250,14688,1769],{"class":786},[250,14690,4420],{"class":782},[250,14692,1379],{"class":912},[250,14694,14695,14697,14700,14702,14705],{"class":252,"line":269},[250,14696,1763],{"class":786},[250,14698,14699],{"class":912}," { hashPassword, verifyPassword } ",[250,14701,1769],{"class":786},[250,14703,14704],{"class":782}," \".\u002Fauth\"",[250,14706,1379],{"class":912},[250,14708,14709],{"class":252,"line":275},[250,14710,795],{"emptyLinePlaceholder":129},[250,14712,14713,14715,14718],{"class":252,"line":281},[250,14714,1360],{"class":786},[250,14716,14717],{"class":774}," CreateUserInput",[250,14719,1118],{"class":912},[250,14721,14722,14725,14727,14729],{"class":252,"line":287},[250,14723,14724],{"class":1370},"  email",[250,14726,1007],{"class":786},[250,14728,2506],{"class":778},[250,14730,1379],{"class":912},[250,14732,14733,14736,14738,14740],{"class":252,"line":293},[250,14734,14735],{"class":1370},"  password",[250,14737,1007],{"class":786},[250,14739,2506],{"class":778},[250,14741,1379],{"class":912},[250,14743,14744,14746,14748,14750],{"class":252,"line":299},[250,14745,2501],{"class":1370},[250,14747,1007],{"class":786},[250,14749,2506],{"class":778},[250,14751,1379],{"class":912},[250,14753,14754],{"class":252,"line":132},[250,14755,991],{"class":912},[250,14757,14758],{"class":252,"line":310},[250,14759,795],{"emptyLinePlaceholder":129},[250,14761,14762,14764,14766,14768,14771,14773,14776,14778,14780],{"class":252,"line":316},[250,14763,1019],{"class":786},[250,14765,2012],{"class":786},[250,14767,1845],{"class":786},[250,14769,14770],{"class":774}," createUser",[250,14772,1434],{"class":912},[250,14774,14775],{"class":1370},"input",[250,14777,1007],{"class":786},[250,14779,14717],{"class":774},[250,14781,1512],{"class":912},[250,14783,14784,14786,14789,14791,14793,14795],{"class":252,"line":322},[250,14785,1455],{"class":786},[250,14787,14788],{"class":778}," hashedPassword",[250,14790,1187],{"class":786},[250,14792,1463],{"class":786},[250,14794,14243],{"class":774},[250,14796,14797],{"class":912},"(input.password);\n",[250,14799,14800],{"class":252,"line":328},[250,14801,1053],{"class":912},[250,14803,14804,14806,14808,14810,14813,14815],{"class":252,"line":334},[250,14805,1565],{"class":786},[250,14807,5683],{"class":912},[250,14809,5730],{"class":774},[250,14811,14812],{"class":912},"(users).",[250,14814,5735],{"class":774},[250,14816,1028],{"class":912},[250,14818,14819,14821,14823],{"class":252,"line":340},[250,14820,1613],{"class":912},[250,14822,1616],{"class":774},[250,14824,1156],{"class":912},[250,14826,14827],{"class":252,"line":346},[250,14828,14829],{"class":912},"    email: input.email,\n",[250,14831,14832],{"class":252,"line":352},[250,14833,14834],{"class":912},"    password: hashedPassword,\n",[250,14836,14837],{"class":252,"line":358},[250,14838,14839],{"class":912},"    name: input.name,\n",[250,14841,14842],{"class":252,"line":364},[250,14843,6749],{"class":912},[250,14845,14846],{"class":252,"line":370},[250,14847,991],{"class":912},[250,14849,14850],{"class":252,"line":376},[250,14851,795],{"emptyLinePlaceholder":129},[250,14853,14854,14856,14858,14860,14863,14865,14867,14869,14871],{"class":252,"line":382},[250,14855,1019],{"class":786},[250,14857,2012],{"class":786},[250,14859,1845],{"class":786},[250,14861,14862],{"class":774}," findUserByEmail",[250,14864,1434],{"class":912},[250,14866,14410],{"class":1370},[250,14868,1007],{"class":786},[250,14870,2506],{"class":778},[250,14872,1512],{"class":912},[250,14874,14875,14877,14879,14881,14883,14885,14887,14889,14891,14893,14896,14898],{"class":252,"line":388},[250,14876,1123],{"class":786},[250,14878,5683],{"class":912},[250,14880,5870],{"class":774},[250,14882,1647],{"class":912},[250,14884,1769],{"class":774},[250,14886,14812],{"class":912},[250,14888,5879],{"class":774},[250,14890,1434],{"class":912},[250,14892,6442],{"class":774},[250,14894,14895],{"class":912},"(users.email, email)).",[250,14897,6062],{"class":774},[250,14899,1906],{"class":912},[250,14901,14902],{"class":252,"line":393},[250,14903,991],{"class":912},[250,14905,14906],{"class":252,"line":399},[250,14907,795],{"emptyLinePlaceholder":129},[250,14909,14910,14912,14914,14916,14919,14921,14923,14925,14927,14929,14931,14933,14935],{"class":252,"line":405},[250,14911,1019],{"class":786},[250,14913,2012],{"class":786},[250,14915,1845],{"class":786},[250,14917,14918],{"class":774}," validateUserCredentials",[250,14920,1434],{"class":912},[250,14922,14410],{"class":1370},[250,14924,1007],{"class":786},[250,14926,2506],{"class":778},[250,14928,7128],{"class":912},[250,14930,14248],{"class":1370},[250,14932,1007],{"class":786},[250,14934,2506],{"class":778},[250,14936,1512],{"class":912},[250,14938,14939,14941,14944,14946,14948,14950],{"class":252,"line":410},[250,14940,1455],{"class":786},[250,14942,14943],{"class":778}," user",[250,14945,1187],{"class":786},[250,14947,1463],{"class":786},[250,14949,14862],{"class":774},[250,14951,14952],{"class":912},"(email);\n",[250,14954,14955],{"class":252,"line":415},[250,14956,1053],{"class":912},[250,14958,14959,14961,14963,14965],{"class":252,"line":420},[250,14960,1486],{"class":786},[250,14962,1440],{"class":912},[250,14964,1491],{"class":786},[250,14966,14967],{"class":912},"user) {\n",[250,14969,14970,14972,14974],{"class":252,"line":426},[250,14971,14581],{"class":786},[250,14973,14546],{"class":778},[250,14975,1379],{"class":912},[250,14977,14978],{"class":252,"line":431},[250,14979,986],{"class":912},[250,14981,14982],{"class":252,"line":436},[250,14983,1053],{"class":912},[250,14985,14986,14988,14991,14993,14995,14997],{"class":252,"line":442},[250,14987,1455],{"class":786},[250,14989,14990],{"class":778}," isValid",[250,14992,1187],{"class":786},[250,14994,1463],{"class":786},[250,14996,14337],{"class":774},[250,14998,14999],{"class":912},"(user.password, password);\n",[250,15001,15002],{"class":252,"line":447},[250,15003,1053],{"class":912},[250,15005,15006,15008,15010,15012],{"class":252,"line":453},[250,15007,1486],{"class":786},[250,15009,1440],{"class":912},[250,15011,1491],{"class":786},[250,15013,15014],{"class":912},"isValid) {\n",[250,15016,15017,15019,15021],{"class":252,"line":459},[250,15018,14581],{"class":786},[250,15020,14546],{"class":778},[250,15022,1379],{"class":912},[250,15024,15025],{"class":252,"line":465},[250,15026,986],{"class":912},[250,15028,15029],{"class":252,"line":471},[250,15030,1053],{"class":912},[250,15032,15033,15035],{"class":252,"line":2201},[250,15034,1123],{"class":786},[250,15036,15037],{"class":912}," { id: user.id, email: user.email, name: user.name };\n",[250,15039,15040],{"class":252,"line":2207},[250,15041,991],{"class":912},[20,15043,15044,15045,1007],{},"Create the users schema in ",[39,15046,4389],{},[47,15048,15050],{"className":1010,"code":15049,"filename":4389,"language":1012,"meta":55,"style":55},"import { sqliteTable, text, integer } from \"drizzle-orm\u002Fsqlite-core\";\n\nexport const users = sqliteTable(\"users\", {\n  id: text(\"id\").primaryKey(),\n  email: text(\"email\").notNull().unique(),\n  password: text(\"password\").notNull(),\n  name: text(\"name\").notNull(),\n  createdAt: integer(\"created_at\", { mode: \"timestamp\" }).notNull(),\n});\n\nexport type User = typeof users.$inferSelect;\n",[39,15051,15052,15065,15069,15089,15105,15128,15146,15162,15182,15186,15190],{"__ignoreMap":55},[250,15053,15054,15056,15059,15061,15063],{"class":252,"line":253},[250,15055,1763],{"class":786},[250,15057,15058],{"class":912}," { sqliteTable, text, integer } ",[250,15060,1769],{"class":786},[250,15062,4406],{"class":782},[250,15064,1379],{"class":912},[250,15066,15067],{"class":252,"line":113},[250,15068,795],{"emptyLinePlaceholder":129},[250,15070,15071,15073,15075,15078,15080,15082,15084,15087],{"class":252,"line":110},[250,15072,1019],{"class":786},[250,15074,4438],{"class":786},[250,15076,15077],{"class":778}," users",[250,15079,1187],{"class":786},[250,15081,4446],{"class":774},[250,15083,1434],{"class":912},[250,15085,15086],{"class":782},"\"users\"",[250,15088,4454],{"class":912},[250,15090,15091,15093,15095,15097,15099,15101,15103],{"class":252,"line":269},[250,15092,4459],{"class":912},[250,15094,52],{"class":774},[250,15096,1434],{"class":912},[250,15098,4466],{"class":782},[250,15100,2380],{"class":912},[250,15102,4471],{"class":774},[250,15104,1156],{"class":912},[250,15106,15107,15110,15112,15114,15117,15119,15121,15123,15126],{"class":252,"line":275},[250,15108,15109],{"class":912},"  email: ",[250,15111,52],{"class":774},[250,15113,1434],{"class":912},[250,15115,15116],{"class":782},"\"email\"",[250,15118,2380],{"class":912},[250,15120,4490],{"class":774},[250,15122,1647],{"class":912},[250,15124,15125],{"class":774},"unique",[250,15127,1156],{"class":912},[250,15129,15130,15133,15135,15137,15140,15142,15144],{"class":252,"line":281},[250,15131,15132],{"class":912},"  password: ",[250,15134,52],{"class":774},[250,15136,1434],{"class":912},[250,15138,15139],{"class":782},"\"password\"",[250,15141,2380],{"class":912},[250,15143,4490],{"class":774},[250,15145,1156],{"class":912},[250,15147,15148,15150,15152,15154,15156,15158,15160],{"class":252,"line":287},[250,15149,4478],{"class":912},[250,15151,52],{"class":774},[250,15153,1434],{"class":912},[250,15155,4485],{"class":782},[250,15157,2380],{"class":912},[250,15159,4490],{"class":774},[250,15161,1156],{"class":912},[250,15163,15164,15166,15168,15170,15172,15174,15176,15178,15180],{"class":252,"line":293},[250,15165,4584],{"class":912},[250,15167,4556],{"class":774},[250,15169,1434],{"class":912},[250,15171,4591],{"class":782},[250,15173,4564],{"class":912},[250,15175,4596],{"class":782},[250,15177,4570],{"class":912},[250,15179,4490],{"class":774},[250,15181,1156],{"class":912},[250,15183,15184],{"class":252,"line":299},[250,15185,1077],{"class":912},[250,15187,15188],{"class":252,"line":132},[250,15189,795],{"emptyLinePlaceholder":129},[250,15191,15192,15194,15196,15199,15201,15203],{"class":252,"line":310},[250,15193,1019],{"class":786},[250,15195,4974],{"class":786},[250,15197,15198],{"class":774}," User",[250,15200,1187],{"class":786},[250,15202,4982],{"class":786},[250,15204,15205],{"class":912}," users.$inferSelect;\n",[72,15207],{},[31,15209,15211],{"id":15210},"step-5-create-authentication-api-routes","Step 5: Create Authentication API Routes",[2459,15213,15215],{"id":15214},"register","Register",[20,15217,1092,15218,1007],{},[39,15219,15220],{},"server\u002Fapi\u002Fauth\u002Fregister.post.ts",[47,15222,15224],{"className":1010,"code":15223,"filename":15220,"language":1012,"meta":55,"style":55},"import { createUser, findUserByEmail } from \"..\u002F..\u002Futils\u002Fdb\";\nimport { createToken } from \"..\u002F..\u002Futils\u002Fauth\";\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event);\n  \n  \u002F\u002F Validate input\n  if (!body.email || !body.password || !body.name) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Email, password, and name are required\",\n    });\n  }\n  \n  \u002F\u002F Check if user exists\n  const existing = await findUserByEmail(body.email);\n  \n  if (existing) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"User already exists\",\n    });\n  }\n  \n  \u002F\u002F Create user\n  await createUser({\n    email: body.email,\n    password: body.password,\n    name: body.name,\n  });\n  \n  \u002F\u002F Generate token\n  const token = await createToken(body.email, body.email);\n  \n  setCookie(event, \"auth_token\", token, {\n    httpOnly: true,\n    secure: process.env.NODE_ENV === \"production\",\n    sameSite: \"lax\",\n    maxAge: 60 * 60 * 24 * 7, \u002F\u002F 7 days\n  });\n  \n  return { success: true, email: body.email };\n});\n",[39,15225,15226,15240,15254,15258,15280,15294,15298,15302,15327,15335,15343,15352,15356,15360,15364,15369,15385,15389,15396,15404,15412,15421,15425,15429,15433,15438,15446,15451,15456,15461,15465,15469,15474,15490,15494,15507,15516,15531,15541,15569,15573,15577,15589],{"__ignoreMap":55},[250,15227,15228,15230,15233,15235,15238],{"class":252,"line":253},[250,15229,1763],{"class":786},[250,15231,15232],{"class":912}," { createUser, findUserByEmail } ",[250,15234,1769],{"class":786},[250,15236,15237],{"class":782}," \"..\u002F..\u002Futils\u002Fdb\"",[250,15239,1379],{"class":912},[250,15241,15242,15244,15247,15249,15252],{"class":252,"line":113},[250,15243,1763],{"class":786},[250,15245,15246],{"class":912}," { createToken } ",[250,15248,1769],{"class":786},[250,15250,15251],{"class":782}," \"..\u002F..\u002Futils\u002Fauth\"",[250,15253,1379],{"class":912},[250,15255,15256],{"class":252,"line":110},[250,15257,795],{"emptyLinePlaceholder":129},[250,15259,15260,15262,15264,15266,15268,15270,15272,15274,15276,15278],{"class":252,"line":269},[250,15261,1019],{"class":786},[250,15263,1022],{"class":786},[250,15265,1109],{"class":774},[250,15267,1434],{"class":912},[250,15269,1437],{"class":786},[250,15271,1440],{"class":912},[250,15273,1443],{"class":1370},[250,15275,1446],{"class":912},[250,15277,1115],{"class":786},[250,15279,1118],{"class":912},[250,15281,15282,15284,15286,15288,15290,15292],{"class":252,"line":275},[250,15283,1455],{"class":786},[250,15285,1458],{"class":778},[250,15287,1187],{"class":786},[250,15289,1463],{"class":786},[250,15291,1466],{"class":774},[250,15293,6261],{"class":912},[250,15295,15296],{"class":252,"line":281},[250,15297,1053],{"class":912},[250,15299,15300],{"class":252,"line":287},[250,15301,6270],{"class":768},[250,15303,15304,15306,15308,15310,15313,15315,15317,15320,15322,15324],{"class":252,"line":293},[250,15305,1486],{"class":786},[250,15307,1440],{"class":912},[250,15309,1491],{"class":786},[250,15311,15312],{"class":912},"body.email ",[250,15314,1497],{"class":786},[250,15316,6286],{"class":786},[250,15318,15319],{"class":912},"body.password ",[250,15321,1497],{"class":786},[250,15323,6286],{"class":786},[250,15325,15326],{"class":912},"body.name) {\n",[250,15328,15329,15331,15333],{"class":252,"line":299},[250,15330,1517],{"class":786},[250,15332,1520],{"class":774},[250,15334,1028],{"class":912},[250,15336,15337,15339,15341],{"class":252,"line":132},[250,15338,1527],{"class":912},[250,15340,1530],{"class":778},[250,15342,927],{"class":912},[250,15344,15345,15347,15350],{"class":252,"line":310},[250,15346,1537],{"class":912},[250,15348,15349],{"class":782},"\"Email, password, and name are required\"",[250,15351,927],{"class":912},[250,15353,15354],{"class":252,"line":316},[250,15355,1547],{"class":912},[250,15357,15358],{"class":252,"line":322},[250,15359,986],{"class":912},[250,15361,15362],{"class":252,"line":328},[250,15363,1053],{"class":912},[250,15365,15366],{"class":252,"line":334},[250,15367,15368],{"class":768},"  \u002F\u002F Check if user exists\n",[250,15370,15371,15373,15376,15378,15380,15382],{"class":252,"line":340},[250,15372,1455],{"class":786},[250,15374,15375],{"class":778}," existing",[250,15377,1187],{"class":786},[250,15379,1463],{"class":786},[250,15381,14862],{"class":774},[250,15383,15384],{"class":912},"(body.email);\n",[250,15386,15387],{"class":252,"line":346},[250,15388,1053],{"class":912},[250,15390,15391,15393],{"class":252,"line":352},[250,15392,1486],{"class":786},[250,15394,15395],{"class":912}," (existing) {\n",[250,15397,15398,15400,15402],{"class":252,"line":358},[250,15399,1517],{"class":786},[250,15401,1520],{"class":774},[250,15403,1028],{"class":912},[250,15405,15406,15408,15410],{"class":252,"line":364},[250,15407,1527],{"class":912},[250,15409,1530],{"class":778},[250,15411,927],{"class":912},[250,15413,15414,15416,15419],{"class":252,"line":370},[250,15415,1537],{"class":912},[250,15417,15418],{"class":782},"\"User already exists\"",[250,15420,927],{"class":912},[250,15422,15423],{"class":252,"line":376},[250,15424,1547],{"class":912},[250,15426,15427],{"class":252,"line":382},[250,15428,986],{"class":912},[250,15430,15431],{"class":252,"line":388},[250,15432,1053],{"class":912},[250,15434,15435],{"class":252,"line":393},[250,15436,15437],{"class":768},"  \u002F\u002F Create user\n",[250,15439,15440,15442,15444],{"class":252,"line":399},[250,15441,1565],{"class":786},[250,15443,14770],{"class":774},[250,15445,1028],{"class":912},[250,15447,15448],{"class":252,"line":405},[250,15449,15450],{"class":912},"    email: body.email,\n",[250,15452,15453],{"class":252,"line":410},[250,15454,15455],{"class":912},"    password: body.password,\n",[250,15457,15458],{"class":252,"line":415},[250,15459,15460],{"class":912},"    name: body.name,\n",[250,15462,15463],{"class":252,"line":420},[250,15464,6749],{"class":912},[250,15466,15467],{"class":252,"line":426},[250,15468,1053],{"class":912},[250,15470,15471],{"class":252,"line":431},[250,15472,15473],{"class":768},"  \u002F\u002F Generate token\n",[250,15475,15476,15478,15481,15483,15485,15487],{"class":252,"line":436},[250,15477,1455],{"class":786},[250,15479,15480],{"class":778}," token",[250,15482,1187],{"class":786},[250,15484,1463],{"class":786},[250,15486,14396],{"class":774},[250,15488,15489],{"class":912},"(body.email, body.email);\n",[250,15491,15492],{"class":252,"line":442},[250,15493,1053],{"class":912},[250,15495,15496,15499,15501,15504],{"class":252,"line":447},[250,15497,15498],{"class":774},"  setCookie",[250,15500,5972],{"class":912},[250,15502,15503],{"class":782},"\"auth_token\"",[250,15505,15506],{"class":912},", token, {\n",[250,15508,15509,15512,15514],{"class":252,"line":453},[250,15510,15511],{"class":912},"    httpOnly: ",[250,15513,1066],{"class":778},[250,15515,927],{"class":912},[250,15517,15518,15521,15524,15526,15529],{"class":252,"line":459},[250,15519,15520],{"class":912},"    secure: process.env.",[250,15522,15523],{"class":778},"NODE_ENV",[250,15525,1506],{"class":786},[250,15527,15528],{"class":782}," \"production\"",[250,15530,927],{"class":912},[250,15532,15533,15536,15539],{"class":252,"line":465},[250,15534,15535],{"class":912},"    sameSite: ",[250,15537,15538],{"class":782},"\"lax\"",[250,15540,927],{"class":912},[250,15542,15543,15546,15549,15551,15554,15556,15559,15561,15564,15566],{"class":252,"line":471},[250,15544,15545],{"class":912},"    maxAge: ",[250,15547,15548],{"class":778},"60",[250,15550,5094],{"class":786},[250,15552,15553],{"class":778}," 60",[250,15555,5094],{"class":786},[250,15557,15558],{"class":778}," 24",[250,15560,5094],{"class":786},[250,15562,15563],{"class":778}," 7",[250,15565,7128],{"class":912},[250,15567,15568],{"class":768},"\u002F\u002F 7 days\n",[250,15570,15571],{"class":252,"line":2201},[250,15572,6749],{"class":912},[250,15574,15575],{"class":252,"line":2207},[250,15576,1053],{"class":912},[250,15578,15579,15581,15584,15586],{"class":252,"line":2213},[250,15580,1123],{"class":786},[250,15582,15583],{"class":912}," { success: ",[250,15585,1066],{"class":778},[250,15587,15588],{"class":912},", email: body.email };\n",[250,15590,15591],{"class":252,"line":2218},[250,15592,1077],{"class":912},[2459,15594,15596],{"id":15595},"login","Login",[20,15598,1092,15599,1007],{},[39,15600,15601],{},"server\u002Fapi\u002Fauth\u002Flogin.post.ts",[47,15603,15605],{"className":1010,"code":15604,"filename":15601,"language":1012,"meta":55,"style":55},"import { validateUserCredentials } from \"..\u002F..\u002Futils\u002Fdb\";\nimport { createToken } from \"..\u002F..\u002Futils\u002Fauth\";\n\nexport default defineEventHandler(async (event) => {\n  const body = await readBody(event);\n  \n  if (!body.email || !body.password) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: \"Email and password are required\",\n    });\n  }\n  \n  const user = await validateUserCredentials(body.email, body.password);\n  \n  if (!user) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"Invalid credentials\",\n    });\n  }\n  \n  const token = await createToken(user.id, user.email);\n  \n  setCookie(event, \"auth_token\", token, {\n    httpOnly: true,\n    secure: process.env.NODE_ENV === \"production\",\n    sameSite: \"lax\",\n    maxAge: 60 * 60 * 24 * 7, \u002F\u002F 7 days\n  });\n  \n  return { success: true, user: { email: user.email, name: user.name } };\n});\n",[39,15606,15607,15620,15632,15636,15658,15672,15676,15693,15701,15709,15718,15722,15726,15730,15745,15749,15759,15767,15775,15784,15788,15792,15796,15811,15815,15825,15833,15845,15853,15875,15879,15883,15894],{"__ignoreMap":55},[250,15608,15609,15611,15614,15616,15618],{"class":252,"line":253},[250,15610,1763],{"class":786},[250,15612,15613],{"class":912}," { validateUserCredentials } ",[250,15615,1769],{"class":786},[250,15617,15237],{"class":782},[250,15619,1379],{"class":912},[250,15621,15622,15624,15626,15628,15630],{"class":252,"line":113},[250,15623,1763],{"class":786},[250,15625,15246],{"class":912},[250,15627,1769],{"class":786},[250,15629,15251],{"class":782},[250,15631,1379],{"class":912},[250,15633,15634],{"class":252,"line":110},[250,15635,795],{"emptyLinePlaceholder":129},[250,15637,15638,15640,15642,15644,15646,15648,15650,15652,15654,15656],{"class":252,"line":269},[250,15639,1019],{"class":786},[250,15641,1022],{"class":786},[250,15643,1109],{"class":774},[250,15645,1434],{"class":912},[250,15647,1437],{"class":786},[250,15649,1440],{"class":912},[250,15651,1443],{"class":1370},[250,15653,1446],{"class":912},[250,15655,1115],{"class":786},[250,15657,1118],{"class":912},[250,15659,15660,15662,15664,15666,15668,15670],{"class":252,"line":275},[250,15661,1455],{"class":786},[250,15663,1458],{"class":778},[250,15665,1187],{"class":786},[250,15667,1463],{"class":786},[250,15669,1466],{"class":774},[250,15671,6261],{"class":912},[250,15673,15674],{"class":252,"line":281},[250,15675,1053],{"class":912},[250,15677,15678,15680,15682,15684,15686,15688,15690],{"class":252,"line":287},[250,15679,1486],{"class":786},[250,15681,1440],{"class":912},[250,15683,1491],{"class":786},[250,15685,15312],{"class":912},[250,15687,1497],{"class":786},[250,15689,6286],{"class":786},[250,15691,15692],{"class":912},"body.password) {\n",[250,15694,15695,15697,15699],{"class":252,"line":293},[250,15696,1517],{"class":786},[250,15698,1520],{"class":774},[250,15700,1028],{"class":912},[250,15702,15703,15705,15707],{"class":252,"line":299},[250,15704,1527],{"class":912},[250,15706,1530],{"class":778},[250,15708,927],{"class":912},[250,15710,15711,15713,15716],{"class":252,"line":132},[250,15712,1537],{"class":912},[250,15714,15715],{"class":782},"\"Email and password are required\"",[250,15717,927],{"class":912},[250,15719,15720],{"class":252,"line":310},[250,15721,1547],{"class":912},[250,15723,15724],{"class":252,"line":316},[250,15725,986],{"class":912},[250,15727,15728],{"class":252,"line":322},[250,15729,1053],{"class":912},[250,15731,15732,15734,15736,15738,15740,15742],{"class":252,"line":328},[250,15733,1455],{"class":786},[250,15735,14943],{"class":778},[250,15737,1187],{"class":786},[250,15739,1463],{"class":786},[250,15741,14918],{"class":774},[250,15743,15744],{"class":912},"(body.email, body.password);\n",[250,15746,15747],{"class":252,"line":334},[250,15748,1053],{"class":912},[250,15750,15751,15753,15755,15757],{"class":252,"line":340},[250,15752,1486],{"class":786},[250,15754,1440],{"class":912},[250,15756,1491],{"class":786},[250,15758,14967],{"class":912},[250,15760,15761,15763,15765],{"class":252,"line":346},[250,15762,1517],{"class":786},[250,15764,1520],{"class":774},[250,15766,1028],{"class":912},[250,15768,15769,15771,15773],{"class":252,"line":352},[250,15770,1527],{"class":912},[250,15772,10538],{"class":778},[250,15774,927],{"class":912},[250,15776,15777,15779,15782],{"class":252,"line":358},[250,15778,1537],{"class":912},[250,15780,15781],{"class":782},"\"Invalid credentials\"",[250,15783,927],{"class":912},[250,15785,15786],{"class":252,"line":364},[250,15787,1547],{"class":912},[250,15789,15790],{"class":252,"line":370},[250,15791,986],{"class":912},[250,15793,15794],{"class":252,"line":376},[250,15795,1053],{"class":912},[250,15797,15798,15800,15802,15804,15806,15808],{"class":252,"line":382},[250,15799,1455],{"class":786},[250,15801,15480],{"class":778},[250,15803,1187],{"class":786},[250,15805,1463],{"class":786},[250,15807,14396],{"class":774},[250,15809,15810],{"class":912},"(user.id, user.email);\n",[250,15812,15813],{"class":252,"line":388},[250,15814,1053],{"class":912},[250,15816,15817,15819,15821,15823],{"class":252,"line":393},[250,15818,15498],{"class":774},[250,15820,5972],{"class":912},[250,15822,15503],{"class":782},[250,15824,15506],{"class":912},[250,15826,15827,15829,15831],{"class":252,"line":399},[250,15828,15511],{"class":912},[250,15830,1066],{"class":778},[250,15832,927],{"class":912},[250,15834,15835,15837,15839,15841,15843],{"class":252,"line":405},[250,15836,15520],{"class":912},[250,15838,15523],{"class":778},[250,15840,1506],{"class":786},[250,15842,15528],{"class":782},[250,15844,927],{"class":912},[250,15846,15847,15849,15851],{"class":252,"line":410},[250,15848,15535],{"class":912},[250,15850,15538],{"class":782},[250,15852,927],{"class":912},[250,15854,15855,15857,15859,15861,15863,15865,15867,15869,15871,15873],{"class":252,"line":415},[250,15856,15545],{"class":912},[250,15858,15548],{"class":778},[250,15860,5094],{"class":786},[250,15862,15553],{"class":778},[250,15864,5094],{"class":786},[250,15866,15558],{"class":778},[250,15868,5094],{"class":786},[250,15870,15563],{"class":778},[250,15872,7128],{"class":912},[250,15874,15568],{"class":768},[250,15876,15877],{"class":252,"line":420},[250,15878,6749],{"class":912},[250,15880,15881],{"class":252,"line":426},[250,15882,1053],{"class":912},[250,15884,15885,15887,15889,15891],{"class":252,"line":431},[250,15886,1123],{"class":786},[250,15888,15583],{"class":912},[250,15890,1066],{"class":778},[250,15892,15893],{"class":912},", user: { email: user.email, name: user.name } };\n",[250,15895,15896],{"class":252,"line":436},[250,15897,1077],{"class":912},[2459,15899,15901],{"id":15900},"logout","Logout",[20,15903,1092,15904,1007],{},[39,15905,15906],{},"server\u002Fapi\u002Fauth\u002Flogout.post.ts",[47,15908,15910],{"className":1010,"code":15909,"filename":15906,"language":1012,"meta":55,"style":55},"export default defineEventHandler(async (event) => {\n  deleteCookie(event, \"auth_token\");\n  return { success: true };\n});\n",[39,15911,15912,15934,15945,15955],{"__ignoreMap":55},[250,15913,15914,15916,15918,15920,15922,15924,15926,15928,15930,15932],{"class":252,"line":253},[250,15915,1019],{"class":786},[250,15917,1022],{"class":786},[250,15919,1109],{"class":774},[250,15921,1434],{"class":912},[250,15923,1437],{"class":786},[250,15925,1440],{"class":912},[250,15927,1443],{"class":1370},[250,15929,1446],{"class":912},[250,15931,1115],{"class":786},[250,15933,1118],{"class":912},[250,15935,15936,15939,15941,15943],{"class":252,"line":113},[250,15937,15938],{"class":774},"  deleteCookie",[250,15940,5972],{"class":912},[250,15942,15503],{"class":782},[250,15944,1885],{"class":912},[250,15946,15947,15949,15951,15953],{"class":252,"line":110},[250,15948,1123],{"class":786},[250,15950,15583],{"class":912},[250,15952,1066],{"class":778},[250,15954,5784],{"class":912},[250,15956,15957],{"class":252,"line":269},[250,15958,1077],{"class":912},[2459,15960,15962],{"id":15961},"get-current-user","Get Current User",[20,15964,1092,15965,1007],{},[39,15966,15967],{},"server\u002Fapi\u002Fauth\u002Fme.get.ts",[47,15969,15971],{"className":1010,"code":15970,"filename":15967,"language":1012,"meta":55,"style":55},"import { verifyToken } from \"..\u002F..\u002Futils\u002Fauth\";\nimport { findUserByEmail } from \"..\u002F..\u002Futils\u002Fdb\";\n\nexport default defineEventHandler(async (event) => {\n  const token = getCookie(event, \"auth_token\");\n  \n  if (!token) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"Not authenticated\",\n    });\n  }\n  \n  const payload = await verifyToken(token);\n  \n  if (!payload) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"Invalid token\",\n    });\n  }\n  \n  const user = await findUserByEmail(payload.email);\n  \n  if (!user) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"User not found\",\n    });\n  }\n  \n  return {\n    id: user.id,\n    email: user.email,\n    name: user.name,\n  };\n});\n",[39,15972,15973,15986,15999,16003,16025,16042,16046,16057,16065,16073,16082,16086,16090,16094,16110,16114,16125,16133,16141,16150,16154,16158,16162,16177,16181,16191,16199,16207,16216,16220,16224,16228,16234,16239,16244,16249,16253],{"__ignoreMap":55},[250,15974,15975,15977,15980,15982,15984],{"class":252,"line":253},[250,15976,1763],{"class":786},[250,15978,15979],{"class":912}," { verifyToken } ",[250,15981,1769],{"class":786},[250,15983,15251],{"class":782},[250,15985,1379],{"class":912},[250,15987,15988,15990,15993,15995,15997],{"class":252,"line":113},[250,15989,1763],{"class":786},[250,15991,15992],{"class":912}," { findUserByEmail } ",[250,15994,1769],{"class":786},[250,15996,15237],{"class":782},[250,15998,1379],{"class":912},[250,16000,16001],{"class":252,"line":110},[250,16002,795],{"emptyLinePlaceholder":129},[250,16004,16005,16007,16009,16011,16013,16015,16017,16019,16021,16023],{"class":252,"line":269},[250,16006,1019],{"class":786},[250,16008,1022],{"class":786},[250,16010,1109],{"class":774},[250,16012,1434],{"class":912},[250,16014,1437],{"class":786},[250,16016,1440],{"class":912},[250,16018,1443],{"class":1370},[250,16020,1446],{"class":912},[250,16022,1115],{"class":786},[250,16024,1118],{"class":912},[250,16026,16027,16029,16031,16033,16036,16038,16040],{"class":252,"line":275},[250,16028,1455],{"class":786},[250,16030,15480],{"class":778},[250,16032,1187],{"class":786},[250,16034,16035],{"class":774}," getCookie",[250,16037,5972],{"class":912},[250,16039,15503],{"class":782},[250,16041,1885],{"class":912},[250,16043,16044],{"class":252,"line":281},[250,16045,1053],{"class":912},[250,16047,16048,16050,16052,16054],{"class":252,"line":287},[250,16049,1486],{"class":786},[250,16051,1440],{"class":912},[250,16053,1491],{"class":786},[250,16055,16056],{"class":912},"token) {\n",[250,16058,16059,16061,16063],{"class":252,"line":293},[250,16060,1517],{"class":786},[250,16062,1520],{"class":774},[250,16064,1028],{"class":912},[250,16066,16067,16069,16071],{"class":252,"line":299},[250,16068,1527],{"class":912},[250,16070,10538],{"class":778},[250,16072,927],{"class":912},[250,16074,16075,16077,16080],{"class":252,"line":132},[250,16076,1537],{"class":912},[250,16078,16079],{"class":782},"\"Not authenticated\"",[250,16081,927],{"class":912},[250,16083,16084],{"class":252,"line":310},[250,16085,1547],{"class":912},[250,16087,16088],{"class":252,"line":316},[250,16089,986],{"class":912},[250,16091,16092],{"class":252,"line":322},[250,16093,1053],{"class":912},[250,16095,16096,16098,16101,16103,16105,16107],{"class":252,"line":328},[250,16097,1455],{"class":786},[250,16099,16100],{"class":778}," payload",[250,16102,1187],{"class":786},[250,16104,1463],{"class":786},[250,16106,14505],{"class":774},[250,16108,16109],{"class":912},"(token);\n",[250,16111,16112],{"class":252,"line":334},[250,16113,1053],{"class":912},[250,16115,16116,16118,16120,16122],{"class":252,"line":340},[250,16117,1486],{"class":786},[250,16119,1440],{"class":912},[250,16121,1491],{"class":786},[250,16123,16124],{"class":912},"payload) {\n",[250,16126,16127,16129,16131],{"class":252,"line":346},[250,16128,1517],{"class":786},[250,16130,1520],{"class":774},[250,16132,1028],{"class":912},[250,16134,16135,16137,16139],{"class":252,"line":352},[250,16136,1527],{"class":912},[250,16138,10538],{"class":778},[250,16140,927],{"class":912},[250,16142,16143,16145,16148],{"class":252,"line":358},[250,16144,1537],{"class":912},[250,16146,16147],{"class":782},"\"Invalid token\"",[250,16149,927],{"class":912},[250,16151,16152],{"class":252,"line":364},[250,16153,1547],{"class":912},[250,16155,16156],{"class":252,"line":370},[250,16157,986],{"class":912},[250,16159,16160],{"class":252,"line":376},[250,16161,1053],{"class":912},[250,16163,16164,16166,16168,16170,16172,16174],{"class":252,"line":382},[250,16165,1455],{"class":786},[250,16167,14943],{"class":778},[250,16169,1187],{"class":786},[250,16171,1463],{"class":786},[250,16173,14862],{"class":774},[250,16175,16176],{"class":912},"(payload.email);\n",[250,16178,16179],{"class":252,"line":388},[250,16180,1053],{"class":912},[250,16182,16183,16185,16187,16189],{"class":252,"line":393},[250,16184,1486],{"class":786},[250,16186,1440],{"class":912},[250,16188,1491],{"class":786},[250,16190,14967],{"class":912},[250,16192,16193,16195,16197],{"class":252,"line":399},[250,16194,1517],{"class":786},[250,16196,1520],{"class":774},[250,16198,1028],{"class":912},[250,16200,16201,16203,16205],{"class":252,"line":405},[250,16202,1527],{"class":912},[250,16204,10538],{"class":778},[250,16206,927],{"class":912},[250,16208,16209,16211,16214],{"class":252,"line":410},[250,16210,1537],{"class":912},[250,16212,16213],{"class":782},"\"User not found\"",[250,16215,927],{"class":912},[250,16217,16218],{"class":252,"line":415},[250,16219,1547],{"class":912},[250,16221,16222],{"class":252,"line":420},[250,16223,986],{"class":912},[250,16225,16226],{"class":252,"line":426},[250,16227,1053],{"class":912},[250,16229,16230,16232],{"class":252,"line":431},[250,16231,1123],{"class":786},[250,16233,1118],{"class":912},[250,16235,16236],{"class":252,"line":436},[250,16237,16238],{"class":912},"    id: user.id,\n",[250,16240,16241],{"class":252,"line":442},[250,16242,16243],{"class":912},"    email: user.email,\n",[250,16245,16246],{"class":252,"line":447},[250,16247,16248],{"class":912},"    name: user.name,\n",[250,16250,16251],{"class":252,"line":453},[250,16252,1161],{"class":912},[250,16254,16255],{"class":252,"line":459},[250,16256,1077],{"class":912},[72,16258],{},[31,16260,16262],{"id":16261},"step-6-protect-api-routes","Step 6: Protect API Routes",[20,16264,16265],{},"Now let's protect our order management endpoints so only authenticated users can access them.",[20,16267,1003,16268,1007],{},[39,16269,7575],{},[47,16271,16273],{"className":1010,"code":16272,"filename":7575,"language":1012,"meta":55,"style":55},"import { db } from \"..\u002Fdb\";\nimport { orders, orderItems } from \"..\u002Fdb\u002Fschema\";\nimport { verifyToken } from \"..\u002Futils\u002Fauth\";\n\nexport default defineEventHandler(async (event) => {\n  \u002F\u002F Authentication check\n  const token = getCookie(event, \"auth_token\");\n  \n  if (!token) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"Authentication required\",\n    });\n  }\n  \n  const payload = await verifyToken(token);\n  \n  if (!payload) {\n    throw createError({\n      statusCode: 401,\n      statusMessage: \"Invalid token\",\n    });\n  }\n  \n  const allOrders = await db\n    .select()\n    .from(orders)\n    .orderBy(orders.createdAt);\n  \n  const ordersWithItems = await Promise.all(\n    allOrders.map(async (order) => {\n      const items = await db\n        .select()\n        .from(orderItems)\n        .where(orderItems.orderId.equals(order.id));\n      return { ...order, items };\n    })\n  );\n  \n  return { orders: ordersWithItems };\n});\n",[39,16274,16275,16287,16299,16312,16316,16338,16343,16359,16363,16373,16381,16389,16398,16402,16406,16410,16424,16428,16438,16446,16454,16462,16466,16470,16474,16486,16494,16502,16510,16514,16532,16552,16564,16572,16580,16592,16602,16606,16610,16614,16620],{"__ignoreMap":55},[250,16276,16277,16279,16281,16283,16285],{"class":252,"line":253},[250,16278,1763],{"class":786},[250,16280,5369],{"class":912},[250,16282,1769],{"class":786},[250,16284,5374],{"class":782},[250,16286,1379],{"class":912},[250,16288,16289,16291,16293,16295,16297],{"class":252,"line":113},[250,16290,1763],{"class":786},[250,16292,7599],{"class":912},[250,16294,1769],{"class":786},[250,16296,5388],{"class":782},[250,16298,1379],{"class":912},[250,16300,16301,16303,16305,16307,16310],{"class":252,"line":110},[250,16302,1763],{"class":786},[250,16304,15979],{"class":912},[250,16306,1769],{"class":786},[250,16308,16309],{"class":782}," \"..\u002Futils\u002Fauth\"",[250,16311,1379],{"class":912},[250,16313,16314],{"class":252,"line":269},[250,16315,795],{"emptyLinePlaceholder":129},[250,16317,16318,16320,16322,16324,16326,16328,16330,16332,16334,16336],{"class":252,"line":275},[250,16319,1019],{"class":786},[250,16321,1022],{"class":786},[250,16323,1109],{"class":774},[250,16325,1434],{"class":912},[250,16327,1437],{"class":786},[250,16329,1440],{"class":912},[250,16331,1443],{"class":1370},[250,16333,1446],{"class":912},[250,16335,1115],{"class":786},[250,16337,1118],{"class":912},[250,16339,16340],{"class":252,"line":281},[250,16341,16342],{"class":768},"  \u002F\u002F Authentication check\n",[250,16344,16345,16347,16349,16351,16353,16355,16357],{"class":252,"line":287},[250,16346,1455],{"class":786},[250,16348,15480],{"class":778},[250,16350,1187],{"class":786},[250,16352,16035],{"class":774},[250,16354,5972],{"class":912},[250,16356,15503],{"class":782},[250,16358,1885],{"class":912},[250,16360,16361],{"class":252,"line":293},[250,16362,1053],{"class":912},[250,16364,16365,16367,16369,16371],{"class":252,"line":299},[250,16366,1486],{"class":786},[250,16368,1440],{"class":912},[250,16370,1491],{"class":786},[250,16372,16056],{"class":912},[250,16374,16375,16377,16379],{"class":252,"line":132},[250,16376,1517],{"class":786},[250,16378,1520],{"class":774},[250,16380,1028],{"class":912},[250,16382,16383,16385,16387],{"class":252,"line":310},[250,16384,1527],{"class":912},[250,16386,10538],{"class":778},[250,16388,927],{"class":912},[250,16390,16391,16393,16396],{"class":252,"line":316},[250,16392,1537],{"class":912},[250,16394,16395],{"class":782},"\"Authentication required\"",[250,16397,927],{"class":912},[250,16399,16400],{"class":252,"line":322},[250,16401,1547],{"class":912},[250,16403,16404],{"class":252,"line":328},[250,16405,986],{"class":912},[250,16407,16408],{"class":252,"line":334},[250,16409,1053],{"class":912},[250,16411,16412,16414,16416,16418,16420,16422],{"class":252,"line":340},[250,16413,1455],{"class":786},[250,16415,16100],{"class":778},[250,16417,1187],{"class":786},[250,16419,1463],{"class":786},[250,16421,14505],{"class":774},[250,16423,16109],{"class":912},[250,16425,16426],{"class":252,"line":346},[250,16427,1053],{"class":912},[250,16429,16430,16432,16434,16436],{"class":252,"line":352},[250,16431,1486],{"class":786},[250,16433,1440],{"class":912},[250,16435,1491],{"class":786},[250,16437,16124],{"class":912},[250,16439,16440,16442,16444],{"class":252,"line":358},[250,16441,1517],{"class":786},[250,16443,1520],{"class":774},[250,16445,1028],{"class":912},[250,16447,16448,16450,16452],{"class":252,"line":364},[250,16449,1527],{"class":912},[250,16451,10538],{"class":778},[250,16453,927],{"class":912},[250,16455,16456,16458,16460],{"class":252,"line":370},[250,16457,1537],{"class":912},[250,16459,16147],{"class":782},[250,16461,927],{"class":912},[250,16463,16464],{"class":252,"line":376},[250,16465,1547],{"class":912},[250,16467,16468],{"class":252,"line":382},[250,16469,986],{"class":912},[250,16471,16472],{"class":252,"line":388},[250,16473,1053],{"class":912},[250,16475,16476,16478,16480,16482,16484],{"class":252,"line":393},[250,16477,1455],{"class":786},[250,16479,7634],{"class":778},[250,16481,1187],{"class":786},[250,16483,1463],{"class":786},[250,16485,6413],{"class":912},[250,16487,16488,16490,16492],{"class":252,"line":399},[250,16489,4604],{"class":912},[250,16491,5870],{"class":774},[250,16493,4861],{"class":912},[250,16495,16496,16498,16500],{"class":252,"line":405},[250,16497,4604],{"class":912},[250,16499,1769],{"class":774},[250,16501,6945],{"class":912},[250,16503,16504,16506,16508],{"class":252,"line":410},[250,16505,4604],{"class":912},[250,16507,7663],{"class":774},[250,16509,7666],{"class":912},[250,16511,16512],{"class":252,"line":415},[250,16513,1053],{"class":912},[250,16515,16516,16518,16520,16522,16524,16526,16528,16530],{"class":252,"line":420},[250,16517,1455],{"class":786},[250,16519,7682],{"class":778},[250,16521,1187],{"class":786},[250,16523,1463],{"class":786},[250,16525,1571],{"class":778},[250,16527,2230],{"class":912},[250,16529,2233],{"class":774},[250,16531,1982],{"class":912},[250,16533,16534,16536,16538,16540,16542,16544,16546,16548,16550],{"class":252,"line":426},[250,16535,7699],{"class":912},[250,16537,2820],{"class":774},[250,16539,1434],{"class":912},[250,16541,1437],{"class":786},[250,16543,1440],{"class":912},[250,16545,7710],{"class":1370},[250,16547,1446],{"class":912},[250,16549,1115],{"class":786},[250,16551,1118],{"class":912},[250,16553,16554,16556,16558,16560,16562],{"class":252,"line":431},[250,16555,7721],{"class":786},[250,16557,5861],{"class":778},[250,16559,1187],{"class":786},[250,16561,1463],{"class":786},[250,16563,6413],{"class":912},[250,16565,16566,16568,16570],{"class":252,"line":436},[250,16567,7734],{"class":912},[250,16569,5870],{"class":774},[250,16571,4861],{"class":912},[250,16573,16574,16576,16578],{"class":252,"line":442},[250,16575,7734],{"class":912},[250,16577,1769],{"class":774},[250,16579,7005],{"class":912},[250,16581,16582,16584,16586,16588,16590],{"class":252,"line":447},[250,16583,7734],{"class":912},[250,16585,5879],{"class":774},[250,16587,7755],{"class":912},[250,16589,6056],{"class":774},[250,16591,7760],{"class":912},[250,16593,16594,16596,16598,16600],{"class":252,"line":453},[250,16595,7765],{"class":786},[250,16597,7768],{"class":912},[250,16599,7771],{"class":786},[250,16601,7774],{"class":912},[250,16603,16604],{"class":252,"line":459},[250,16605,7485],{"class":912},[250,16607,16608],{"class":252,"line":465},[250,16609,2859],{"class":912},[250,16611,16612],{"class":252,"line":471},[250,16613,1053],{"class":912},[250,16615,16616,16618],{"class":252,"line":2201},[250,16617,1123],{"class":786},[250,16619,7793],{"class":912},[250,16621,16622],{"class":252,"line":2207},[250,16623,1077],{"class":912},[161,16625,16627],{"icon":7846,"title":16626},"Middleware Pattern",[20,16628,16629],{},"You can extract this auth check into a reusable middleware function to protect multiple routes without repetition.",[72,16631],{},[31,16633,16635],{"id":16634},"step-7-add-oauth-with-github","Step 7: Add OAuth with GitHub",[20,16637,16638],{},"Let's add social login using GitHub as an example.",[20,16640,16641,16642],{},"First, create a GitHub OAuth app at ",[203,16643,16644],{"href":16644,"rel":16645},"https:\u002F\u002Fgithub.com\u002Fsettings\u002Fdevelopers",[207],[20,16647,16648,16649,1007],{},"Add credentials to your ",[39,16650,14116],{},[47,16652,16654],{"className":758,"code":16653,"filename":14116,"language":761,"meta":55,"style":55},"GITHUB_CLIENT_ID=your_client_id\nGITHUB_CLIENT_SECRET=your_client_secret\n",[39,16655,16656,16666],{"__ignoreMap":55},[250,16657,16658,16661,16663],{"class":252,"line":253},[250,16659,16660],{"class":912},"GITHUB_CLIENT_ID",[250,16662,1416],{"class":786},[250,16664,16665],{"class":782},"your_client_id\n",[250,16667,16668,16671,16673],{"class":252,"line":113},[250,16669,16670],{"class":912},"GITHUB_CLIENT_SECRET",[250,16672,1416],{"class":786},[250,16674,16675],{"class":782},"your_client_secret\n",[20,16677,1003,16678,1007],{},[39,16679,1006],{},[47,16681,16683],{"className":1010,"code":16682,"filename":1006,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  auth: {\n    provider: {\n      type: \"authjs\",\n      provider: \"github\",\n    },\n    globalAppMiddleware: true,\n  },\n  \n  runtimeConfig: {\n    authSecret: process.env.AUTH_SECRET,\n    github: {\n      clientId: process.env.GITHUB_CLIENT_ID,\n      clientSecret: process.env.GITHUB_CLIENT_SECRET,\n    },\n    public: {\n      authOrigin: process.env.AUTH_ORIGIN || \"http:\u002F\u002Flocalhost:3000\",\n    },\n  },\n});\n",[39,16684,16685,16695,16699,16703,16711,16721,16725,16733,16737,16741,16745,16753,16758,16767,16776,16780,16784,16796,16800,16804],{"__ignoreMap":55},[250,16686,16687,16689,16691,16693],{"class":252,"line":253},[250,16688,1019],{"class":786},[250,16690,1022],{"class":786},[250,16692,1025],{"class":774},[250,16694,1028],{"class":912},[250,16696,16697],{"class":252,"line":113},[250,16698,14009],{"class":912},[250,16700,16701],{"class":252,"line":110},[250,16702,14014],{"class":912},[250,16704,16705,16707,16709],{"class":252,"line":269},[250,16706,14019],{"class":912},[250,16708,14022],{"class":782},[250,16710,927],{"class":912},[250,16712,16713,16716,16719],{"class":252,"line":275},[250,16714,16715],{"class":912},"      provider: ",[250,16717,16718],{"class":782},"\"github\"",[250,16720,927],{"class":912},[250,16722,16723],{"class":252,"line":281},[250,16724,14039],{"class":912},[250,16726,16727,16729,16731],{"class":252,"line":287},[250,16728,14044],{"class":912},[250,16730,1066],{"class":778},[250,16732,927],{"class":912},[250,16734,16735],{"class":252,"line":293},[250,16736,1048],{"class":912},[250,16738,16739],{"class":252,"line":299},[250,16740,1053],{"class":912},[250,16742,16743],{"class":252,"line":132},[250,16744,8929],{"class":912},[250,16746,16747,16749,16751],{"class":252,"line":310},[250,16748,14065],{"class":912},[250,16750,14068],{"class":778},[250,16752,927],{"class":912},[250,16754,16755],{"class":252,"line":316},[250,16756,16757],{"class":912},"    github: {\n",[250,16759,16760,16763,16765],{"class":252,"line":322},[250,16761,16762],{"class":912},"      clientId: process.env.",[250,16764,16660],{"class":778},[250,16766,927],{"class":912},[250,16768,16769,16772,16774],{"class":252,"line":328},[250,16770,16771],{"class":912},"      clientSecret: process.env.",[250,16773,16670],{"class":778},[250,16775,927],{"class":912},[250,16777,16778],{"class":252,"line":334},[250,16779,14039],{"class":912},[250,16781,16782],{"class":252,"line":340},[250,16783,8934],{"class":912},[250,16785,16786,16788,16790,16792,16794],{"class":252,"line":346},[250,16787,14079],{"class":912},[250,16789,14082],{"class":778},[250,16791,14085],{"class":786},[250,16793,14088],{"class":782},[250,16795,927],{"class":912},[250,16797,16798],{"class":252,"line":352},[250,16799,14039],{"class":912},[250,16801,16802],{"class":252,"line":358},[250,16803,1048],{"class":912},[250,16805,16806],{"class":252,"line":364},[250,16807,1077],{"class":912},[20,16809,1092,16810,1007],{},[39,16811,16812],{},"server\u002Fapi\u002Fauth\u002F[...].ts",[47,16814,16816],{"className":1010,"code":16815,"filename":16812,"language":1012,"meta":55,"style":55},"import { NuxtAuthHandler } from \"@sidebase\u002Fnuxt-auth\";\nimport GithubProvider from \"next-auth\u002Fproviders\u002Fgithub\";\n\nexport default NuxtAuthHandler({\n  secret: process.env.AUTH_SECRET,\n  providers: [\n    GithubProvider.default({\n      clientId: process.env.GITHUB_CLIENT_ID,\n      clientSecret: process.env.GITHUB_CLIENT_SECRET,\n    }),\n  ],\n});\n",[39,16817,16818,16832,16846,16850,16861,16870,16875,16884,16892,16900,16904,16908],{"__ignoreMap":55},[250,16819,16820,16822,16825,16827,16830],{"class":252,"line":253},[250,16821,1763],{"class":786},[250,16823,16824],{"class":912}," { NuxtAuthHandler } ",[250,16826,1769],{"class":786},[250,16828,16829],{"class":782}," \"@sidebase\u002Fnuxt-auth\"",[250,16831,1379],{"class":912},[250,16833,16834,16836,16839,16841,16844],{"class":252,"line":113},[250,16835,1763],{"class":786},[250,16837,16838],{"class":912}," GithubProvider ",[250,16840,1769],{"class":786},[250,16842,16843],{"class":782}," \"next-auth\u002Fproviders\u002Fgithub\"",[250,16845,1379],{"class":912},[250,16847,16848],{"class":252,"line":110},[250,16849,795],{"emptyLinePlaceholder":129},[250,16851,16852,16854,16856,16859],{"class":252,"line":269},[250,16853,1019],{"class":786},[250,16855,1022],{"class":786},[250,16857,16858],{"class":774}," NuxtAuthHandler",[250,16860,1028],{"class":912},[250,16862,16863,16866,16868],{"class":252,"line":275},[250,16864,16865],{"class":912},"  secret: process.env.",[250,16867,14068],{"class":778},[250,16869,927],{"class":912},[250,16871,16872],{"class":252,"line":281},[250,16873,16874],{"class":912},"  providers: [\n",[250,16876,16877,16880,16882],{"class":252,"line":287},[250,16878,16879],{"class":912},"    GithubProvider.",[250,16881,4573],{"class":774},[250,16883,1028],{"class":912},[250,16885,16886,16888,16890],{"class":252,"line":293},[250,16887,16762],{"class":912},[250,16889,16660],{"class":778},[250,16891,927],{"class":912},[250,16893,16894,16896,16898],{"class":252,"line":299},[250,16895,16771],{"class":912},[250,16897,16670],{"class":778},[250,16899,927],{"class":912},[250,16901,16902],{"class":252,"line":132},[250,16903,462],{"class":912},[250,16905,16906],{"class":252,"line":310},[250,16907,468],{"class":912},[250,16909,16910],{"class":252,"line":316},[250,16911,1077],{"class":912},[72,16913],{},[31,16915,16917],{"id":16916},"step-8-create-the-frontend-auth-pages","Step 8: Create the Frontend Auth Pages",[20,16919,1092,16920,1007],{},[39,16921,16922],{},"pages\u002Flogin.vue",[47,16924,16927],{"className":16925,"code":16926,"filename":16922,"language":13747,"meta":55,"style":55},"language-vue shiki shiki-themes github-light github-dark","\u003Ctemplate>\n  \u003Cdiv class=\"auth-page\">\n    \u003Ch1>Login to BrewStop\u003C\u002Fh1>\n    \n    \u003Cform @submit.prevent=\"handleLogin\">\n      \u003Cdiv class=\"form-group\">\n        \u003Clabel>Email\u003C\u002Flabel>\n        \u003Cinput v-model=\"email\" type=\"email\" required \u002F>\n      \u003C\u002Fdiv>\n      \n      \u003Cdiv class=\"form-group\">\n        \u003Clabel>Password\u003C\u002Flabel>\n        \u003Cinput v-model=\"password\" type=\"password\" required \u002F>\n      \u003C\u002Fdiv>\n      \n      \u003Cbutton type=\"submit\" :disabled=\"loading\">\n        {{ loading ? \"Logging in...\" : \"Login\" }}\n      \u003C\u002Fbutton>\n      \n      \u003Cp v-if=\"error\" class=\"error\">{{ error }}\u003C\u002Fp>\n    \u003C\u002Fform>\n    \n    \u003Cp class=\"oauth-separator\">or\u003C\u002Fp>\n    \n    \u003Cbutton @click=\"loginWithGithub\" class=\"github-btn\">\n      Continue with GitHub\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst email = ref(\"\");\nconst password = ref(\"\");\nconst loading = ref(false);\nconst error = ref(\"\");\n\nasync function handleLogin() {\n  loading.value = true;\n  error.value = \"\";\n  \n  try {\n    await $fetch(\"\u002Fapi\u002Fauth\u002Flogin\", {\n      method: \"POST\",\n      body: { email: email.value, password: password.value },\n    });\n    \n    navigateTo(\"\u002Fdashboard\");\n  } catch (e: any) {\n    error.value = e.data?.statusMessage || \"Login failed\";\n  } finally {\n    loading.value = false;\n  }\n}\n\nasync function loginWithGithub() {\n  await navigateTo(\"\u002Fapi\u002Fauth\u002Fsignin\u002Fgithub\", { external: true });\n}\n\u003C\u002Fscript>\n",[39,16928,16929,16939,16957,16971,16975,16992,17008,17023,17048,17057,17062,17076,17089,17111,17119,17123,17147,17152,17160,17164,17190,17199,17203,17223,17227,17250,17255,17263,17272,17280,17284,17302,17320,17337,17355,17372,17376,17387,17399,17411,17415,17421,17435,17445,17450,17454,17458,17470,17487,17504,17513,17525,17529,17533,17537,17548,17568,17572],{"__ignoreMap":55},[250,16930,16931,16933,16937],{"class":252,"line":253},[250,16932,1962],{"class":912},[250,16934,16936],{"class":16935},"s9eBZ","template",[250,16938,13111],{"class":912},[250,16940,16941,16944,16947,16950,16952,16955],{"class":252,"line":113},[250,16942,16943],{"class":912},"  \u003C",[250,16945,16946],{"class":16935},"div",[250,16948,16949],{"class":774}," class",[250,16951,1416],{"class":912},[250,16953,16954],{"class":782},"\"auth-page\"",[250,16956,13111],{"class":912},[250,16958,16959,16962,16964,16967,16969],{"class":252,"line":110},[250,16960,16961],{"class":912},"    \u003C",[250,16963,15],{"class":16935},[250,16965,16966],{"class":912},">Login to BrewStop\u003C\u002F",[250,16968,15],{"class":16935},[250,16970,13111],{"class":912},[250,16972,16973],{"class":252,"line":269},[250,16974,6458],{"class":912},[250,16976,16977,16979,16982,16985,16987,16990],{"class":252,"line":275},[250,16978,16961],{"class":912},[250,16980,16981],{"class":16935},"form",[250,16983,16984],{"class":774}," @submit.prevent",[250,16986,1416],{"class":912},[250,16988,16989],{"class":782},"\"handleLogin\"",[250,16991,13111],{"class":912},[250,16993,16994,16997,16999,17001,17003,17006],{"class":252,"line":281},[250,16995,16996],{"class":912},"      \u003C",[250,16998,16946],{"class":16935},[250,17000,16949],{"class":774},[250,17002,1416],{"class":912},[250,17004,17005],{"class":782},"\"form-group\"",[250,17007,13111],{"class":912},[250,17009,17010,17013,17016,17019,17021],{"class":252,"line":287},[250,17011,17012],{"class":912},"        \u003C",[250,17014,17015],{"class":16935},"label",[250,17017,17018],{"class":912},">Email\u003C\u002F",[250,17020,17015],{"class":16935},[250,17022,13111],{"class":912},[250,17024,17025,17027,17029,17032,17034,17036,17038,17040,17042,17045],{"class":252,"line":293},[250,17026,17012],{"class":912},[250,17028,14775],{"class":16935},[250,17030,17031],{"class":774}," v-model",[250,17033,1416],{"class":912},[250,17035,15116],{"class":782},[250,17037,4974],{"class":774},[250,17039,1416],{"class":912},[250,17041,15116],{"class":782},[250,17043,17044],{"class":774}," required",[250,17046,17047],{"class":912}," \u002F>\n",[250,17049,17050,17053,17055],{"class":252,"line":299},[250,17051,17052],{"class":912},"      \u003C\u002F",[250,17054,16946],{"class":16935},[250,17056,13111],{"class":912},[250,17058,17059],{"class":252,"line":132},[250,17060,17061],{"class":912},"      \n",[250,17063,17064,17066,17068,17070,17072,17074],{"class":252,"line":310},[250,17065,16996],{"class":912},[250,17067,16946],{"class":16935},[250,17069,16949],{"class":774},[250,17071,1416],{"class":912},[250,17073,17005],{"class":782},[250,17075,13111],{"class":912},[250,17077,17078,17080,17082,17085,17087],{"class":252,"line":316},[250,17079,17012],{"class":912},[250,17081,17015],{"class":16935},[250,17083,17084],{"class":912},">Password\u003C\u002F",[250,17086,17015],{"class":16935},[250,17088,13111],{"class":912},[250,17090,17091,17093,17095,17097,17099,17101,17103,17105,17107,17109],{"class":252,"line":322},[250,17092,17012],{"class":912},[250,17094,14775],{"class":16935},[250,17096,17031],{"class":774},[250,17098,1416],{"class":912},[250,17100,15139],{"class":782},[250,17102,4974],{"class":774},[250,17104,1416],{"class":912},[250,17106,15139],{"class":782},[250,17108,17044],{"class":774},[250,17110,17047],{"class":912},[250,17112,17113,17115,17117],{"class":252,"line":328},[250,17114,17052],{"class":912},[250,17116,16946],{"class":16935},[250,17118,13111],{"class":912},[250,17120,17121],{"class":252,"line":334},[250,17122,17061],{"class":912},[250,17124,17125,17127,17130,17132,17134,17137,17140,17142,17145],{"class":252,"line":340},[250,17126,16996],{"class":912},[250,17128,17129],{"class":16935},"button",[250,17131,4974],{"class":774},[250,17133,1416],{"class":912},[250,17135,17136],{"class":782},"\"submit\"",[250,17138,17139],{"class":774}," :disabled",[250,17141,1416],{"class":912},[250,17143,17144],{"class":782},"\"loading\"",[250,17146,13111],{"class":912},[250,17148,17149],{"class":252,"line":346},[250,17150,17151],{"class":912},"        {{ loading ? \"Logging in...\" : \"Login\" }}\n",[250,17153,17154,17156,17158],{"class":252,"line":352},[250,17155,17052],{"class":912},[250,17157,17129],{"class":16935},[250,17159,13111],{"class":912},[250,17161,17162],{"class":252,"line":358},[250,17163,17061],{"class":912},[250,17165,17166,17168,17170,17173,17175,17177,17179,17181,17183,17186,17188],{"class":252,"line":364},[250,17167,16996],{"class":912},[250,17169,20],{"class":16935},[250,17171,17172],{"class":774}," v-if",[250,17174,1416],{"class":912},[250,17176,12292],{"class":782},[250,17178,16949],{"class":774},[250,17180,1416],{"class":912},[250,17182,12292],{"class":782},[250,17184,17185],{"class":912},">{{ error }}\u003C\u002F",[250,17187,20],{"class":16935},[250,17189,13111],{"class":912},[250,17191,17192,17195,17197],{"class":252,"line":370},[250,17193,17194],{"class":912},"    \u003C\u002F",[250,17196,16981],{"class":16935},[250,17198,13111],{"class":912},[250,17200,17201],{"class":252,"line":376},[250,17202,6458],{"class":912},[250,17204,17205,17207,17209,17211,17213,17216,17219,17221],{"class":252,"line":382},[250,17206,16961],{"class":912},[250,17208,20],{"class":16935},[250,17210,16949],{"class":774},[250,17212,1416],{"class":912},[250,17214,17215],{"class":782},"\"oauth-separator\"",[250,17217,17218],{"class":912},">or\u003C\u002F",[250,17220,20],{"class":16935},[250,17222,13111],{"class":912},[250,17224,17225],{"class":252,"line":388},[250,17226,6458],{"class":912},[250,17228,17229,17231,17233,17236,17238,17241,17243,17245,17248],{"class":252,"line":393},[250,17230,16961],{"class":912},[250,17232,17129],{"class":16935},[250,17234,17235],{"class":774}," @click",[250,17237,1416],{"class":912},[250,17239,17240],{"class":782},"\"loginWithGithub\"",[250,17242,16949],{"class":774},[250,17244,1416],{"class":912},[250,17246,17247],{"class":782},"\"github-btn\"",[250,17249,13111],{"class":912},[250,17251,17252],{"class":252,"line":399},[250,17253,17254],{"class":912},"      Continue with GitHub\n",[250,17256,17257,17259,17261],{"class":252,"line":405},[250,17258,17194],{"class":912},[250,17260,17129],{"class":16935},[250,17262,13111],{"class":912},[250,17264,17265,17268,17270],{"class":252,"line":410},[250,17266,17267],{"class":912},"  \u003C\u002F",[250,17269,16946],{"class":16935},[250,17271,13111],{"class":912},[250,17273,17274,17276,17278],{"class":252,"line":415},[250,17275,13209],{"class":912},[250,17277,16936],{"class":16935},[250,17279,13111],{"class":912},[250,17281,17282],{"class":252,"line":420},[250,17283,795],{"emptyLinePlaceholder":129},[250,17285,17286,17288,17290,17293,17296,17298,17300],{"class":252,"line":426},[250,17287,1962],{"class":912},[250,17289,13212],{"class":16935},[250,17291,17292],{"class":774}," setup",[250,17294,17295],{"class":774}," lang",[250,17297,1416],{"class":912},[250,17299,13108],{"class":782},[250,17301,13111],{"class":912},[250,17303,17304,17306,17309,17311,17313,17315,17318],{"class":252,"line":431},[250,17305,1181],{"class":786},[250,17307,17308],{"class":778}," email",[250,17310,1187],{"class":786},[250,17312,13496],{"class":774},[250,17314,1434],{"class":912},[250,17316,17317],{"class":782},"\"\"",[250,17319,1885],{"class":912},[250,17321,17322,17324,17327,17329,17331,17333,17335],{"class":252,"line":436},[250,17323,1181],{"class":786},[250,17325,17326],{"class":778}," password",[250,17328,1187],{"class":786},[250,17330,13496],{"class":774},[250,17332,1434],{"class":912},[250,17334,17317],{"class":782},[250,17336,1885],{"class":912},[250,17338,17339,17341,17344,17346,17348,17350,17353],{"class":252,"line":442},[250,17340,1181],{"class":786},[250,17342,17343],{"class":778}," loading",[250,17345,1187],{"class":786},[250,17347,13496],{"class":774},[250,17349,1434],{"class":912},[250,17351,17352],{"class":778},"false",[250,17354,1885],{"class":912},[250,17356,17357,17359,17362,17364,17366,17368,17370],{"class":252,"line":447},[250,17358,1181],{"class":786},[250,17360,17361],{"class":778}," error",[250,17363,1187],{"class":786},[250,17365,13496],{"class":774},[250,17367,1434],{"class":912},[250,17369,17317],{"class":782},[250,17371,1885],{"class":912},[250,17373,17374],{"class":252,"line":453},[250,17375,795],{"emptyLinePlaceholder":129},[250,17377,17378,17380,17382,17385],{"class":252,"line":459},[250,17379,1437],{"class":786},[250,17381,1845],{"class":786},[250,17383,17384],{"class":774}," handleLogin",[250,17386,1851],{"class":912},[250,17388,17389,17392,17394,17397],{"class":252,"line":465},[250,17390,17391],{"class":912},"  loading.value ",[250,17393,1416],{"class":786},[250,17395,17396],{"class":778}," true",[250,17398,1379],{"class":912},[250,17400,17401,17404,17406,17409],{"class":252,"line":471},[250,17402,17403],{"class":912},"  error.value ",[250,17405,1416],{"class":786},[250,17407,17408],{"class":782}," \"\"",[250,17410,1379],{"class":912},[250,17412,17413],{"class":252,"line":2201},[250,17414,1053],{"class":912},[250,17416,17417,17419],{"class":252,"line":2207},[250,17418,14553],{"class":786},[250,17420,1118],{"class":912},[250,17422,17423,17425,17428,17430,17433],{"class":252,"line":2213},[250,17424,5725],{"class":786},[250,17426,17427],{"class":774}," $fetch",[250,17429,1434],{"class":912},[250,17431,17432],{"class":782},"\"\u002Fapi\u002Fauth\u002Flogin\"",[250,17434,4454],{"class":912},[250,17436,17437,17440,17443],{"class":252,"line":2218},[250,17438,17439],{"class":912},"      method: ",[250,17441,17442],{"class":782},"\"POST\"",[250,17444,927],{"class":912},[250,17446,17447],{"class":252,"line":2223},[250,17448,17449],{"class":912},"      body: { email: email.value, password: password.value },\n",[250,17451,17452],{"class":252,"line":2239},[250,17453,1547],{"class":912},[250,17455,17456],{"class":252,"line":2244},[250,17457,6458],{"class":912},[250,17459,17460,17463,17465,17468],{"class":252,"line":2267},[250,17461,17462],{"class":774},"    navigateTo",[250,17464,1434],{"class":912},[250,17466,17467],{"class":782},"\"\u002Fdashboard\"",[250,17469,1885],{"class":912},[250,17471,17472,17474,17476,17478,17481,17483,17485],{"class":252,"line":2301},[250,17473,14609],{"class":912},[250,17475,2164],{"class":786},[250,17477,1440],{"class":912},[250,17479,17480],{"class":1370},"e",[250,17482,1007],{"class":786},[250,17484,1410],{"class":778},[250,17486,1512],{"class":912},[250,17488,17489,17492,17494,17497,17499,17502],{"class":252,"line":2306},[250,17490,17491],{"class":912},"    error.value ",[250,17493,1416],{"class":786},[250,17495,17496],{"class":912}," e.data?.statusMessage ",[250,17498,1497],{"class":786},[250,17500,17501],{"class":782}," \"Login failed\"",[250,17503,1379],{"class":912},[250,17505,17506,17508,17511],{"class":252,"line":2320},[250,17507,14609],{"class":912},[250,17509,17510],{"class":786},"finally",[250,17512,1118],{"class":912},[250,17514,17515,17518,17520,17523],{"class":252,"line":2340},[250,17516,17517],{"class":912},"    loading.value ",[250,17519,1416],{"class":786},[250,17521,17522],{"class":778}," false",[250,17524,1379],{"class":912},[250,17526,17527],{"class":252,"line":2360},[250,17528,986],{"class":912},[250,17530,17531],{"class":252,"line":2397},[250,17532,991],{"class":912},[250,17534,17535],{"class":252,"line":2402},[250,17536,795],{"emptyLinePlaceholder":129},[250,17538,17539,17541,17543,17546],{"class":252,"line":2407},[250,17540,1437],{"class":786},[250,17542,1845],{"class":786},[250,17544,17545],{"class":774}," loginWithGithub",[250,17547,1851],{"class":912},[250,17549,17550,17552,17555,17557,17560,17563,17565],{"class":252,"line":6667},[250,17551,1565],{"class":786},[250,17553,17554],{"class":774}," navigateTo",[250,17556,1434],{"class":912},[250,17558,17559],{"class":782},"\"\u002Fapi\u002Fauth\u002Fsignin\u002Fgithub\"",[250,17561,17562],{"class":912},", { external: ",[250,17564,1066],{"class":778},[250,17566,17567],{"class":912}," });\n",[250,17569,17570],{"class":252,"line":6672},[250,17571,991],{"class":912},[250,17573,17574,17576,17578],{"class":252,"line":6688},[250,17575,13209],{"class":912},[250,17577,13212],{"class":16935},[250,17579,13111],{"class":912},[20,17581,1092,17582,1007],{},[39,17583,17584],{},"pages\u002Fregister.vue",[47,17586,17588],{"className":16925,"code":17587,"filename":17584,"language":13747,"meta":55,"style":55},"\u003Ctemplate>\n  \u003Cdiv class=\"auth-page\">\n    \u003Ch1>Create an Account\u003C\u002Fh1>\n    \n    \u003Cform @submit.prevent=\"handleRegister\">\n      \u003Cdiv class=\"form-group\">\n        \u003Clabel>Name\u003C\u002Flabel>\n        \u003Cinput v-model=\"name\" type=\"text\" required \u002F>\n      \u003C\u002Fdiv>\n      \n      \u003Cdiv class=\"form-group\">\n        \u003Clabel>Email\u003C\u002Flabel>\n        \u003Cinput v-model=\"email\" type=\"email\" required \u002F>\n      \u003C\u002Fdiv>\n      \n      \u003Cdiv class=\"form-group\">\n        \u003Clabel>Password\u003C\u002Flabel>\n        \u003Cinput v-model=\"password\" type=\"password\" required \u002F>\n      \u003C\u002Fdiv>\n      \n      \u003Cbutton type=\"submit\" :disabled=\"loading\">\n        {{ loading ? \"Creating account...\" : \"Register\" }}\n      \u003C\u002Fbutton>\n      \n      \u003Cp v-if=\"error\" class=\"error\">{{ error }}\u003C\u002Fp>\n    \u003C\u002Fform>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst name = ref(\"\");\nconst email = ref(\"\");\nconst password = ref(\"\");\nconst loading = ref(false);\nconst error = ref(\"\");\n\nasync function handleRegister() {\n  loading.value = true;\n  error.value = \"\";\n  \n  try {\n    await $fetch(\"\u002Fapi\u002Fauth\u002Fregister\", {\n      method: \"POST\",\n      body: { name: name.value, email: email.value, password: password.value },\n    });\n    \n    navigateTo(\"\u002Fdashboard\");\n  } catch (e: any) {\n    error.value = e.data?.statusMessage || \"Registration failed\";\n  } finally {\n    loading.value = false;\n  }\n}\n\u003C\u002Fscript>\n",[39,17589,17590,17598,17612,17625,17629,17644,17658,17671,17694,17702,17706,17720,17732,17754,17762,17766,17780,17792,17814,17822,17826,17846,17851,17859,17863,17887,17895,17903,17911,17915,17931,17948,17964,17980,17996,18012,18016,18027,18037,18047,18051,18057,18070,18078,18083,18087,18091,18101,18117,18132,18140,18150,18154,18158],{"__ignoreMap":55},[250,17591,17592,17594,17596],{"class":252,"line":253},[250,17593,1962],{"class":912},[250,17595,16936],{"class":16935},[250,17597,13111],{"class":912},[250,17599,17600,17602,17604,17606,17608,17610],{"class":252,"line":113},[250,17601,16943],{"class":912},[250,17603,16946],{"class":16935},[250,17605,16949],{"class":774},[250,17607,1416],{"class":912},[250,17609,16954],{"class":782},[250,17611,13111],{"class":912},[250,17613,17614,17616,17618,17621,17623],{"class":252,"line":110},[250,17615,16961],{"class":912},[250,17617,15],{"class":16935},[250,17619,17620],{"class":912},">Create an Account\u003C\u002F",[250,17622,15],{"class":16935},[250,17624,13111],{"class":912},[250,17626,17627],{"class":252,"line":269},[250,17628,6458],{"class":912},[250,17630,17631,17633,17635,17637,17639,17642],{"class":252,"line":275},[250,17632,16961],{"class":912},[250,17634,16981],{"class":16935},[250,17636,16984],{"class":774},[250,17638,1416],{"class":912},[250,17640,17641],{"class":782},"\"handleRegister\"",[250,17643,13111],{"class":912},[250,17645,17646,17648,17650,17652,17654,17656],{"class":252,"line":281},[250,17647,16996],{"class":912},[250,17649,16946],{"class":16935},[250,17651,16949],{"class":774},[250,17653,1416],{"class":912},[250,17655,17005],{"class":782},[250,17657,13111],{"class":912},[250,17659,17660,17662,17664,17667,17669],{"class":252,"line":287},[250,17661,17012],{"class":912},[250,17663,17015],{"class":16935},[250,17665,17666],{"class":912},">Name\u003C\u002F",[250,17668,17015],{"class":16935},[250,17670,13111],{"class":912},[250,17672,17673,17675,17677,17679,17681,17683,17685,17687,17690,17692],{"class":252,"line":293},[250,17674,17012],{"class":912},[250,17676,14775],{"class":16935},[250,17678,17031],{"class":774},[250,17680,1416],{"class":912},[250,17682,4485],{"class":782},[250,17684,4974],{"class":774},[250,17686,1416],{"class":912},[250,17688,17689],{"class":782},"\"text\"",[250,17691,17044],{"class":774},[250,17693,17047],{"class":912},[250,17695,17696,17698,17700],{"class":252,"line":299},[250,17697,17052],{"class":912},[250,17699,16946],{"class":16935},[250,17701,13111],{"class":912},[250,17703,17704],{"class":252,"line":132},[250,17705,17061],{"class":912},[250,17707,17708,17710,17712,17714,17716,17718],{"class":252,"line":310},[250,17709,16996],{"class":912},[250,17711,16946],{"class":16935},[250,17713,16949],{"class":774},[250,17715,1416],{"class":912},[250,17717,17005],{"class":782},[250,17719,13111],{"class":912},[250,17721,17722,17724,17726,17728,17730],{"class":252,"line":316},[250,17723,17012],{"class":912},[250,17725,17015],{"class":16935},[250,17727,17018],{"class":912},[250,17729,17015],{"class":16935},[250,17731,13111],{"class":912},[250,17733,17734,17736,17738,17740,17742,17744,17746,17748,17750,17752],{"class":252,"line":322},[250,17735,17012],{"class":912},[250,17737,14775],{"class":16935},[250,17739,17031],{"class":774},[250,17741,1416],{"class":912},[250,17743,15116],{"class":782},[250,17745,4974],{"class":774},[250,17747,1416],{"class":912},[250,17749,15116],{"class":782},[250,17751,17044],{"class":774},[250,17753,17047],{"class":912},[250,17755,17756,17758,17760],{"class":252,"line":328},[250,17757,17052],{"class":912},[250,17759,16946],{"class":16935},[250,17761,13111],{"class":912},[250,17763,17764],{"class":252,"line":334},[250,17765,17061],{"class":912},[250,17767,17768,17770,17772,17774,17776,17778],{"class":252,"line":340},[250,17769,16996],{"class":912},[250,17771,16946],{"class":16935},[250,17773,16949],{"class":774},[250,17775,1416],{"class":912},[250,17777,17005],{"class":782},[250,17779,13111],{"class":912},[250,17781,17782,17784,17786,17788,17790],{"class":252,"line":346},[250,17783,17012],{"class":912},[250,17785,17015],{"class":16935},[250,17787,17084],{"class":912},[250,17789,17015],{"class":16935},[250,17791,13111],{"class":912},[250,17793,17794,17796,17798,17800,17802,17804,17806,17808,17810,17812],{"class":252,"line":352},[250,17795,17012],{"class":912},[250,17797,14775],{"class":16935},[250,17799,17031],{"class":774},[250,17801,1416],{"class":912},[250,17803,15139],{"class":782},[250,17805,4974],{"class":774},[250,17807,1416],{"class":912},[250,17809,15139],{"class":782},[250,17811,17044],{"class":774},[250,17813,17047],{"class":912},[250,17815,17816,17818,17820],{"class":252,"line":358},[250,17817,17052],{"class":912},[250,17819,16946],{"class":16935},[250,17821,13111],{"class":912},[250,17823,17824],{"class":252,"line":364},[250,17825,17061],{"class":912},[250,17827,17828,17830,17832,17834,17836,17838,17840,17842,17844],{"class":252,"line":370},[250,17829,16996],{"class":912},[250,17831,17129],{"class":16935},[250,17833,4974],{"class":774},[250,17835,1416],{"class":912},[250,17837,17136],{"class":782},[250,17839,17139],{"class":774},[250,17841,1416],{"class":912},[250,17843,17144],{"class":782},[250,17845,13111],{"class":912},[250,17847,17848],{"class":252,"line":376},[250,17849,17850],{"class":912},"        {{ loading ? \"Creating account...\" : \"Register\" }}\n",[250,17852,17853,17855,17857],{"class":252,"line":382},[250,17854,17052],{"class":912},[250,17856,17129],{"class":16935},[250,17858,13111],{"class":912},[250,17860,17861],{"class":252,"line":388},[250,17862,17061],{"class":912},[250,17864,17865,17867,17869,17871,17873,17875,17877,17879,17881,17883,17885],{"class":252,"line":393},[250,17866,16996],{"class":912},[250,17868,20],{"class":16935},[250,17870,17172],{"class":774},[250,17872,1416],{"class":912},[250,17874,12292],{"class":782},[250,17876,16949],{"class":774},[250,17878,1416],{"class":912},[250,17880,12292],{"class":782},[250,17882,17185],{"class":912},[250,17884,20],{"class":16935},[250,17886,13111],{"class":912},[250,17888,17889,17891,17893],{"class":252,"line":399},[250,17890,17194],{"class":912},[250,17892,16981],{"class":16935},[250,17894,13111],{"class":912},[250,17896,17897,17899,17901],{"class":252,"line":405},[250,17898,17267],{"class":912},[250,17900,16946],{"class":16935},[250,17902,13111],{"class":912},[250,17904,17905,17907,17909],{"class":252,"line":410},[250,17906,13209],{"class":912},[250,17908,16936],{"class":16935},[250,17910,13111],{"class":912},[250,17912,17913],{"class":252,"line":415},[250,17914,795],{"emptyLinePlaceholder":129},[250,17916,17917,17919,17921,17923,17925,17927,17929],{"class":252,"line":420},[250,17918,1962],{"class":912},[250,17920,13212],{"class":16935},[250,17922,17292],{"class":774},[250,17924,17295],{"class":774},[250,17926,1416],{"class":912},[250,17928,13108],{"class":782},[250,17930,13111],{"class":912},[250,17932,17933,17935,17938,17940,17942,17944,17946],{"class":252,"line":426},[250,17934,1181],{"class":786},[250,17936,17937],{"class":778}," name",[250,17939,1187],{"class":786},[250,17941,13496],{"class":774},[250,17943,1434],{"class":912},[250,17945,17317],{"class":782},[250,17947,1885],{"class":912},[250,17949,17950,17952,17954,17956,17958,17960,17962],{"class":252,"line":431},[250,17951,1181],{"class":786},[250,17953,17308],{"class":778},[250,17955,1187],{"class":786},[250,17957,13496],{"class":774},[250,17959,1434],{"class":912},[250,17961,17317],{"class":782},[250,17963,1885],{"class":912},[250,17965,17966,17968,17970,17972,17974,17976,17978],{"class":252,"line":436},[250,17967,1181],{"class":786},[250,17969,17326],{"class":778},[250,17971,1187],{"class":786},[250,17973,13496],{"class":774},[250,17975,1434],{"class":912},[250,17977,17317],{"class":782},[250,17979,1885],{"class":912},[250,17981,17982,17984,17986,17988,17990,17992,17994],{"class":252,"line":442},[250,17983,1181],{"class":786},[250,17985,17343],{"class":778},[250,17987,1187],{"class":786},[250,17989,13496],{"class":774},[250,17991,1434],{"class":912},[250,17993,17352],{"class":778},[250,17995,1885],{"class":912},[250,17997,17998,18000,18002,18004,18006,18008,18010],{"class":252,"line":447},[250,17999,1181],{"class":786},[250,18001,17361],{"class":778},[250,18003,1187],{"class":786},[250,18005,13496],{"class":774},[250,18007,1434],{"class":912},[250,18009,17317],{"class":782},[250,18011,1885],{"class":912},[250,18013,18014],{"class":252,"line":453},[250,18015,795],{"emptyLinePlaceholder":129},[250,18017,18018,18020,18022,18025],{"class":252,"line":459},[250,18019,1437],{"class":786},[250,18021,1845],{"class":786},[250,18023,18024],{"class":774}," handleRegister",[250,18026,1851],{"class":912},[250,18028,18029,18031,18033,18035],{"class":252,"line":465},[250,18030,17391],{"class":912},[250,18032,1416],{"class":786},[250,18034,17396],{"class":778},[250,18036,1379],{"class":912},[250,18038,18039,18041,18043,18045],{"class":252,"line":471},[250,18040,17403],{"class":912},[250,18042,1416],{"class":786},[250,18044,17408],{"class":782},[250,18046,1379],{"class":912},[250,18048,18049],{"class":252,"line":2201},[250,18050,1053],{"class":912},[250,18052,18053,18055],{"class":252,"line":2207},[250,18054,14553],{"class":786},[250,18056,1118],{"class":912},[250,18058,18059,18061,18063,18065,18068],{"class":252,"line":2213},[250,18060,5725],{"class":786},[250,18062,17427],{"class":774},[250,18064,1434],{"class":912},[250,18066,18067],{"class":782},"\"\u002Fapi\u002Fauth\u002Fregister\"",[250,18069,4454],{"class":912},[250,18071,18072,18074,18076],{"class":252,"line":2218},[250,18073,17439],{"class":912},[250,18075,17442],{"class":782},[250,18077,927],{"class":912},[250,18079,18080],{"class":252,"line":2223},[250,18081,18082],{"class":912},"      body: { name: name.value, email: email.value, password: password.value },\n",[250,18084,18085],{"class":252,"line":2239},[250,18086,1547],{"class":912},[250,18088,18089],{"class":252,"line":2244},[250,18090,6458],{"class":912},[250,18092,18093,18095,18097,18099],{"class":252,"line":2267},[250,18094,17462],{"class":774},[250,18096,1434],{"class":912},[250,18098,17467],{"class":782},[250,18100,1885],{"class":912},[250,18102,18103,18105,18107,18109,18111,18113,18115],{"class":252,"line":2301},[250,18104,14609],{"class":912},[250,18106,2164],{"class":786},[250,18108,1440],{"class":912},[250,18110,17480],{"class":1370},[250,18112,1007],{"class":786},[250,18114,1410],{"class":778},[250,18116,1512],{"class":912},[250,18118,18119,18121,18123,18125,18127,18130],{"class":252,"line":2306},[250,18120,17491],{"class":912},[250,18122,1416],{"class":786},[250,18124,17496],{"class":912},[250,18126,1497],{"class":786},[250,18128,18129],{"class":782}," \"Registration failed\"",[250,18131,1379],{"class":912},[250,18133,18134,18136,18138],{"class":252,"line":2320},[250,18135,14609],{"class":912},[250,18137,17510],{"class":786},[250,18139,1118],{"class":912},[250,18141,18142,18144,18146,18148],{"class":252,"line":2340},[250,18143,17517],{"class":912},[250,18145,1416],{"class":786},[250,18147,17522],{"class":778},[250,18149,1379],{"class":912},[250,18151,18152],{"class":252,"line":2360},[250,18153,986],{"class":912},[250,18155,18156],{"class":252,"line":2397},[250,18157,991],{"class":912},[250,18159,18160,18162,18164],{"class":252,"line":2402},[250,18161,13209],{"class":912},[250,18163,13212],{"class":16935},[250,18165,13111],{"class":912},[72,18167],{},[31,18169,18171],{"id":18170},"step-9-use-auth-composable","Step 9: Use Auth Composable",[20,18173,18174],{},"Nuxt provides a composable for easy auth state management.",[47,18176,18179],{"className":1010,"code":18177,"filename":18178,"language":1012,"meta":55,"style":55},"export const useAuth = () => {\n  const user = useState(\"auth-user\", () => null);\n  const loading = useState(\"auth-loading\", () => true);\n  \n  const fetchUser = async () => {\n    loading.value = true;\n    try {\n      user.value = await $fetch(\"\u002Fapi\u002Fauth\u002Fme\");\n    } catch {\n      user.value = null;\n    } finally {\n      loading.value = false;\n    }\n  };\n  \n  const logout = async () => {\n    await $fetch(\"\u002Fapi\u002Fauth\u002Flogout\", { method: \"POST\" });\n    user.value = null;\n    navigateTo(\"\u002Flogin\");\n  };\n  \n  return { user, loading, fetchUser, logout };\n};\n","composables\u002FuseAuth.ts",[39,18180,18181,18198,18222,18245,18249,18266,18276,18283,18301,18310,18320,18328,18339,18343,18347,18351,18368,18386,18397,18408,18412,18416,18423],{"__ignoreMap":55},[250,18182,18183,18185,18187,18190,18192,18194,18196],{"class":252,"line":253},[250,18184,1019],{"class":786},[250,18186,4438],{"class":786},[250,18188,18189],{"class":774}," useAuth",[250,18191,1187],{"class":786},[250,18193,2015],{"class":912},[250,18195,1115],{"class":786},[250,18197,1118],{"class":912},[250,18199,18200,18202,18204,18206,18209,18211,18214,18216,18218,18220],{"class":252,"line":113},[250,18201,1455],{"class":786},[250,18203,14943],{"class":778},[250,18205,1187],{"class":786},[250,18207,18208],{"class":774}," useState",[250,18210,1434],{"class":912},[250,18212,18213],{"class":782},"\"auth-user\"",[250,18215,13157],{"class":912},[250,18217,1115],{"class":786},[250,18219,14546],{"class":778},[250,18221,1885],{"class":912},[250,18223,18224,18226,18228,18230,18232,18234,18237,18239,18241,18243],{"class":252,"line":110},[250,18225,1455],{"class":786},[250,18227,17343],{"class":778},[250,18229,1187],{"class":786},[250,18231,18208],{"class":774},[250,18233,1434],{"class":912},[250,18235,18236],{"class":782},"\"auth-loading\"",[250,18238,13157],{"class":912},[250,18240,1115],{"class":786},[250,18242,17396],{"class":778},[250,18244,1885],{"class":912},[250,18246,18247],{"class":252,"line":269},[250,18248,1053],{"class":912},[250,18250,18251,18253,18256,18258,18260,18262,18264],{"class":252,"line":275},[250,18252,1455],{"class":786},[250,18254,18255],{"class":774}," fetchUser",[250,18257,1187],{"class":786},[250,18259,2012],{"class":786},[250,18261,2015],{"class":912},[250,18263,1115],{"class":786},[250,18265,1118],{"class":912},[250,18267,18268,18270,18272,18274],{"class":252,"line":281},[250,18269,17517],{"class":912},[250,18271,1416],{"class":786},[250,18273,17396],{"class":778},[250,18275,1379],{"class":912},[250,18277,18278,18281],{"class":252,"line":287},[250,18279,18280],{"class":786},"    try",[250,18282,1118],{"class":912},[250,18284,18285,18288,18290,18292,18294,18296,18299],{"class":252,"line":293},[250,18286,18287],{"class":912},"      user.value ",[250,18289,1416],{"class":786},[250,18291,1463],{"class":786},[250,18293,17427],{"class":774},[250,18295,1434],{"class":912},[250,18297,18298],{"class":782},"\"\u002Fapi\u002Fauth\u002Fme\"",[250,18300,1885],{"class":912},[250,18302,18303,18306,18308],{"class":252,"line":299},[250,18304,18305],{"class":912},"    } ",[250,18307,2164],{"class":786},[250,18309,1118],{"class":912},[250,18311,18312,18314,18316,18318],{"class":252,"line":132},[250,18313,18287],{"class":912},[250,18315,1416],{"class":786},[250,18317,14546],{"class":778},[250,18319,1379],{"class":912},[250,18321,18322,18324,18326],{"class":252,"line":310},[250,18323,18305],{"class":912},[250,18325,17510],{"class":786},[250,18327,1118],{"class":912},[250,18329,18330,18333,18335,18337],{"class":252,"line":316},[250,18331,18332],{"class":912},"      loading.value ",[250,18334,1416],{"class":786},[250,18336,17522],{"class":778},[250,18338,1379],{"class":912},[250,18340,18341],{"class":252,"line":322},[250,18342,3684],{"class":912},[250,18344,18345],{"class":252,"line":328},[250,18346,1161],{"class":912},[250,18348,18349],{"class":252,"line":334},[250,18350,1053],{"class":912},[250,18352,18353,18355,18358,18360,18362,18364,18366],{"class":252,"line":340},[250,18354,1455],{"class":786},[250,18356,18357],{"class":774}," logout",[250,18359,1187],{"class":786},[250,18361,2012],{"class":786},[250,18363,2015],{"class":912},[250,18365,1115],{"class":786},[250,18367,1118],{"class":912},[250,18369,18370,18372,18374,18376,18379,18382,18384],{"class":252,"line":346},[250,18371,5725],{"class":786},[250,18373,17427],{"class":774},[250,18375,1434],{"class":912},[250,18377,18378],{"class":782},"\"\u002Fapi\u002Fauth\u002Flogout\"",[250,18380,18381],{"class":912},", { method: ",[250,18383,17442],{"class":782},[250,18385,17567],{"class":912},[250,18387,18388,18391,18393,18395],{"class":252,"line":352},[250,18389,18390],{"class":912},"    user.value ",[250,18392,1416],{"class":786},[250,18394,14546],{"class":778},[250,18396,1379],{"class":912},[250,18398,18399,18401,18403,18406],{"class":252,"line":358},[250,18400,17462],{"class":774},[250,18402,1434],{"class":912},[250,18404,18405],{"class":782},"\"\u002Flogin\"",[250,18407,1885],{"class":912},[250,18409,18410],{"class":252,"line":364},[250,18411,1161],{"class":912},[250,18413,18414],{"class":252,"line":370},[250,18415,1053],{"class":912},[250,18417,18418,18420],{"class":252,"line":376},[250,18419,1123],{"class":786},[250,18421,18422],{"class":912}," { user, loading, fetchUser, logout };\n",[250,18424,18425],{"class":252,"line":382},[250,18426,10945],{"class":912},[72,18428],{},[31,18430,18432],{"id":18431},"security-checklist","Security Checklist",[20,18434,18435],{},"Before going to production, verify:",[24,18437,18438],{"type":26},[561,18439,18442,18450,18456,18462,18468,18474,18480],{"className":18440},[18441],"contains-task-list",[564,18443,18446,18449],{"className":18444},[18445],"task-list-item",[14775,18447],{"disabled":129,"type":18448},"checkbox"," HTTPS enabled",[564,18451,18453,18455],{"className":18452},[18445],[14775,18454],{"disabled":129,"type":18448}," AUTH_SECRET is set and secure",[564,18457,18459,18461],{"className":18458},[18445],[14775,18460],{"disabled":129,"type":18448}," Passwords are hashed with Argon2 or bcrypt",[564,18463,18465,18467],{"className":18464},[18445],[14775,18466],{"disabled":129,"type":18448}," Cookie has httpOnly, secure, and sameSite flags",[564,18469,18471,18473],{"className":18470},[18445],[14775,18472],{"disabled":129,"type":18448}," Rate limiting on login\u002Fregister endpoints",[564,18475,18477,18479],{"className":18476},[18445],[14775,18478],{"disabled":129,"type":18448}," Email validation implemented",[564,18481,18483,18485],{"className":18482},[18445],[14775,18484],{"disabled":129,"type":18448}," Password strength requirements enforced",[72,18487],{},[31,18489,18491],{"id":18490},"api-routes-summary","API Routes Summary",[645,18493,18494,18504],{},[648,18495,18496],{},[651,18497,18498,18500,18502],{},[654,18499,8060],{},[654,18501,3289],{},[654,18503,3292],{},[666,18505,18506,18518,18530,18542,18554],{},[651,18507,18508,18510,18515],{},[671,18509,8096],{},[671,18511,18512],{},[39,18513,18514],{},"\u002Fapi\u002Fauth\u002Fregister",[671,18516,18517],{},"Create new account",[651,18519,18520,18522,18527],{},[671,18521,8096],{},[671,18523,18524],{},[39,18525,18526],{},"\u002Fapi\u002Fauth\u002Flogin",[671,18528,18529],{},"Authenticate user",[651,18531,18532,18534,18539],{},[671,18533,8096],{},[671,18535,18536],{},[39,18537,18538],{},"\u002Fapi\u002Fauth\u002Flogout",[671,18540,18541],{},"Clear session",[651,18543,18544,18546,18551],{},[671,18545,8071],{},[671,18547,18548],{},[39,18549,18550],{},"\u002Fapi\u002Fauth\u002Fme",[671,18552,18553],{},"Get current user",[651,18555,18556,18558,18563],{},[671,18557,8071],{},[671,18559,18560],{},[39,18561,18562],{},"\u002Fapi\u002Fauth\u002F[...]",[671,18564,18565],{},"OAuth handlers",[72,18567],{},[15,18569,3352],{"id":3351},[20,18571,18572],{},"Authentication is complex, but with Nuxt 4 and the right tools, you can build a secure system without reinventing the wheel. We've covered:",[561,18574,18575,18581,18587,18593,18599],{},[564,18576,18577,18580],{},[546,18578,18579],{},"Credentials-based auth"," with secure password hashing",[564,18582,18583,18586],{},[546,18584,18585],{},"JWT tokens"," stored in httpOnly cookies",[564,18588,18589,18592],{},[546,18590,18591],{},"OAuth integration"," with GitHub",[564,18594,18595,18598],{},[546,18596,18597],{},"Protected API routes"," for authenticated endpoints",[564,18600,18601,18604],{},[546,18602,18603],{},"Frontend auth pages"," with proper error handling",[20,18606,18607],{},"The key takeaways:",[2922,18609,18610,18616,18622,18628],{},[564,18611,18612,18615],{},[546,18613,18614],{},"Never store plain-text passwords"," — use Argon2 or bcrypt",[564,18617,18618,18621],{},[546,18619,18620],{},"Use httpOnly cookies"," for token storage",[564,18623,18624,18627],{},[546,18625,18626],{},"Validate everything"," on both client and server",[564,18629,18630,18633],{},[546,18631,18632],{},"Use established libraries"," rather than rolling your own",[20,18635,18636],{},"In production, consider adding:",[561,18638,18639,18642,18645,18648],{},[564,18640,18641],{},"Rate limiting on auth endpoints",[564,18643,18644],{},"Email verification flow",[564,18646,18647],{},"Password reset functionality",[564,18649,18650],{},"Two-factor authentication",[20,18652,18653],{},"Now go forth and secure your applications! 🔐",[500,18655,18656],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":55,"searchDepth":110,"depth":110,"links":18658},[18659,18660,18661,18662,18663,18664,18670,18671,18672,18673,18674,18675],{"id":13800,"depth":113,"text":13801},{"id":4181,"depth":113,"text":4182},{"id":13966,"depth":113,"text":13967},{"id":14145,"depth":113,"text":14146},{"id":14640,"depth":113,"text":14641},{"id":15210,"depth":113,"text":15211,"children":18665},[18666,18667,18668,18669],{"id":15214,"depth":110,"text":15215},{"id":15595,"depth":110,"text":15596},{"id":15900,"depth":110,"text":15901},{"id":15961,"depth":110,"text":15962},{"id":16261,"depth":113,"text":16262},{"id":16634,"depth":113,"text":16635},{"id":16916,"depth":113,"text":16917},{"id":18170,"depth":113,"text":18171},{"id":18431,"depth":113,"text":18432},{"id":18490,"depth":113,"text":18491},"A comprehensive guide to implementing authentication in Nuxt 4. Learn about session management, JWT, OAuth, and securing your API routes with type-safe authentication.",{"type":12,"value":18678},[18679,18681,18683,18687,18703],[15,18680,541],{"id":540},[20,18682,13764],{},[20,18684,13767,18685,1007],{},[546,18686,13008],{},[561,18688,18689,18691,18693,18695,18697,18699,18701],{},[564,18690,13774],{},[564,18692,13777],{},[564,18694,13780],{},[564,18696,13783],{},[564,18698,13786],{},[564,18700,13789],{},[564,18702,13792],{},[20,18704,13795],{},[18706,8179,18707,18708,18709,18710,18711],"nuxt","auth","jwt","session","security","nuxt auth",{},"\u002Fblog\u002Fnuxt-auth-guide",{"title":13756,"description":18676},"blog\u002Fnuxt-auth-guide","rLYDq6kP6Vru4AFumujpbdQ0qG6tTIuebNlppQZilns",{"id":18718,"title":18719,"author":18720,"body":18721,"canonical":115,"categories":115,"date":20020,"description":20021,"excerpt":20022,"extension":118,"img":20050,"keywords":20051,"language":3510,"meta":20056,"navigation":129,"ogImage":115,"path":20057,"rating":275,"readTime":334,"seo":20058,"stem":20059,"tag":11602,"__hash__":20060},"blog\u002Fblog\u002Fnuxt-layer.md","Mastering Nuxt Layers: A Complete Guide to Scalable Nuxt 3 Architecture",{"name":8,"img":10,"website":535},{"type":12,"value":18722,"toc":19992},[18723,18727,18729,18740,18743,18754,18757,18764,18766,18770,18780,18783,18794,18797,18820,18826,18828,18832,18839,18843,18860,18866,18868,18872,18878,18889,18895,18897,18901,18905,18933,18936,18971,18974,18976,18980,19023,19026,19179,19181,19185,19189,19217,19220,19254,19257,19300,19302,19306,19313,19361,19364,19366,19370,19373,19382,19385,19388,19397,19400,19402,19406,19409,19475,19478,19480,19484,19487,19590,19593,19595,19599,19602,19645,19648,19650,19654,19657,19677,19680,19685,19687,19691,19741,19744,19746,19750,19753,19778,19821,19824,19826,19830,19833,19843,19849,19851,19855,19869,19876,19878,19882,19938,19941,19943,19947,19952,19963,19968,19976,19978,19980,19983,19986,19989],[15,18724,18726],{"id":18725},"mastering-nuxt-layers","Mastering Nuxt Layers",[31,18728,541],{"id":540},[20,18730,18731,18732,18735,18736,18739],{},"Nuxt 3 introduced many powerful features, but ",[546,18733,18734],{},"Nuxt Layers"," stand out as one of the most transformative. Layers allow you to build applications by ",[546,18737,18738],{},"composing reusable Nuxt projects",", instead of maintaining large monolithic codebases or copying boilerplate across repositories.",[20,18741,18742],{},"If you’ve ever wanted to:",[561,18744,18745,18748,18751],{},[564,18746,18747],{},"Reuse layouts, components, and pages across projects",[564,18749,18750],{},"Build a scalable SaaS architecture",[564,18752,18753],{},"Maintain a shared design system or feature set",[20,18755,18756],{},"Then Nuxt Layers are exactly what you’re looking for.",[20,18758,18759,18760,18763],{},"This guide is written as a ",[546,18761,18762],{},"long-form tutorial",". You can follow along step by step and apply everything directly to real projects.",[72,18765],{},[31,18767,18769],{"id":18768},"what-are-nuxt-layers","What Are Nuxt Layers?",[20,18771,13238,18772,18775,18776,18779],{},[546,18773,18774],{},"Nuxt Layer"," is a Nuxt application that is designed to be ",[546,18777,18778],{},"extended",", not deployed on its own.",[20,18781,18782],{},"In simple terms:",[561,18784,18785,18788,18791],{},[564,18786,18787],{},"A layer looks like a normal Nuxt app",[564,18789,18790],{},"Another Nuxt app can extend it",[564,18792,18793],{},"Nuxt merges everything together at runtime",[20,18795,18796],{},"Layers can contain:",[561,18798,18799,18802,18805,18808,18811,18814,18817],{},[564,18800,18801],{},"Pages",[564,18803,18804],{},"Components",[564,18806,18807],{},"Layouts",[564,18809,18810],{},"Composables",[564,18812,18813],{},"Assets",[564,18815,18816],{},"Configuration",[564,18818,18819],{},"Dependencies",[18821,18822,18823],"blockquote",{},[20,18824,18825],{},"Think of layers as inheritance for Nuxt applications.",[72,18827],{},[31,18829,18831],{"id":18830},"why-nuxt-layers-matter","Why Nuxt Layers Matter",[20,18833,18834,18835,18838],{},"Before layers, reuse often meant duplication. Layers introduce a ",[546,18836,18837],{},"first-class architectural pattern"," for sharing functionality.",[2459,18840,18842],{"id":18841},"benefits-of-using-layers","Benefits of Using Layers",[561,18844,18845,18848,18851,18854,18857],{},[564,18846,18847],{},"Reusable features across multiple apps",[564,18849,18850],{},"Cleaner separation of concerns",[564,18852,18853],{},"Faster project setup",[564,18855,18856],{},"Easier long-term maintenance",[564,18858,18859],{},"Ideal for SaaS platforms and white-label apps",[20,18861,18862,18863,2230],{},"Layers help teams move faster ",[546,18864,18865],{},"without sacrificing structure",[72,18867],{},[31,18869,18871],{"id":18870},"how-nuxt-layers-work","How Nuxt Layers Work",[20,18873,18874,18875,1007],{},"Nuxt merges layers ",[546,18876,18877],{},"from bottom to top",[2922,18879,18880,18883,18886],{},[564,18881,18882],{},"Base layers (design system, shared config)",[564,18884,18885],{},"Feature layers (auth, billing, dashboards)",[564,18887,18888],{},"Final application (branding, custom logic)",[20,18890,18891,18892,2230],{},"If multiple layers define the same file, ",[546,18893,18894],{},"the closest one wins",[72,18896],{},[31,18898,18900],{"id":18899},"creating-your-first-nuxt-layer","Creating Your First Nuxt Layer",[2459,18902,18904],{"id":18903},"step-1-create-the-layer","Step 1: Create the Layer",[47,18906,18908],{"className":758,"code":18907,"language":761,"meta":55,"style":55},"npx nuxi init layers\u002Fbase-ui\ncd layers\u002Fbase-ui\nnpm install\n",[39,18909,18910,18921,18927],{"__ignoreMap":55},[250,18911,18912,18914,18916,18918],{"class":252,"line":253},[250,18913,4200],{"class":774},[250,18915,3231],{"class":782},[250,18917,862],{"class":782},[250,18919,18920],{"class":782}," layers\u002Fbase-ui\n",[250,18922,18923,18925],{"class":252,"line":113},[250,18924,874],{"class":778},[250,18926,18920],{"class":782},[250,18928,18929,18931],{"class":252,"line":110},[250,18930,4226],{"class":774},[250,18932,896],{"class":782},[20,18934,18935],{},"This creates a standard Nuxt project structure:",[47,18937,18939],{"className":12725,"code":18938,"language":12727,"meta":55,"style":55},"layers\u002Fbase-ui\u002F\n├─ components\u002F\n├─ layouts\u002F\n├─ composables\u002F\n├─ assets\u002F\n├─ nuxt.config.ts\n",[39,18940,18941,18946,18951,18956,18961,18966],{"__ignoreMap":55},[250,18942,18943],{"class":252,"line":253},[250,18944,18945],{},"layers\u002Fbase-ui\u002F\n",[250,18947,18948],{"class":252,"line":113},[250,18949,18950],{},"├─ components\u002F\n",[250,18952,18953],{"class":252,"line":110},[250,18954,18955],{},"├─ layouts\u002F\n",[250,18957,18958],{"class":252,"line":269},[250,18959,18960],{},"├─ composables\u002F\n",[250,18962,18963],{"class":252,"line":275},[250,18964,18965],{},"├─ assets\u002F\n",[250,18967,18968],{"class":252,"line":281},[250,18969,18970],{},"├─ nuxt.config.ts\n",[20,18972,18973],{},"You will not run this project directly—it exists to be extended.",[72,18975],{},[2459,18977,18979],{"id":18978},"step-2-configure-the-layer","Step 2: Configure the Layer",[47,18981,18983],{"className":1010,"code":18982,"language":1012,"meta":55,"style":55},"\u002F\u002F layers\u002Fbase-ui\u002Fnuxt.config.ts\nexport default defineNuxtConfig({\n  components: true,\n  css: ['~\u002Fassets\u002Fmain.css']\n})\n",[39,18984,18985,18990,19000,19009,19019],{"__ignoreMap":55},[250,18986,18987],{"class":252,"line":253},[250,18988,18989],{"class":768},"\u002F\u002F layers\u002Fbase-ui\u002Fnuxt.config.ts\n",[250,18991,18992,18994,18996,18998],{"class":252,"line":113},[250,18993,1019],{"class":786},[250,18995,1022],{"class":786},[250,18997,1025],{"class":774},[250,18999,1028],{"class":912},[250,19001,19002,19005,19007],{"class":252,"line":110},[250,19003,19004],{"class":912},"  components: ",[250,19006,1066],{"class":778},[250,19008,927],{"class":912},[250,19010,19011,19014,19017],{"class":252,"line":269},[250,19012,19013],{"class":912},"  css: [",[250,19015,19016],{"class":782},"'~\u002Fassets\u002Fmain.css'",[250,19018,8695],{"class":912},[250,19020,19021],{"class":252,"line":275},[250,19022,474],{"class":912},[20,19024,19025],{},"Add a shared component:",[47,19027,19029],{"className":16925,"code":19028,"language":13747,"meta":55,"style":55},"\u003C!-- layers\u002Fbase-ui\u002Fcomponents\u002FBaseButton.vue -->\n\u003Ctemplate>\n  \u003Cbutton class=\"btn\">\n    \u003Cslot \u002F>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\n.btn {\n  padding: 0.75rem 1.25rem;\n  border-radius: 0.5rem;\n  background: black;\n  color: white;\n}\n\u003C\u002Fstyle>\n",[39,19030,19031,19036,19044,19059,19071,19079,19087,19091,19102,19109,19129,19143,19155,19167,19171],{"__ignoreMap":55},[250,19032,19033],{"class":252,"line":253},[250,19034,19035],{"class":768},"\u003C!-- layers\u002Fbase-ui\u002Fcomponents\u002FBaseButton.vue -->\n",[250,19037,19038,19040,19042],{"class":252,"line":113},[250,19039,1962],{"class":912},[250,19041,16936],{"class":16935},[250,19043,13111],{"class":912},[250,19045,19046,19048,19050,19052,19054,19057],{"class":252,"line":110},[250,19047,16943],{"class":912},[250,19049,17129],{"class":16935},[250,19051,16949],{"class":774},[250,19053,1416],{"class":912},[250,19055,19056],{"class":782},"\"btn\"",[250,19058,13111],{"class":912},[250,19060,19061,19063,19066,19069],{"class":252,"line":269},[250,19062,16961],{"class":912},[250,19064,19065],{"class":16935},"slot",[250,19067,2287],{"class":19068},"s7hpK",[250,19070,13111],{"class":912},[250,19072,19073,19075,19077],{"class":252,"line":275},[250,19074,17267],{"class":912},[250,19076,17129],{"class":16935},[250,19078,13111],{"class":912},[250,19080,19081,19083,19085],{"class":252,"line":281},[250,19082,13209],{"class":912},[250,19084,16936],{"class":16935},[250,19086,13111],{"class":912},[250,19088,19089],{"class":252,"line":287},[250,19090,795],{"emptyLinePlaceholder":129},[250,19092,19093,19095,19097,19100],{"class":252,"line":293},[250,19094,1962],{"class":912},[250,19096,500],{"class":16935},[250,19098,19099],{"class":774}," scoped",[250,19101,13111],{"class":912},[250,19103,19104,19107],{"class":252,"line":299},[250,19105,19106],{"class":774},".btn",[250,19108,1118],{"class":912},[250,19110,19111,19114,19116,19119,19122,19125,19127],{"class":252,"line":132},[250,19112,19113],{"class":778},"  padding",[250,19115,921],{"class":912},[250,19117,19118],{"class":778},"0.75",[250,19120,19121],{"class":786},"rem",[250,19123,19124],{"class":778}," 1.25",[250,19126,19121],{"class":786},[250,19128,1379],{"class":912},[250,19130,19131,19134,19136,19139,19141],{"class":252,"line":310},[250,19132,19133],{"class":778},"  border-radius",[250,19135,921],{"class":912},[250,19137,19138],{"class":778},"0.5",[250,19140,19121],{"class":786},[250,19142,1379],{"class":912},[250,19144,19145,19148,19150,19153],{"class":252,"line":316},[250,19146,19147],{"class":778},"  background",[250,19149,921],{"class":912},[250,19151,19152],{"class":778},"black",[250,19154,1379],{"class":912},[250,19156,19157,19160,19162,19165],{"class":252,"line":322},[250,19158,19159],{"class":778},"  color",[250,19161,921],{"class":912},[250,19163,19164],{"class":778},"white",[250,19166,1379],{"class":912},[250,19168,19169],{"class":252,"line":328},[250,19170,991],{"class":912},[250,19172,19173,19175,19177],{"class":252,"line":334},[250,19174,13209],{"class":912},[250,19176,500],{"class":16935},[250,19178,13111],{"class":912},[72,19180],{},[31,19182,19184],{"id":19183},"using-a-layer-in-a-nuxt-app","Using a Layer in a Nuxt App",[2459,19186,19188],{"id":19187},"step-3-create-the-app","Step 3: Create the App",[47,19190,19192],{"className":758,"code":19191,"language":761,"meta":55,"style":55},"npx nuxi init apps\u002Fweb\ncd apps\u002Fweb\nnpm install\n",[39,19193,19194,19205,19211],{"__ignoreMap":55},[250,19195,19196,19198,19200,19202],{"class":252,"line":253},[250,19197,4200],{"class":774},[250,19199,3231],{"class":782},[250,19201,862],{"class":782},[250,19203,19204],{"class":782}," apps\u002Fweb\n",[250,19206,19207,19209],{"class":252,"line":113},[250,19208,874],{"class":778},[250,19210,19204],{"class":782},[250,19212,19213,19215],{"class":252,"line":110},[250,19214,4226],{"class":774},[250,19216,896],{"class":782},[20,19218,19219],{},"Extend the layer:",[47,19221,19223],{"className":1010,"code":19222,"language":1012,"meta":55,"style":55},"\u002F\u002F apps\u002Fweb\u002Fnuxt.config.ts\nexport default defineNuxtConfig({\n  extends: ['..\u002Flayers\u002Fbase-ui']\n})\n",[39,19224,19225,19230,19240,19250],{"__ignoreMap":55},[250,19226,19227],{"class":252,"line":253},[250,19228,19229],{"class":768},"\u002F\u002F apps\u002Fweb\u002Fnuxt.config.ts\n",[250,19231,19232,19234,19236,19238],{"class":252,"line":113},[250,19233,1019],{"class":786},[250,19235,1022],{"class":786},[250,19237,1025],{"class":774},[250,19239,1028],{"class":912},[250,19241,19242,19245,19248],{"class":252,"line":110},[250,19243,19244],{"class":912},"  extends: [",[250,19246,19247],{"class":782},"'..\u002Flayers\u002Fbase-ui'",[250,19249,8695],{"class":912},[250,19251,19252],{"class":252,"line":269},[250,19253,474],{"class":912},[20,19255,19256],{},"Now you can use the shared component without importing it:",[47,19258,19260],{"className":16925,"code":19259,"language":13747,"meta":55,"style":55},"\u003Ctemplate>\n  \u003CBaseButton>\n    Click Me\n  \u003C\u002FBaseButton>\n\u003C\u002Ftemplate>\n",[39,19261,19262,19270,19279,19284,19292],{"__ignoreMap":55},[250,19263,19264,19266,19268],{"class":252,"line":253},[250,19265,1962],{"class":912},[250,19267,16936],{"class":16935},[250,19269,13111],{"class":912},[250,19271,19272,19274,19277],{"class":252,"line":113},[250,19273,16943],{"class":912},[250,19275,19276],{"class":16935},"BaseButton",[250,19278,13111],{"class":912},[250,19280,19281],{"class":252,"line":110},[250,19282,19283],{"class":912},"    Click Me\n",[250,19285,19286,19288,19290],{"class":252,"line":269},[250,19287,17267],{"class":912},[250,19289,19276],{"class":16935},[250,19291,13111],{"class":912},[250,19293,19294,19296,19298],{"class":252,"line":275},[250,19295,13209],{"class":912},[250,19297,16936],{"class":16935},[250,19299,13111],{"class":912},[72,19301],{},[31,19303,19305],{"id":19304},"using-multiple-layers","Using Multiple Layers",[20,19307,19308,19309,19312],{},"You can extend ",[546,19310,19311],{},"multiple layers"," in a single app.",[47,19314,19316],{"className":1010,"code":19315,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  extends: [\n    '..\u002Flayers\u002Fbase-ui',\n    '..\u002Flayers\u002Fauth',\n    '..\u002Flayers\u002Fdashboard'\n  ]\n})\n",[39,19317,19318,19328,19333,19340,19347,19352,19357],{"__ignoreMap":55},[250,19319,19320,19322,19324,19326],{"class":252,"line":253},[250,19321,1019],{"class":786},[250,19323,1022],{"class":786},[250,19325,1025],{"class":774},[250,19327,1028],{"class":912},[250,19329,19330],{"class":252,"line":113},[250,19331,19332],{"class":912},"  extends: [\n",[250,19334,19335,19338],{"class":252,"line":110},[250,19336,19337],{"class":782},"    '..\u002Flayers\u002Fbase-ui'",[250,19339,927],{"class":912},[250,19341,19342,19345],{"class":252,"line":269},[250,19343,19344],{"class":782},"    '..\u002Flayers\u002Fauth'",[250,19346,927],{"class":912},[250,19348,19349],{"class":252,"line":275},[250,19350,19351],{"class":782},"    '..\u002Flayers\u002Fdashboard'\n",[250,19353,19354],{"class":252,"line":281},[250,19355,19356],{"class":912},"  ]\n",[250,19358,19359],{"class":252,"line":287},[250,19360,474],{"class":912},[20,19362,19363],{},"Later layers override earlier ones.",[72,19365],{},[31,19367,19369],{"id":19368},"pages-inside-layers","Pages Inside Layers",[20,19371,19372],{},"Layers can define pages just like an app.",[47,19374,19376],{"className":12725,"code":19375,"language":12727,"meta":55,"style":55},"layers\u002Fauth\u002Fpages\u002Flogin.vue\n",[39,19377,19378],{"__ignoreMap":55},[250,19379,19380],{"class":252,"line":253},[250,19381,19375],{},[20,19383,19384],{},"That page automatically becomes available in the app.",[20,19386,19387],{},"To override it:",[47,19389,19391],{"className":12725,"code":19390,"language":12727,"meta":55,"style":55},"apps\u002Fweb\u002Fpages\u002Flogin.vue\n",[39,19392,19393],{"__ignoreMap":55},[250,19394,19395],{"class":252,"line":253},[250,19396,19390],{},[20,19398,19399],{},"Nuxt will use the app’s version instead.",[72,19401],{},[31,19403,19405],{"id":19404},"layouts-in-layers","Layouts in Layers",[20,19407,19408],{},"Shared layouts are ideal for base UI.",[47,19410,19412],{"className":16925,"code":19411,"language":13747,"meta":55,"style":55},"\u003C!-- layers\u002Fbase-ui\u002Flayouts\u002Fdefault.vue -->\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cheader>Base Header\u003C\u002Fheader>\n    \u003Cslot \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[39,19413,19414,19419,19427,19435,19449,19459,19467],{"__ignoreMap":55},[250,19415,19416],{"class":252,"line":253},[250,19417,19418],{"class":768},"\u003C!-- layers\u002Fbase-ui\u002Flayouts\u002Fdefault.vue -->\n",[250,19420,19421,19423,19425],{"class":252,"line":113},[250,19422,1962],{"class":912},[250,19424,16936],{"class":16935},[250,19426,13111],{"class":912},[250,19428,19429,19431,19433],{"class":252,"line":110},[250,19430,16943],{"class":912},[250,19432,16946],{"class":16935},[250,19434,13111],{"class":912},[250,19436,19437,19439,19442,19445,19447],{"class":252,"line":269},[250,19438,16961],{"class":912},[250,19440,19441],{"class":16935},"header",[250,19443,19444],{"class":912},">Base Header\u003C\u002F",[250,19446,19441],{"class":16935},[250,19448,13111],{"class":912},[250,19450,19451,19453,19455,19457],{"class":252,"line":275},[250,19452,16961],{"class":912},[250,19454,19065],{"class":16935},[250,19456,2287],{"class":19068},[250,19458,13111],{"class":912},[250,19460,19461,19463,19465],{"class":252,"line":281},[250,19462,17267],{"class":912},[250,19464,16946],{"class":16935},[250,19466,13111],{"class":912},[250,19468,19469,19471,19473],{"class":252,"line":287},[250,19470,13209],{"class":912},[250,19472,16936],{"class":16935},[250,19474,13111],{"class":912},[20,19476,19477],{},"All extending apps inherit this layout automatically.",[72,19479],{},[31,19481,19483],{"id":19482},"composables-in-layers","Composables in Layers",[20,19485,19486],{},"Layers are perfect for shared logic.",[47,19488,19490],{"className":1010,"code":19489,"language":1012,"meta":55,"style":55},"\u002F\u002F layers\u002Fauth\u002Fcomposables\u002FuseAuth.ts\nexport const useAuth = () => {\n  const user = useState('user', () => null)\n\n  const login = async () => {\n    user.value = { name: 'Vantol' }\n  }\n\n  return { user, login }\n}\n",[39,19491,19492,19497,19513,19536,19540,19557,19571,19575,19579,19586],{"__ignoreMap":55},[250,19493,19494],{"class":252,"line":253},[250,19495,19496],{"class":768},"\u002F\u002F layers\u002Fauth\u002Fcomposables\u002FuseAuth.ts\n",[250,19498,19499,19501,19503,19505,19507,19509,19511],{"class":252,"line":113},[250,19500,1019],{"class":786},[250,19502,4438],{"class":786},[250,19504,18189],{"class":774},[250,19506,1187],{"class":786},[250,19508,2015],{"class":912},[250,19510,1115],{"class":786},[250,19512,1118],{"class":912},[250,19514,19515,19517,19519,19521,19523,19525,19528,19530,19532,19534],{"class":252,"line":110},[250,19516,1455],{"class":786},[250,19518,14943],{"class":778},[250,19520,1187],{"class":786},[250,19522,18208],{"class":774},[250,19524,1434],{"class":912},[250,19526,19527],{"class":782},"'user'",[250,19529,13157],{"class":912},[250,19531,1115],{"class":786},[250,19533,14546],{"class":778},[250,19535,4852],{"class":912},[250,19537,19538],{"class":252,"line":269},[250,19539,795],{"emptyLinePlaceholder":129},[250,19541,19542,19544,19547,19549,19551,19553,19555],{"class":252,"line":275},[250,19543,1455],{"class":786},[250,19545,19546],{"class":774}," login",[250,19548,1187],{"class":786},[250,19550,2012],{"class":786},[250,19552,2015],{"class":912},[250,19554,1115],{"class":786},[250,19556,1118],{"class":912},[250,19558,19559,19561,19563,19566,19569],{"class":252,"line":281},[250,19560,18390],{"class":912},[250,19562,1416],{"class":786},[250,19564,19565],{"class":912}," { name: ",[250,19567,19568],{"class":782},"'Vantol'",[250,19570,8690],{"class":912},[250,19572,19573],{"class":252,"line":287},[250,19574,986],{"class":912},[250,19576,19577],{"class":252,"line":293},[250,19578,795],{"emptyLinePlaceholder":129},[250,19580,19581,19583],{"class":252,"line":299},[250,19582,1123],{"class":786},[250,19584,19585],{"class":912}," { user, login }\n",[250,19587,19588],{"class":252,"line":132},[250,19589,991],{"class":912},[20,19591,19592],{},"This composable is globally available.",[72,19594],{},[31,19596,19598],{"id":19597},"runtime-config-and-environment-variables","Runtime Config and Environment Variables",[20,19600,19601],{},"Layers can define runtime configuration:",[47,19603,19605],{"className":1010,"code":19604,"language":1012,"meta":55,"style":55},"export default defineNuxtConfig({\n  runtimeConfig: {\n    public: {\n      appName: 'Base App'\n    }\n  }\n})\n",[39,19606,19607,19617,19621,19625,19633,19637,19641],{"__ignoreMap":55},[250,19608,19609,19611,19613,19615],{"class":252,"line":253},[250,19610,1019],{"class":786},[250,19612,1022],{"class":786},[250,19614,1025],{"class":774},[250,19616,1028],{"class":912},[250,19618,19619],{"class":252,"line":113},[250,19620,8929],{"class":912},[250,19622,19623],{"class":252,"line":110},[250,19624,8934],{"class":912},[250,19626,19627,19630],{"class":252,"line":269},[250,19628,19629],{"class":912},"      appName: ",[250,19631,19632],{"class":782},"'Base App'\n",[250,19634,19635],{"class":252,"line":275},[250,19636,3684],{"class":912},[250,19638,19639],{"class":252,"line":281},[250,19640,986],{"class":912},[250,19642,19643],{"class":252,"line":287},[250,19644,474],{"class":912},[20,19646,19647],{},"Apps can override these values safely.",[72,19649],{},[31,19651,19653],{"id":19652},"dependencies-in-layers","Dependencies in Layers",[20,19655,19656],{},"Layers may include their own dependencies:",[47,19658,19660],{"className":758,"code":19659,"language":761,"meta":55,"style":55},"cd layers\u002Fbase-ui\nnpm install tailwindcss\n",[39,19661,19662,19668],{"__ignoreMap":55},[250,19663,19664,19666],{"class":252,"line":253},[250,19665,874],{"class":778},[250,19667,18920],{"class":782},[250,19669,19670,19672,19674],{"class":252,"line":113},[250,19671,4226],{"class":774},[250,19673,808],{"class":782},[250,19675,19676],{"class":782}," tailwindcss\n",[20,19678,19679],{},"Dependencies are merged into the final build.",[18821,19681,19682],{},[20,19683,19684],{},"Be mindful—shared dependencies affect every extending app.",[72,19686],{},[31,19688,19690],{"id":19689},"recommended-monorepo-structure","Recommended Monorepo Structure",[47,19692,19694],{"className":12725,"code":19693,"language":12727,"meta":55,"style":55},".\n├─ apps\u002F\n│  ├─ web\n│  └─ admin\n├─ layers\u002F\n│  ├─ base-ui\n│  ├─ auth\n│  ├─ billing\n│  └─ dashboard\n",[39,19695,19696,19701,19706,19711,19716,19721,19726,19731,19736],{"__ignoreMap":55},[250,19697,19698],{"class":252,"line":253},[250,19699,19700],{},".\n",[250,19702,19703],{"class":252,"line":113},[250,19704,19705],{},"├─ apps\u002F\n",[250,19707,19708],{"class":252,"line":110},[250,19709,19710],{},"│  ├─ web\n",[250,19712,19713],{"class":252,"line":269},[250,19714,19715],{},"│  └─ admin\n",[250,19717,19718],{"class":252,"line":275},[250,19719,19720],{},"├─ layers\u002F\n",[250,19722,19723],{"class":252,"line":281},[250,19724,19725],{},"│  ├─ base-ui\n",[250,19727,19728],{"class":252,"line":287},[250,19729,19730],{},"│  ├─ auth\n",[250,19732,19733],{"class":252,"line":293},[250,19734,19735],{},"│  ├─ billing\n",[250,19737,19738],{"class":252,"line":299},[250,19739,19740],{},"│  └─ dashboard\n",[20,19742,19743],{},"This structure works well with pnpm workspaces, Turborepo, or Nx.",[72,19745],{},[31,19747,19749],{"id":19748},"real-world-example-saas-starter","Real-World Example: SaaS Starter",[20,19751,19752],{},"A common production setup:",[561,19754,19755,19761,19766,19772],{},[564,19756,19757,19760],{},[39,19758,19759],{},"base-ui"," – Design system",[564,19762,19763,19765],{},[39,19764,18707],{}," – Authentication and guards",[564,19767,19768,19771],{},[39,19769,19770],{},"billing"," – Stripe and subscriptions",[564,19773,19774,19777],{},[39,19775,19776],{},"dashboard"," – Core product UI",[47,19779,19781],{"className":1010,"code":19780,"language":1012,"meta":55,"style":55},"extends: [\n  '..\u002Flayers\u002Fbase-ui',\n  '..\u002Flayers\u002Fauth',\n  '..\u002Flayers\u002Fbilling',\n  '..\u002Flayers\u002Fdashboard'\n]\n",[39,19782,19783,19791,19798,19805,19812,19817],{"__ignoreMap":55},[250,19784,19785,19788],{"class":252,"line":253},[250,19786,19787],{"class":774},"extends",[250,19789,19790],{"class":912},": [\n",[250,19792,19793,19796],{"class":252,"line":113},[250,19794,19795],{"class":782},"  '..\u002Flayers\u002Fbase-ui'",[250,19797,927],{"class":912},[250,19799,19800,19803],{"class":252,"line":110},[250,19801,19802],{"class":782},"  '..\u002Flayers\u002Fauth'",[250,19804,927],{"class":912},[250,19806,19807,19810],{"class":252,"line":269},[250,19808,19809],{"class":782},"  '..\u002Flayers\u002Fbilling'",[250,19811,927],{"class":912},[250,19813,19814],{"class":252,"line":275},[250,19815,19816],{"class":782},"  '..\u002Flayers\u002Fdashboard'\n",[250,19818,19819],{"class":252,"line":281},[250,19820,8695],{"class":912},[20,19822,19823],{},"New apps can be launched in days instead of weeks.",[72,19825],{},[31,19827,19829],{"id":19828},"overriding-behavior-safely","Overriding Behavior Safely",[20,19831,19832],{},"You can override:",[561,19834,19835,19837,19839,19841],{},[564,19836,18804],{},[564,19838,18801],{},[564,19840,18807],{},[564,19842,18810],{},[20,19844,19845,19846,2230],{},"Nuxt resolves conflicts using ",[546,19847,19848],{},"closest-first resolution",[72,19850],{},[31,19852,19854],{"id":19853},"common-pitfalls","Common Pitfalls",[561,19856,19857,19860,19863,19866],{},[564,19858,19859],{},"Putting app-specific logic in base layers",[564,19861,19862],{},"Creating tight coupling between layers",[564,19864,19865],{},"Ignoring layer order",[564,19867,19868],{},"Treating layers like plugins",[20,19870,19871,19872,19875],{},"Design layers as ",[546,19873,19874],{},"products",", not shortcuts.",[72,19877],{},[31,19879,19881],{"id":19880},"layers-vs-nuxt-modules","Layers vs Nuxt Modules",[645,19883,19884,19897],{},[648,19885,19886],{},[651,19887,19888,19891,19894],{},[654,19889,19890],{},"Feature",[654,19892,19893],{},"Layers",[654,19895,19896],{},"Modules",[666,19898,19899,19910,19919,19928],{},[651,19900,19901,19904,19907],{},[671,19902,19903],{},"Pages & layouts",[671,19905,19906],{},"Yes",[671,19908,19909],{},"No",[651,19911,19912,19915,19917],{},[671,19913,19914],{},"File-system reuse",[671,19916,19906],{},[671,19918,19909],{},[651,19920,19921,19924,19926],{},[671,19922,19923],{},"App architecture",[671,19925,19906],{},[671,19927,19909],{},[651,19929,19930,19933,19936],{},[671,19931,19932],{},"Runtime hooks",[671,19934,19935],{},"Limited",[671,19937,19906],{},[20,19939,19940],{},"They solve different problems and often work best together.",[72,19942],{},[31,19944,19946],{"id":19945},"when-you-should-and-shouldnt-use-layers","When You Should (and Shouldn’t) Use Layers",[20,19948,19949],{},[546,19950,19951],{},"Use layers when:",[561,19953,19954,19957,19960],{},[564,19955,19956],{},"You manage multiple Nuxt apps",[564,19958,19959],{},"You want shared features or UI",[564,19961,19962],{},"You’re building a SaaS platform",[20,19964,19965],{},[546,19966,19967],{},"Avoid layers when:",[561,19969,19970,19973],{},[564,19971,19972],{},"You have a single small app",[564,19974,19975],{},"There is little to no shared logic",[72,19977],{},[31,19979,3352],{"id":3351},[20,19981,19982],{},"Nuxt Layers unlock a new level of scalability and maintainability for Nuxt 3 applications. When designed intentionally, they allow teams to move faster, share more, and maintain cleaner architectures over time.",[20,19984,19985],{},"If you’re serious about building scalable Nuxt applications, mastering layers is no longer optional—it’s essential.",[20,19987,19988],{},"Happy building 🚀",[500,19990,19991],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"title":55,"searchDepth":110,"depth":110,"links":19993},[19994,19995,19996,19999,20000,20004,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,20018,20019],{"id":540,"depth":113,"text":541},{"id":18768,"depth":113,"text":18769},{"id":18830,"depth":113,"text":18831,"children":19997},[19998],{"id":18841,"depth":110,"text":18842},{"id":18870,"depth":113,"text":18871},{"id":18899,"depth":113,"text":18900,"children":20001},[20002,20003],{"id":18903,"depth":110,"text":18904},{"id":18978,"depth":110,"text":18979},{"id":19183,"depth":113,"text":19184,"children":20005},[20006],{"id":19187,"depth":110,"text":19188},{"id":19304,"depth":113,"text":19305},{"id":19368,"depth":113,"text":19369},{"id":19404,"depth":113,"text":19405},{"id":19482,"depth":113,"text":19483},{"id":19597,"depth":113,"text":19598},{"id":19652,"depth":113,"text":19653},{"id":19689,"depth":113,"text":19690},{"id":19748,"depth":113,"text":19749},{"id":19828,"depth":113,"text":19829},{"id":19853,"depth":113,"text":19854},{"id":19880,"depth":113,"text":19881},{"id":19945,"depth":113,"text":19946},{"id":3351,"depth":113,"text":3352},"2026-01-06","A comprehensive, tutorial-style deep dive into Nuxt Layers—learn how to design, build, and scale reusable Nuxt 3 applications using layers.",{"type":12,"value":20023},[20024,20026,20028,20034,20036,20044,20046],[15,20025,18726],{"id":18725},[31,20027,541],{"id":540},[20,20029,18731,20030,18735,20032,18739],{},[546,20031,18734],{},[546,20033,18738],{},[20,20035,18742],{},[561,20037,20038,20040,20042],{},[564,20039,18747],{},[564,20041,18750],{},[564,20043,18753],{},[20,20045,18756],{},[20,20047,18759,20048,18763],{},[546,20049,18762],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517433456452-f9633a875f6f",[18706,20052,20053,13747,20054,20055],"nuxt layers","nuxt 3","architecture","monorepo",{},"\u002Fblog\u002Fnuxt-layer",{"title":18719,"description":20021},"blog\u002Fnuxt-layer","9KWnMT6x33L-CQzC53dSqzURulcxL3MpwoC-Y4Vn_yY",{"id":20062,"title":20063,"author":20064,"body":20065,"canonical":115,"categories":115,"date":20144,"description":20145,"excerpt":20146,"extension":118,"img":119,"keywords":20152,"language":127,"meta":20153,"navigation":129,"ogImage":115,"path":20154,"rating":269,"readTime":132,"seo":20155,"stem":20156,"tag":125,"__hash__":20157},"blog\u002Fblog\u002Fnuxt3-lets-talk.md","Nuxt3-RC 10 Lets Talk",{"name":8,"website":9,"img":10},{"type":12,"value":20066,"toc":20135},[20067,20071,20074,20078,20084,20088,20095,20099,20106,20109,20118,20122,20125,20129,20132],[15,20068,20070],{"id":20069},"nuxt3-rc","Nuxt3 RC",[20,20072,20073],{},"Since its release last year October, Nuxt 3 Beta to RC10; Nuxt developers and maintainers have place a lot of\nemphasis on the performance first to be blazing fast with impressive features suchas auto imports (the best feature to date)\nand not coming to nearly a year the stable version should see the long await Hybrid Generation which will allow developers to\ndevelop web application to exisit on both a static and server side rendered environment. So lets look at RC10 and see if we can make heads or tails of this release.",[15,20075,20077],{"id":20076},"features-at-a-glance","Features at a Glance",[47,20079,20082],{"className":20080,"code":20081,"language":52},[50],"Nuxt 3 Release Candidate 10 is out ✨\n\n🚀 Full Static Generation\n⚡️ Link Prefetching\n💨 Inlined Critical Styles\n0️⃣ Experimental Zero-Client-JS Mode\n🪡 55+ enhancements and bug fixes\n",[39,20083,20081],{"__ignoreMap":55},[31,20085,20087],{"id":20086},"full-static-generation","Full Static Generation",[20,20089,20090,20091,20094],{},"Static rendering is basically files being pre-rendered using ",[39,20092,20093],{},"nuxt generate"," which allows for Nuxt to be deployed to any static\nhosting without a server API, but Nuxt3 takes it to whole other level based on the update changes in RC10 - however it does not give\nus the long await hybrid or incremental generated pages so its a start (hopefully RC12).",[31,20096,20098],{"id":20097},"link-prefetching","Link Prefetching",[20,20100,20101,20102],{},"This feature ported from Nuxt 2, is automatically prefetching the next pages when a ",[20103,20104,20105],"nuxt-link",{}," is in the viewport.",[20,20107,20108],{},"This feature is integrated with vue-router to prefetch components of the next route and also payload extraction to prefetch the payload of the next pages ahead of time! You can also hook into link:prefetch to do more prefetches.",[2459,20110,20112,20113],{"id":20111},"so-much-more-have-read-here","so much more have ",[203,20114,20117],{"href":20115,"rel":20116},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fframework\u002Fdiscussions\u002F7513",[207],"read here",[31,20119,20121],{"id":20120},"whats-next","What's Next?",[20,20123,20124],{},"Your guess is as good as mine the stable version was promised from Summer and summer is well summer. It seems the best bet\nwould be for Nuxt 3 to come out in October the same time the beta was announced but I am just guessing.",[31,20126,20128],{"id":20127},"how-to-get-started","How to get started",[20,20130,20131],{},"Well the Nuxt3 RC documentation is your best bet for all your nuxt goodness. I will be starting a deep in Nuxt soon be update.",[20,20133,20134],{},"Peace......",{"title":55,"searchDepth":110,"depth":110,"links":20136},[20137,20138,20142,20143],{"id":20086,"depth":113,"text":20087},{"id":20097,"depth":113,"text":20098,"children":20139},[20140],{"id":20111,"depth":110,"text":20141},"so much more have read here",{"id":20120,"depth":113,"text":20121},{"id":20127,"depth":113,"text":20128},"2022-08-10","Nuxt3 RC is now 10 releases old but how does it stack up with past releases.",{"type":12,"value":20147},[20148,20150],[15,20149,20070],{"id":20069},[20,20151,20073],{},[121,122,123,124,125,126],{},"\u002Fblog\u002Fnuxt3-lets-talk",{"title":20063,"description":20145},"blog\u002Fnuxt3-lets-talk","hmAlO8zxdUYcQ-mukkrvk4i94POdgHtqaGp1nuEMpDQ",{"id":20159,"title":20160,"author":20161,"body":20162,"canonical":115,"categories":115,"date":20884,"description":20885,"excerpt":20886,"extension":118,"img":20050,"keywords":20902,"language":3510,"meta":20905,"navigation":129,"ogImage":115,"path":20906,"rating":275,"readTime":132,"seo":20907,"stem":20908,"tag":3515,"__hash__":20909},"blog\u002Fblog\u002Freact-native-vs-dious.md","Dioxus vs React Native: A Modern Cross-Platform UI Comparison",{"name":8,"img":10,"website":535},{"type":12,"value":20163,"toc":20850},[20164,20166,20175,20184,20186,20190,20269,20271,20275,20277,20283,20297,20323,20326,20329,20336,20347,20368,20371,20377,20379,20383,20387,20390,20404,20407,20418,20422,20425,20433,20436,20444,20447,20449,20453,20457,20460,20493,20496,20507,20510,20515,20519,20522,20531,20533,20541,20543,20551,20553,20555,20558,20563,20571,20574,20585,20588,20591,20599,20602,20610,20612,20616,20620,20634,20647,20653,20657,20671,20674,20685,20689,20692,20694,20696,20699,20702,20716,20722,20725,20728,20739,20742,20744,20748,20751,20762,20765,20776,20779,20781,20785,20791,20805,20809,20813,20827,20829,20831,20838,20841,20844,20847],[15,20165,541],{"id":540},[20,20167,20168,20169,20171,20172,20174],{},"Cross-platform development has become the default approach for building modern applications. Among the many frameworks available, ",[546,20170,3566],{}," has long been the industry standard. However, newer frameworks like ",[546,20173,3529],{}," are challenging that position by offering a Rust-first, high-performance alternative.",[20,20176,20177,20178,20180,20181,20183],{},"In this post, we’ll compare ",[546,20179,3558],{}," and ",[546,20182,3566],{}," across architecture, performance, developer experience, tooling, and ecosystem to help you decide which framework fits your next project.",[15,20185,748],{"id":747},[31,20187,20189],{"id":20188},"high-level-overview","High-Level Overview",[645,20191,20192,20202],{},[648,20193,20194],{},[651,20195,20196,20198,20200],{},[654,20197,19890],{},[654,20199,3529],{},[654,20201,3566],{},[666,20203,20204,20214,20225,20236,20247,20258],{},[651,20205,20206,20209,20211],{},[671,20207,20208],{},"Language",[671,20210,3533],{},[671,20212,20213],{},"JavaScript \u002F TypeScript",[651,20215,20216,20219,20222],{},[671,20217,20218],{},"UI Model",[671,20220,20221],{},"Declarative (RSX)",[671,20223,20224],{},"Declarative (JSX)",[651,20226,20227,20230,20233],{},[671,20228,20229],{},"Platforms",[671,20231,20232],{},"Web, Desktop, Mobile",[671,20234,20235],{},"Mobile (iOS, Android)",[651,20237,20238,20241,20244],{},[671,20239,20240],{},"Rendering",[671,20242,20243],{},"Native + WASM",[671,20245,20246],{},"Native via bridge",[651,20248,20249,20252,20255],{},[671,20250,20251],{},"Backend Integration",[671,20253,20254],{},"Native Rust fullstack",[671,20256,20257],{},"Separate backend",[651,20259,20260,20263,20266],{},[671,20261,20262],{},"Performance Focus",[671,20264,20265],{},"Compile-time + memory safety",[671,20267,20268],{},"Runtime optimizations",[72,20270],{},[31,20272,20274],{"id":20273},"language-type-safety","Language & Type Safety",[2459,20276,3558],{"id":4070},[20,20278,20279,20280,20282],{},"Dioxus is built entirely in ",[546,20281,3533],{},", giving developers:",[561,20284,20285,20288,20291,20294],{},[564,20286,20287],{},"Strong compile-time guarantees",[564,20289,20290],{},"Memory safety without garbage collection",[564,20292,20293],{},"Fearless refactoring",[564,20295,20296],{},"Fewer runtime crashes",[47,20298,20300],{"className":3660,"code":20299,"language":3662,"meta":55,"style":55},"fn App() -> Element {\n    rsx! {\n        div { \"Hello from Rust!\" }\n    }\n}\n",[39,20301,20302,20306,20310,20315,20319],{"__ignoreMap":55},[250,20303,20304],{"class":252,"line":253},[250,20305,3669],{},[250,20307,20308],{"class":252,"line":113},[250,20309,3674],{},[250,20311,20312],{"class":252,"line":110},[250,20313,20314],{},"        div { \"Hello from Rust!\" }\n",[250,20316,20317],{"class":252,"line":269},[250,20318,3684],{},[250,20320,20321],{"class":252,"line":275},[250,20322,991],{},[20,20324,20325],{},"Rust errors are caught at compile time, reducing runtime failures common in large JavaScript codebases.\n::",[2459,20327,3566],{"id":20328},"react-native",[20,20330,20331,20332,20335],{},"React Native relies on ",[546,20333,20334],{},"JavaScript or TypeScript",", which offers:",[561,20337,20338,20341,20344],{},[564,20339,20340],{},"Faster onboarding",[564,20342,20343],{},"Massive community knowledge",[564,20345,20346],{},"Runtime flexibility",[47,20348,20352],{"className":20349,"code":20350,"language":20351,"meta":55,"style":55},"language-tsx shiki shiki-themes github-light github-dark","export default function App() {\n  return \u003CText>Hello from React Native\u003C\u002FText>;\n}\n","tsx",[39,20353,20354,20359,20364],{"__ignoreMap":55},[250,20355,20356],{"class":252,"line":253},[250,20357,20358],{},"export default function App() {\n",[250,20360,20361],{"class":252,"line":113},[250,20362,20363],{},"  return \u003CText>Hello from React Native\u003C\u002FText>;\n",[250,20365,20366],{"class":252,"line":110},[250,20367,991],{},[20,20369,20370],{},"Despite TypeScript, many errors in React Native still surface at runtime, especially around async state and native bridges.\n::",[20,20372,20373,20376],{},[546,20374,20375],{},"Verdict:","\nDioxus wins on safety and correctness. React Native wins on approachability and familiarity.",[72,20378],{},[31,20380,20382],{"id":20381},"performance-architecture","Performance & Architecture",[2459,20384,20386],{"id":20385},"dioxus-performance-model","Dioxus Performance Model",[20,20388,20389],{},"Dioxus benefits from:",[561,20391,20392,20395,20398,20401],{},[564,20393,20394],{},"Zero-cost abstractions",[564,20396,20397],{},"No JS bridge",[564,20399,20400],{},"Direct native execution",[564,20402,20403],{},"WASM for the web",[20,20405,20406],{},"This leads to:",[561,20408,20409,20412,20415],{},[564,20410,20411],{},"Faster startup times",[564,20413,20414],{},"Lower memory usage",[564,20416,20417],{},"Predictable performance",[2459,20419,20421],{"id":20420},"react-native-performance-model","React Native Performance Model",[20,20423,20424],{},"React Native uses:",[561,20426,20427,20430],{},[564,20428,20429],{},"A JS runtime",[564,20431,20432],{},"A native bridge (even with the new architecture)",[20,20434,20435],{},"While performance has improved significantly, complex UIs can still suffer from:",[561,20437,20438,20441],{},[564,20439,20440],{},"Bridge overhead",[564,20442,20443],{},"Thread synchronization issues",[20,20445,20446],{},"If your app is performance-critical (IoT dashboards, embedded systems, real-time UIs), Dioxus has a structural advantage.\n::",[72,20448],{},[31,20450,20452],{"id":20451},"ui-development-experience","UI Development Experience",[2459,20454,20456],{"id":20455},"dioxus-rsx","Dioxus (RSX)",[20,20458,20459],{},"RSX feels similar to JSX but enforces correctness:",[47,20461,20463],{"className":3660,"code":20462,"language":3662,"meta":55,"style":55},"rsx! {\n    button {\n        onclick: move |_| count += 1,\n        \"Increment\"\n    }\n}\n",[39,20464,20465,20470,20475,20480,20485,20489],{"__ignoreMap":55},[250,20466,20467],{"class":252,"line":253},[250,20468,20469],{},"rsx! {\n",[250,20471,20472],{"class":252,"line":113},[250,20473,20474],{},"    button {\n",[250,20476,20477],{"class":252,"line":110},[250,20478,20479],{},"        onclick: move |_| count += 1,\n",[250,20481,20482],{"class":252,"line":269},[250,20483,20484],{},"        \"Increment\"\n",[250,20486,20487],{"class":252,"line":275},[250,20488,3684],{},[250,20490,20491],{"class":252,"line":281},[250,20492,991],{},[20,20494,20495],{},"Pros:",[561,20497,20498,20501,20504],{},[564,20499,20500],{},"Compile-time UI validation",[564,20502,20503],{},"No undefined props",[564,20505,20506],{},"Cleaner refactors",[20,20508,20509],{},"Cons:",[561,20511,20512],{},[564,20513,20514],{},"Rust macros have a learning curve",[2459,20516,20518],{"id":20517},"react-native-jsx","React Native (JSX)",[20,20520,20521],{},"JSX is flexible and expressive:",[47,20523,20525],{"className":20349,"code":20524,"language":20351,"meta":55,"style":55},"\u003CButton title=\"Increment\" onPress={() => setCount(c => c + 1)} \u002F>\n",[39,20526,20527],{"__ignoreMap":55},[250,20528,20529],{"class":252,"line":253},[250,20530,20524],{},[20,20532,20495],{},[561,20534,20535,20538],{},[564,20536,20537],{},"Huge component ecosystem",[564,20539,20540],{},"Familiar React mental model",[20,20542,20509],{},[561,20544,20545,20548],{},[564,20546,20547],{},"Runtime UI errors",[564,20549,20550],{},"Props misuse is easy",[72,20552],{},[31,20554,3710],{"id":3709},[2459,20556,3558],{"id":20557},"dioxus-1",[20,20559,3647,20560,20562],{},[546,20561,3716],{}," and hooks that integrate deeply with Rust’s ownership model:",[47,20564,20565],{"className":3660,"code":3724,"language":3662,"meta":55,"style":55},[39,20566,20567],{"__ignoreMap":55},[250,20568,20569],{"class":252,"line":253},[250,20570,3724],{},[20,20572,20573],{},"Benefits:",[561,20575,20576,20579,20582],{},[564,20577,20578],{},"No stale closures",[564,20580,20581],{},"Predictable updates",[564,20583,20584],{},"Compile-time guarantees",[2459,20586,3566],{"id":20587},"react-native-1",[20,20589,20590],{},"React Native relies on:",[561,20592,20593,20596],{},[564,20594,20595],{},"React hooks",[564,20597,20598],{},"External libraries (Redux, Zustand, Recoil)",[20,20600,20601],{},"This flexibility is powerful—but can lead to:",[561,20603,20604,20607],{},[564,20605,20606],{},"State sprawl",[564,20608,20609],{},"Hard-to-debug race conditions",[72,20611],{},[31,20613,20615],{"id":20614},"tooling-developer-experience","Tooling & Developer Experience",[2459,20617,20619],{"id":20618},"dioxus-tooling","Dioxus Tooling",[561,20621,20622,20625,20628,20631],{},[564,20623,20624],{},"Built-in CLI",[564,20626,20627],{},"Hot reload",[564,20629,20630],{},"Unified build pipeline",[564,20632,20633],{},"Rust analyzer integration",[47,20635,20637],{"className":758,"code":20636,"language":761,"meta":55,"style":55},"dx serve\n",[39,20638,20639],{"__ignoreMap":55},[250,20640,20641,20644],{"class":252,"line":253},[250,20642,20643],{"class":774},"dx",[250,20645,20646],{"class":782}," serve\n",[20,20648,20649,20650,2230],{},"Everything—from UI to backend—lives in ",[546,20651,20652],{},"one ecosystem",[2459,20654,20656],{"id":20655},"react-native-tooling","React Native Tooling",[561,20658,20659,20662,20665,20668],{},[564,20660,20661],{},"Metro bundler",[564,20663,20664],{},"Native SDKs",[564,20666,20667],{},"Xcode & Android Studio",[564,20669,20670],{},"Many third-party tools",[20,20672,20673],{},"Powerful, but:",[561,20675,20676,20679,20682],{},[564,20677,20678],{},"Complex setup",[564,20680,20681],{},"Platform-specific bugs",[564,20683,20684],{},"Steeper maintenance at scale",[2459,20686,20688],{"id":20687},"tooling-summary","Tooling Summary",[20,20690,20691],{},"Dioxus prioritizes simplicity and cohesion.\nReact Native prioritizes flexibility and scale.\n::",[72,20693],{},[31,20695,3955],{"id":3954},[2459,20697,3558],{"id":20698},"dioxus-2",[20,20700,20701],{},"Dioxus shines here.",[561,20703,20704,20707,20710,20713],{},[564,20705,20706],{},"Frontend and backend both in Rust",[564,20708,20709],{},"Shared types",[564,20711,20712],{},"Server functions",[564,20714,20715],{},"SSR support",[20,20717,20718,20719,2230],{},"This makes it ideal for ",[546,20720,20721],{},"end-to-end Rust teams",[2459,20723,3566],{"id":20724},"react-native-2",[20,20726,20727],{},"React Native typically requires:",[561,20729,20730,20733,20736],{},[564,20731,20732],{},"Separate backend stack",[564,20734,20735],{},"API contracts",[564,20737,20738],{},"Data validation duplication",[20,20740,20741],{},"Still powerful—but fragmented.",[72,20743],{},[31,20745,20747],{"id":20746},"ecosystem-community","Ecosystem & Community",[2459,20749,3566],{"id":20750},"react-native-3",[561,20752,20753,20756,20759],{},[564,20754,20755],{},"Massive ecosystem",[564,20757,20758],{},"Thousands of libraries",[564,20760,20761],{},"Long-term industry support",[2459,20763,3558],{"id":20764},"dioxus-3",[561,20766,20767,20770,20773],{},[564,20768,20769],{},"Smaller but growing ecosystem",[564,20771,20772],{},"Strong Rust community backing",[564,20774,20775],{},"Rapid iteration",[20,20777,20778],{},"Dioxus is younger, but its pace of development is significantly faster than React Native’s early years.\n::",[72,20780],{},[31,20782,20784],{"id":20783},"when-to-choose-dioxus","When to Choose Dioxus",[20,20786,20787,20788,20790],{},"Choose ",[546,20789,3558],{}," if:",[561,20792,20793,20796,20799,20802],{},[564,20794,20795],{},"You value performance and safety",[564,20797,20798],{},"Your team knows Rust",[564,20800,20801],{},"You want a unified fullstack solution",[564,20803,20804],{},"You target web + desktop + mobile",[31,20806,20808],{"id":20807},"when-to-choose-react-native","When to Choose React Native",[20,20810,20787,20811,20790],{},[546,20812,3566],{},[561,20814,20815,20818,20821,20824],{},[564,20816,20817],{},"You need mature mobile tooling",[564,20819,20820],{},"You rely on third-party native modules",[564,20822,20823],{},"Your team is React-centric",[564,20825,20826],{},"Time-to-market is critical",[72,20828],{},[15,20830,3352],{"id":3351},[20,20832,20833,20834,20837],{},"React Native remains a dominant force in cross-platform mobile development, backed by a massive ecosystem and years of production usage. However, ",[546,20835,20836],{},"Dioxus 0.7 introduces a compelling alternative","—one built on performance, safety, and architectural simplicity.",[20,20839,20840],{},"For teams willing to invest in Rust, Dioxus offers a future-proof approach to building fast, reliable, cross-platform applications with fewer runtime surprises.",[20,20842,20843],{},"The choice isn’t about which framework is “better”—it’s about which philosophy aligns with your product and team.",[20,20845,20846],{},"And in 2026, Dioxus is no longer experimental—it’s a serious contender. 🚀",[500,20848,20849],{},"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 .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}",{"title":55,"searchDepth":110,"depth":110,"links":20851},[20852,20853,20857,20861,20865,20869,20874,20878,20882,20883],{"id":20188,"depth":113,"text":20189},{"id":20273,"depth":113,"text":20274,"children":20854},[20855,20856],{"id":4070,"depth":110,"text":3558},{"id":20328,"depth":110,"text":3566},{"id":20381,"depth":113,"text":20382,"children":20858},[20859,20860],{"id":20385,"depth":110,"text":20386},{"id":20420,"depth":110,"text":20421},{"id":20451,"depth":113,"text":20452,"children":20862},[20863,20864],{"id":20455,"depth":110,"text":20456},{"id":20517,"depth":110,"text":20518},{"id":3709,"depth":113,"text":3710,"children":20866},[20867,20868],{"id":20557,"depth":110,"text":3558},{"id":20587,"depth":110,"text":3566},{"id":20614,"depth":113,"text":20615,"children":20870},[20871,20872,20873],{"id":20618,"depth":110,"text":20619},{"id":20655,"depth":110,"text":20656},{"id":20687,"depth":110,"text":20688},{"id":3954,"depth":113,"text":3955,"children":20875},[20876,20877],{"id":20698,"depth":110,"text":3558},{"id":20724,"depth":110,"text":3566},{"id":20746,"depth":113,"text":20747,"children":20879},[20880,20881],{"id":20750,"depth":110,"text":3566},{"id":20764,"depth":110,"text":3558},{"id":20783,"depth":113,"text":20784},{"id":20807,"depth":113,"text":20808},"2026-01-11","A deep comparison of Dioxus 0.7 and React Native, exploring performance, developer experience, tooling, and when to choose each framework.",{"type":12,"value":20887},[20888,20890,20896],[15,20889,541],{"id":540},[20,20891,20168,20892,20171,20894,20174],{},[546,20893,3566],{},[546,20895,3529],{},[20,20897,20177,20898,20180,20900,20183],{},[546,20899,3558],{},[546,20901,3566],{},[4070,20903,3662,4071,20904],"react native","mobile development",{},"\u002Fblog\u002Freact-native-vs-dious",{"title":20160,"description":20885},"blog\u002Freact-native-vs-dious","VlkcpvVRs-Q5BDQX5w19bfZQiDlIXmJbA3bgXLsQqsc",{"id":20911,"title":20912,"author":20913,"body":20914,"canonical":115,"categories":115,"date":21111,"description":21112,"excerpt":21113,"extension":118,"img":21125,"keywords":21126,"language":3510,"meta":21132,"navigation":129,"ogImage":115,"path":21133,"rating":275,"readTime":287,"seo":21134,"stem":21135,"tag":3515,"__hash__":21136},"blog\u002Fblog\u002Fsolo-level.md","Level Up in 2026: Why The Solo Level Is a Game-Changer for Developers",{"name":8,"img":10,"website":535},{"type":12,"value":20915,"toc":21102},[20916,20918,20931,20933,20937,20946,20953,20957,20960,20986,21009,21012,21016,21025,21031,21038,21042,21049,21054,21058,21069,21071,21073,21091,21099],[15,20917,541],{"id":540},[20,20919,20920,20921,20924,20925,20928,20929,2230],{},"What if leveling up your ",[546,20922,20923],{},"coding skills"," felt more like playing your favorite RPG than checking off tasks? That’s exactly the experience The Solo Level delivers — a gamified, AI-enhanced platform that makes coding ",[546,20926,20927],{},"fun, competitive, and deeply motivating",". If you’re a developer looking to stay engaged, track progress, and connect with others on the same journey, this is one tool you’ll want in your toolkit in ",[546,20930,11126],{},[15,20932,748],{"id":747},[31,20934,20936],{"id":20935},"what-is-the-solo-level","What Is The Solo Level?",[20,20938,20939,20940,20943,20944],{},"The Solo Level is an innovative coding platform that transforms everyday programming work into a ",[546,20941,20942],{},"role-playing game experience",". Every commit becomes XP, streaks power up your multiplier, and even bugs can earn you rewards — turning the grind of coding into an adventure. ",[3540,20945,3543],{"index":3542},[24,20947,20948],{"type":631},[20,20949,20950,20951],{},"With seamless VS Code integration and real-time visual stats, you don’t just write code — you level up your developer avatar as you improve. ",[3540,20952,3570],{"index":1198},[31,20954,20956],{"id":20955},"how-it-works-your-coding-quest-begins","How It Works — Your Coding Quest Begins",[20,20958,20959],{},"Getting started is simple:",[2922,20961,20962,20970,20978],{},[564,20963,20964,20967,20968],{},[546,20965,20966],{},"Install the Solo Level VS Code extension"," — your editor becomes your dashboard as you code. ",[3540,20969,3582],{"index":1226},[564,20971,20972,20975,20976],{},[546,20973,20974],{},"Write & Commit Code"," — every commit earns you XP and tracks your progress. ",[3540,20977,3630],{"index":1249},[564,20979,20980,20983,20984],{},[546,20981,20982],{},"Earn Badges & Climb the Leaderboards"," — unlock achievements, compete globally, and celebrate your wins with the community. ",[3540,20985,3638],{"index":1273},[10834,20987,20988,20992],{},[2459,20989,20991],{"id":20990},"core-gameplay-features","Core Gameplay Features",[561,20993,20994,20997,21000,21003,21006],{},[564,20995,20996],{},"✔ XP for commits and daily streaks",[564,20998,20999],{},"✔ Visual progress dashboards",[564,21001,21002],{},"✔ Global and guild leaderboards",[564,21004,21005],{},"✔ Bounty system for challenges",[564,21007,21008],{},"✔ Team management and competitions",[20,21010,21011],{},"Whether you’re coding solo or rallying a guild of teammates, Solo Level turns your codebase into a world of quests and rewards.",[31,21013,21015],{"id":21014},"supercharged-by-ai","Supercharged by AI",[20,21017,21018,21019,21022,21023],{},"One of the most exciting aspects of The Solo Level is how it uses ",[546,21020,21021],{},"AI to boost learning and challenge creation",". Personalized AI-generated coding challenges match your skill level and learning goals, offering custom tasks that help you grow faster. ",[3540,21024,3653],{"index":1297},[161,21026,21028],{"icon":11228,"title":21027},"AI That Learns With You",[20,21029,21030],{},"AI isn’t just a buzzword here — it creates tailored challenges and insightful feedback that adapt to your progress.",[20,21032,21033,21034],{},"AI also powers smart analytics, giving actionable insights into your coding habits so you can identify strengths and areas to improve. ",[3540,21035,21037],{"index":21036},"6","oaicite:6",[31,21039,21041],{"id":21040},"go-beyond-solo-build-a-community","Go Beyond Solo — Build a Community",[20,21043,21044,21045],{},"Coding doesn’t have to be a solitary pursuit. With guilds and team challenges, The Solo Level encourages collaboration, friendly competition, and shared accomplishment. Assemble a team, set goals, track progress together, and climb the leaderboards as a squad. ",[3540,21046,21048],{"index":21047},"7","oaicite:7",[24,21050,21051],{"type":26},[20,21052,21053],{},"Friendly competition isn’t just fun — it motivates consistent progress and boosts productivity.",[31,21055,21057],{"id":21056},"why-developers-love-it","Why Developers Love It",[20,21059,21060,21061,21064,21065],{},"Solo Level isn’t just another tool — it’s a ",[546,21062,21063],{},"motivation engine",". Whether you’re a beginner wanting to build habits or a seasoned pro striving for mastery, gamification helps you stay engaged and productive. From day one you’re rewarded, tracked, and connected. ",[3540,21066,21068],{"index":21067},"8","oaicite:8",[72,21070],{},[15,21072,3352],{"id":3351},[20,21074,21075,21076,21079,21080,7128,21083,21086,21087,21090],{},"The Solo Level turns coding into something you ",[3587,21077,21078],{},"want"," to come back to every day. It blends ",[546,21081,21082],{},"game mechanics",[546,21084,21085],{},"AI-powered challenges",", and ",[546,21088,21089],{},"community engagement"," to make improving your craft both fun and measurable. If you’re ready to level up your skills and join a growing guild of developers, there’s never been a better time to start your journey. 🎮🚀",[20,21092,21093,21094,21098],{},"👉 Check it out at ",[203,21095,21096],{"href":21096,"rel":21097},"https:\u002F\u002Fwww.thesololevel.com\u002F",[207]," and begin your own coding adventure.",[3540,21100,21101],{},"oaicite:9",{"title":55,"searchDepth":110,"depth":110,"links":21103},[21104,21105,21108,21109,21110],{"id":20935,"depth":113,"text":20936},{"id":20955,"depth":113,"text":20956,"children":21106},[21107],{"id":20990,"depth":110,"text":20991},{"id":21014,"depth":113,"text":21015},{"id":21040,"depth":113,"text":21041},{"id":21056,"depth":113,"text":21057},"2026-01-05","Explore how The Solo Level turns coding into an RPG adventure with AI-powered challenges, XP systems, and community leaderboards.",{"type":12,"value":21114},[21115,21117],[15,21116,541],{"id":540},[20,21118,20920,21119,20924,21121,20928,21123,2230],{},[546,21120,20923],{},[546,21122,20927],{},[546,21124,11126],{},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1767533332\u002Fsolo_level_pqfwko.jpg",[21127,21128,21129,21130,21131],"solo level","coding gamification","ai","developers","productivity",{},"\u002Fblog\u002Fsolo-level",{"title":20912,"description":21112},"blog\u002Fsolo-level","mLN2pXFUaKU9_0bbZ48fq4EhyfBty7OHC2KRS2cxt9Y",{"id":21138,"title":21139,"author":21140,"body":21141,"canonical":115,"categories":115,"date":22498,"description":22499,"excerpt":22500,"extension":118,"img":3502,"keywords":22506,"language":3510,"meta":22512,"navigation":129,"ogImage":115,"path":22513,"rating":275,"readTime":293,"seo":22514,"stem":22515,"tag":3515,"__hash__":22516},"blog\u002Fblog\u002Ftanstack-query.md","Mastering Data Fetching with TanStack Query: A Modern Approach",{"name":8,"img":10,"website":535},{"type":12,"value":21142,"toc":22482},[21143,21145,21148,21152,21155,21158,21162,21165,21203,21208,21212,21215,21219,21248,21252,21255,21312,21316,21319,21464,21470,21474,21478,21481,21668,21672,21675,21794,21803,21807,21810,21948,21950,21955,21959,22012,22016,22019,22184,22188,22191,22238,22244,22248,22252,22255,22324,22327,22330,22463,22465,22467,22470,22473,22476,22479],[15,21144,541],{"id":540},[20,21146,21147],{},"Data fetching is one of the most common challenges developers face when building modern web applications. While it might seem straightforward at first, managing server state quickly becomes complex when you need to handle caching, background updates, pagination, and error states. This is where TanStack Query (formerly React Query) comes in—a powerful library that transforms how we think about server state management.",[15,21149,21151],{"id":21150},"what-is-tanstack-query","What is TanStack Query?",[20,21153,21154],{},"TanStack Query is a data-fetching and state management library that provides powerful tools for fetching, caching, synchronizing, and updating server state in your applications. Unlike traditional state management solutions, TanStack Query treats server data as a first-class citizen, recognizing that it has fundamentally different characteristics than client state.",[20,21156,21157],{},"The library works seamlessly with React, Vue, Svelte, and Solid, making it a versatile choice regardless of your framework preference. It eliminates the need for writing complex boilerplate code and helps you build more maintainable applications.",[31,21159,21161],{"id":21160},"why-use-tanstack-query","Why Use TanStack Query?",[20,21163,21164],{},"Traditional data fetching approaches often require you to manage loading states, error handling, caching logic, and refetching strategies manually. TanStack Query handles all of this out of the box, providing:",[561,21166,21167,21173,21179,21185,21191,21197],{},[564,21168,21169,21172],{},[546,21170,21171],{},"Automatic caching"," with intelligent cache invalidation",[564,21174,21175,21178],{},[546,21176,21177],{},"Background refetching"," to keep data fresh",[564,21180,21181,21184],{},[546,21182,21183],{},"Optimistic updates"," for better UX",[564,21186,21187,21190],{},[546,21188,21189],{},"Request deduplication"," to prevent unnecessary network calls",[564,21192,21193,21196],{},[546,21194,21195],{},"Pagination and infinite scroll"," support",[564,21198,21199,21202],{},[546,21200,21201],{},"Prefetching"," for improved perceived performance",[24,21204,21205],{"type":631},[20,21206,21207],{},"TanStack Query doesn't replace fetch or axios—it enhances them by providing a smart layer of abstraction for managing server state.",[15,21209,21211],{"id":21210},"getting-started","Getting Started",[20,21213,21214],{},"Let's dive into how you can start using TanStack Query in your React application.",[31,21216,21218],{"id":21217},"installation","Installation",[47,21220,21222],{"className":758,"code":21221,"filename":760,"language":761,"meta":55,"style":55},"npm install @tanstack\u002Freact-query\n# or\nyarn add @tanstack\u002Freact-query\n",[39,21223,21224,21233,21238],{"__ignoreMap":55},[250,21225,21226,21228,21230],{"class":252,"line":253},[250,21227,4226],{"class":774},[250,21229,808],{"class":782},[250,21231,21232],{"class":782}," @tanstack\u002Freact-query\n",[250,21234,21235],{"class":252,"line":113},[250,21236,21237],{"class":768},"# or\n",[250,21239,21240,21243,21246],{"class":252,"line":110},[250,21241,21242],{"class":774},"yarn",[250,21244,21245],{"class":782}," add",[250,21247,21232],{"class":782},[31,21249,21251],{"id":21250},"basic-setup","Basic Setup",[20,21253,21254],{},"First, wrap your application with the QueryClientProvider:",[47,21256,21259],{"className":20349,"code":21257,"filename":21258,"language":20351,"meta":55,"style":55},"import { QueryClient, QueryClientProvider } from '@tanstack\u002Freact-query';\n\nconst queryClient = new QueryClient();\n\nfunction App() {\n  return (\n    \u003CQueryClientProvider client={queryClient}>\n      \u003CYourApp \u002F>\n    \u003C\u002FQueryClientProvider>\n  );\n}\n","App.tsx",[39,21260,21261,21266,21270,21275,21279,21284,21289,21294,21299,21304,21308],{"__ignoreMap":55},[250,21262,21263],{"class":252,"line":253},[250,21264,21265],{},"import { QueryClient, QueryClientProvider } from '@tanstack\u002Freact-query';\n",[250,21267,21268],{"class":252,"line":113},[250,21269,795],{"emptyLinePlaceholder":129},[250,21271,21272],{"class":252,"line":110},[250,21273,21274],{},"const queryClient = new QueryClient();\n",[250,21276,21277],{"class":252,"line":269},[250,21278,795],{"emptyLinePlaceholder":129},[250,21280,21281],{"class":252,"line":275},[250,21282,21283],{},"function App() {\n",[250,21285,21286],{"class":252,"line":281},[250,21287,21288],{},"  return (\n",[250,21290,21291],{"class":252,"line":287},[250,21292,21293],{},"    \u003CQueryClientProvider client={queryClient}>\n",[250,21295,21296],{"class":252,"line":293},[250,21297,21298],{},"      \u003CYourApp \u002F>\n",[250,21300,21301],{"class":252,"line":299},[250,21302,21303],{},"    \u003C\u002FQueryClientProvider>\n",[250,21305,21306],{"class":252,"line":132},[250,21307,2859],{},[250,21309,21310],{"class":252,"line":310},[250,21311,991],{},[31,21313,21315],{"id":21314},"your-first-query","Your First Query",[20,21317,21318],{},"Here's a simple example of fetching user data:",[47,21320,21323],{"className":20349,"code":21321,"filename":21322,"language":20351,"meta":55,"style":55},"import { useQuery } from '@tanstack\u002Freact-query';\n\ninterface User {\n  id: number;\n  name: string;\n  email: string;\n}\n\nasync function fetchUser(userId: string): Promise\u003CUser> {\n  const response = await fetch(`\u002Fapi\u002Fusers\u002F${userId}`);\n  if (!response.ok) throw new Error('Failed to fetch user');\n  return response.json();\n}\n\nfunction UserProfile({ userId }: { userId: string }) {\n  const { data, isLoading, error } = useQuery({\n    queryKey: ['user', userId],\n    queryFn: () => fetchUser(userId),\n  });\n\n  if (isLoading) return \u003Cdiv>Loading...\u003C\u002Fdiv>;\n  if (error) return \u003Cdiv>Error: {error.message}\u003C\u002Fdiv>;\n\n  return (\n    \u003Cdiv>\n      \u003Ch1>{data.name}\u003C\u002Fh1>\n      \u003Cp>{data.email}\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  );\n}\n","UserProfile.tsx",[39,21324,21325,21330,21334,21339,21344,21349,21354,21358,21362,21367,21372,21377,21382,21386,21390,21395,21400,21405,21410,21414,21418,21423,21428,21432,21436,21441,21446,21451,21456,21460],{"__ignoreMap":55},[250,21326,21327],{"class":252,"line":253},[250,21328,21329],{},"import { useQuery } from '@tanstack\u002Freact-query';\n",[250,21331,21332],{"class":252,"line":113},[250,21333,795],{"emptyLinePlaceholder":129},[250,21335,21336],{"class":252,"line":110},[250,21337,21338],{},"interface User {\n",[250,21340,21341],{"class":252,"line":269},[250,21342,21343],{},"  id: number;\n",[250,21345,21346],{"class":252,"line":275},[250,21347,21348],{},"  name: string;\n",[250,21350,21351],{"class":252,"line":281},[250,21352,21353],{},"  email: string;\n",[250,21355,21356],{"class":252,"line":287},[250,21357,991],{},[250,21359,21360],{"class":252,"line":293},[250,21361,795],{"emptyLinePlaceholder":129},[250,21363,21364],{"class":252,"line":299},[250,21365,21366],{},"async function fetchUser(userId: string): Promise\u003CUser> {\n",[250,21368,21369],{"class":252,"line":132},[250,21370,21371],{},"  const response = await fetch(`\u002Fapi\u002Fusers\u002F${userId}`);\n",[250,21373,21374],{"class":252,"line":310},[250,21375,21376],{},"  if (!response.ok) throw new Error('Failed to fetch user');\n",[250,21378,21379],{"class":252,"line":316},[250,21380,21381],{},"  return response.json();\n",[250,21383,21384],{"class":252,"line":322},[250,21385,991],{},[250,21387,21388],{"class":252,"line":328},[250,21389,795],{"emptyLinePlaceholder":129},[250,21391,21392],{"class":252,"line":334},[250,21393,21394],{},"function UserProfile({ userId }: { userId: string }) {\n",[250,21396,21397],{"class":252,"line":340},[250,21398,21399],{},"  const { data, isLoading, error } = useQuery({\n",[250,21401,21402],{"class":252,"line":346},[250,21403,21404],{},"    queryKey: ['user', userId],\n",[250,21406,21407],{"class":252,"line":352},[250,21408,21409],{},"    queryFn: () => fetchUser(userId),\n",[250,21411,21412],{"class":252,"line":358},[250,21413,6749],{},[250,21415,21416],{"class":252,"line":364},[250,21417,795],{"emptyLinePlaceholder":129},[250,21419,21420],{"class":252,"line":370},[250,21421,21422],{},"  if (isLoading) return \u003Cdiv>Loading...\u003C\u002Fdiv>;\n",[250,21424,21425],{"class":252,"line":376},[250,21426,21427],{},"  if (error) return \u003Cdiv>Error: {error.message}\u003C\u002Fdiv>;\n",[250,21429,21430],{"class":252,"line":382},[250,21431,795],{"emptyLinePlaceholder":129},[250,21433,21434],{"class":252,"line":388},[250,21435,21288],{},[250,21437,21438],{"class":252,"line":393},[250,21439,21440],{},"    \u003Cdiv>\n",[250,21442,21443],{"class":252,"line":399},[250,21444,21445],{},"      \u003Ch1>{data.name}\u003C\u002Fh1>\n",[250,21447,21448],{"class":252,"line":405},[250,21449,21450],{},"      \u003Cp>{data.email}\u003C\u002Fp>\n",[250,21452,21453],{"class":252,"line":410},[250,21454,21455],{},"    \u003C\u002Fdiv>\n",[250,21457,21458],{"class":252,"line":415},[250,21459,2859],{},[250,21461,21462],{"class":252,"line":420},[250,21463,991],{},[161,21465,21467],{"icon":5036,"title":21466},"Query Keys",[20,21468,21469],{},"Query keys are crucial in TanStack Query. They uniquely identify your queries and are used for caching, refetching, and cache invalidation. Use arrays with descriptive values for better organization.",[15,21471,21473],{"id":21472},"advanced-features","Advanced Features",[31,21475,21477],{"id":21476},"mutations","Mutations",[20,21479,21480],{},"Mutations handle data updates, creations, and deletions. Here's how to create a mutation for updating user data:",[47,21482,21485],{"className":20349,"code":21483,"filename":21484,"language":20351,"meta":55,"style":55},"import { useMutation, useQueryClient } from '@tanstack\u002Freact-query';\n\ninterface UpdateUserData {\n  name: string;\n  email: string;\n}\n\nfunction UpdateUserForm({ userId }: { userId: string }) {\n  const queryClient = useQueryClient();\n\n  const mutation = useMutation({\n    mutationFn: (userData: UpdateUserData) =>\n      fetch(`\u002Fapi\u002Fusers\u002F${userId}`, {\n        method: 'PUT',\n        body: JSON.stringify(userData),\n        headers: { 'Content-Type': 'application\u002Fjson' },\n      }),\n    onSuccess: () => {\n      \u002F\u002F Invalidate and refetch user data\n      queryClient.invalidateQueries({ queryKey: ['user', userId] });\n    },\n  });\n\n  const handleSubmit = (data: UpdateUserData) => {\n    mutation.mutate(data);\n  };\n\n  return (\n    \u003Cform onSubmit={(e) => {\n      e.preventDefault();\n      \u002F\u002F Form handling logic\n    }}>\n      {mutation.isPending && \u003Cp>Updating...\u003C\u002Fp>}\n      {mutation.isError && \u003Cp>Error updating user\u003C\u002Fp>}\n      {mutation.isSuccess && \u003Cp>User updated successfully!\u003C\u002Fp>}\n      {\u002F* Form fields *\u002F}\n    \u003C\u002Fform>\n  );\n}\n","UpdateUser.tsx",[39,21486,21487,21492,21496,21501,21505,21509,21513,21517,21522,21527,21531,21536,21541,21546,21551,21556,21561,21566,21571,21576,21581,21585,21589,21593,21598,21603,21607,21611,21615,21620,21625,21630,21635,21640,21645,21650,21655,21660,21664],{"__ignoreMap":55},[250,21488,21489],{"class":252,"line":253},[250,21490,21491],{},"import { useMutation, useQueryClient } from '@tanstack\u002Freact-query';\n",[250,21493,21494],{"class":252,"line":113},[250,21495,795],{"emptyLinePlaceholder":129},[250,21497,21498],{"class":252,"line":110},[250,21499,21500],{},"interface UpdateUserData {\n",[250,21502,21503],{"class":252,"line":269},[250,21504,21348],{},[250,21506,21507],{"class":252,"line":275},[250,21508,21353],{},[250,21510,21511],{"class":252,"line":281},[250,21512,991],{},[250,21514,21515],{"class":252,"line":287},[250,21516,795],{"emptyLinePlaceholder":129},[250,21518,21519],{"class":252,"line":293},[250,21520,21521],{},"function UpdateUserForm({ userId }: { userId: string }) {\n",[250,21523,21524],{"class":252,"line":299},[250,21525,21526],{},"  const queryClient = useQueryClient();\n",[250,21528,21529],{"class":252,"line":132},[250,21530,795],{"emptyLinePlaceholder":129},[250,21532,21533],{"class":252,"line":310},[250,21534,21535],{},"  const mutation = useMutation({\n",[250,21537,21538],{"class":252,"line":316},[250,21539,21540],{},"    mutationFn: (userData: UpdateUserData) =>\n",[250,21542,21543],{"class":252,"line":322},[250,21544,21545],{},"      fetch(`\u002Fapi\u002Fusers\u002F${userId}`, {\n",[250,21547,21548],{"class":252,"line":328},[250,21549,21550],{},"        method: 'PUT',\n",[250,21552,21553],{"class":252,"line":334},[250,21554,21555],{},"        body: JSON.stringify(userData),\n",[250,21557,21558],{"class":252,"line":340},[250,21559,21560],{},"        headers: { 'Content-Type': 'application\u002Fjson' },\n",[250,21562,21563],{"class":252,"line":346},[250,21564,21565],{},"      }),\n",[250,21567,21568],{"class":252,"line":352},[250,21569,21570],{},"    onSuccess: () => {\n",[250,21572,21573],{"class":252,"line":358},[250,21574,21575],{},"      \u002F\u002F Invalidate and refetch user data\n",[250,21577,21578],{"class":252,"line":364},[250,21579,21580],{},"      queryClient.invalidateQueries({ queryKey: ['user', userId] });\n",[250,21582,21583],{"class":252,"line":370},[250,21584,14039],{},[250,21586,21587],{"class":252,"line":376},[250,21588,6749],{},[250,21590,21591],{"class":252,"line":382},[250,21592,795],{"emptyLinePlaceholder":129},[250,21594,21595],{"class":252,"line":388},[250,21596,21597],{},"  const handleSubmit = (data: UpdateUserData) => {\n",[250,21599,21600],{"class":252,"line":393},[250,21601,21602],{},"    mutation.mutate(data);\n",[250,21604,21605],{"class":252,"line":399},[250,21606,1161],{},[250,21608,21609],{"class":252,"line":405},[250,21610,795],{"emptyLinePlaceholder":129},[250,21612,21613],{"class":252,"line":410},[250,21614,21288],{},[250,21616,21617],{"class":252,"line":415},[250,21618,21619],{},"    \u003Cform onSubmit={(e) => {\n",[250,21621,21622],{"class":252,"line":420},[250,21623,21624],{},"      e.preventDefault();\n",[250,21626,21627],{"class":252,"line":426},[250,21628,21629],{},"      \u002F\u002F Form handling logic\n",[250,21631,21632],{"class":252,"line":431},[250,21633,21634],{},"    }}>\n",[250,21636,21637],{"class":252,"line":436},[250,21638,21639],{},"      {mutation.isPending && \u003Cp>Updating...\u003C\u002Fp>}\n",[250,21641,21642],{"class":252,"line":442},[250,21643,21644],{},"      {mutation.isError && \u003Cp>Error updating user\u003C\u002Fp>}\n",[250,21646,21647],{"class":252,"line":447},[250,21648,21649],{},"      {mutation.isSuccess && \u003Cp>User updated successfully!\u003C\u002Fp>}\n",[250,21651,21652],{"class":252,"line":453},[250,21653,21654],{},"      {\u002F* Form fields *\u002F}\n",[250,21656,21657],{"class":252,"line":459},[250,21658,21659],{},"    \u003C\u002Fform>\n",[250,21661,21662],{"class":252,"line":465},[250,21663,2859],{},[250,21665,21666],{"class":252,"line":471},[250,21667,991],{},[31,21669,21671],{"id":21670},"optimistic-updates","Optimistic Updates",[20,21673,21674],{},"Optimistic updates provide instant feedback by updating the UI before the server responds:",[47,21676,21679],{"className":20349,"code":21677,"filename":21678,"language":20351,"meta":55,"style":55},"const mutation = useMutation({\n  mutationFn: updateTodo,\n  onMutate: async (newTodo) => {\n    \u002F\u002F Cancel outgoing refetches\n    await queryClient.cancelQueries({ queryKey: ['todos'] });\n\n    \u002F\u002F Snapshot the previous value\n    const previousTodos = queryClient.getQueryData(['todos']);\n\n    \u002F\u002F Optimistically update\n    queryClient.setQueryData(['todos'], (old: Todo[]) => [...old, newTodo]);\n\n    \u002F\u002F Return context with the snapshot\n    return { previousTodos };\n  },\n  onError: (err, newTodo, context) => {\n    \u002F\u002F Rollback on error\n    queryClient.setQueryData(['todos'], context?.previousTodos);\n  },\n  onSettled: () => {\n    \u002F\u002F Refetch after error or success\n    queryClient.invalidateQueries({ queryKey: ['todos'] });\n  },\n});\n","OptimisticUpdate.tsx",[39,21680,21681,21686,21691,21696,21701,21706,21710,21715,21720,21724,21729,21734,21738,21743,21748,21752,21757,21762,21767,21771,21776,21781,21786,21790],{"__ignoreMap":55},[250,21682,21683],{"class":252,"line":253},[250,21684,21685],{},"const mutation = useMutation({\n",[250,21687,21688],{"class":252,"line":113},[250,21689,21690],{},"  mutationFn: updateTodo,\n",[250,21692,21693],{"class":252,"line":110},[250,21694,21695],{},"  onMutate: async (newTodo) => {\n",[250,21697,21698],{"class":252,"line":269},[250,21699,21700],{},"    \u002F\u002F Cancel outgoing refetches\n",[250,21702,21703],{"class":252,"line":275},[250,21704,21705],{},"    await queryClient.cancelQueries({ queryKey: ['todos'] });\n",[250,21707,21708],{"class":252,"line":281},[250,21709,795],{"emptyLinePlaceholder":129},[250,21711,21712],{"class":252,"line":287},[250,21713,21714],{},"    \u002F\u002F Snapshot the previous value\n",[250,21716,21717],{"class":252,"line":293},[250,21718,21719],{},"    const previousTodos = queryClient.getQueryData(['todos']);\n",[250,21721,21722],{"class":252,"line":299},[250,21723,795],{"emptyLinePlaceholder":129},[250,21725,21726],{"class":252,"line":132},[250,21727,21728],{},"    \u002F\u002F Optimistically update\n",[250,21730,21731],{"class":252,"line":310},[250,21732,21733],{},"    queryClient.setQueryData(['todos'], (old: Todo[]) => [...old, newTodo]);\n",[250,21735,21736],{"class":252,"line":316},[250,21737,795],{"emptyLinePlaceholder":129},[250,21739,21740],{"class":252,"line":322},[250,21741,21742],{},"    \u002F\u002F Return context with the snapshot\n",[250,21744,21745],{"class":252,"line":328},[250,21746,21747],{},"    return { previousTodos };\n",[250,21749,21750],{"class":252,"line":334},[250,21751,1048],{},[250,21753,21754],{"class":252,"line":340},[250,21755,21756],{},"  onError: (err, newTodo, context) => {\n",[250,21758,21759],{"class":252,"line":346},[250,21760,21761],{},"    \u002F\u002F Rollback on error\n",[250,21763,21764],{"class":252,"line":352},[250,21765,21766],{},"    queryClient.setQueryData(['todos'], context?.previousTodos);\n",[250,21768,21769],{"class":252,"line":358},[250,21770,1048],{},[250,21772,21773],{"class":252,"line":364},[250,21774,21775],{},"  onSettled: () => {\n",[250,21777,21778],{"class":252,"line":370},[250,21779,21780],{},"    \u002F\u002F Refetch after error or success\n",[250,21782,21783],{"class":252,"line":376},[250,21784,21785],{},"    queryClient.invalidateQueries({ queryKey: ['todos'] });\n",[250,21787,21788],{"class":252,"line":382},[250,21789,1048],{},[250,21791,21792],{"class":252,"line":388},[250,21793,1077],{},[10834,21795,21796,21800],{},[2459,21797,21799],{"id":21798},"performance-benefits","Performance Benefits",[20,21801,21802],{},"Optimistic updates can make your application feel up to 10x faster by eliminating the perceived latency of server responses.",[31,21804,21806],{"id":21805},"pagination","Pagination",[20,21808,21809],{},"TanStack Query makes pagination simple with built-in support:",[47,21811,21814],{"className":20349,"code":21812,"filename":21813,"language":20351,"meta":55,"style":55},"function PaginatedPosts() {\n  const [page, setPage] = useState(1);\n\n  const { data, isLoading, isPlaceholderData } = useQuery({\n    queryKey: ['posts', page],\n    queryFn: () => fetchPosts(page),\n    placeholderData: (previousData) => previousData,\n  });\n\n  return (\n    \u003Cdiv>\n      {data?.posts.map(post => \u003CPostCard key={post.id} post={post} \u002F>)}\n      \n      \u003Cbutton\n        onClick={() => setPage(old => Math.max(old - 1, 1))}\n        disabled={page === 1}\n      >\n        Previous\n      \u003C\u002Fbutton>\n      \n      \u003Cbutton\n        onClick={() => setPage(old => old + 1)}\n        disabled={isPlaceholderData || !data?.hasMore}\n      >\n        Next\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n}\n","PaginatedList.tsx",[39,21815,21816,21821,21826,21830,21835,21840,21845,21850,21854,21858,21862,21866,21871,21875,21880,21885,21890,21895,21900,21905,21909,21913,21918,21923,21927,21932,21936,21940,21944],{"__ignoreMap":55},[250,21817,21818],{"class":252,"line":253},[250,21819,21820],{},"function PaginatedPosts() {\n",[250,21822,21823],{"class":252,"line":113},[250,21824,21825],{},"  const [page, setPage] = useState(1);\n",[250,21827,21828],{"class":252,"line":110},[250,21829,795],{"emptyLinePlaceholder":129},[250,21831,21832],{"class":252,"line":269},[250,21833,21834],{},"  const { data, isLoading, isPlaceholderData } = useQuery({\n",[250,21836,21837],{"class":252,"line":275},[250,21838,21839],{},"    queryKey: ['posts', page],\n",[250,21841,21842],{"class":252,"line":281},[250,21843,21844],{},"    queryFn: () => fetchPosts(page),\n",[250,21846,21847],{"class":252,"line":287},[250,21848,21849],{},"    placeholderData: (previousData) => previousData,\n",[250,21851,21852],{"class":252,"line":293},[250,21853,6749],{},[250,21855,21856],{"class":252,"line":299},[250,21857,795],{"emptyLinePlaceholder":129},[250,21859,21860],{"class":252,"line":132},[250,21861,21288],{},[250,21863,21864],{"class":252,"line":310},[250,21865,21440],{},[250,21867,21868],{"class":252,"line":316},[250,21869,21870],{},"      {data?.posts.map(post => \u003CPostCard key={post.id} post={post} \u002F>)}\n",[250,21872,21873],{"class":252,"line":322},[250,21874,17061],{},[250,21876,21877],{"class":252,"line":328},[250,21878,21879],{},"      \u003Cbutton\n",[250,21881,21882],{"class":252,"line":334},[250,21883,21884],{},"        onClick={() => setPage(old => Math.max(old - 1, 1))}\n",[250,21886,21887],{"class":252,"line":340},[250,21888,21889],{},"        disabled={page === 1}\n",[250,21891,21892],{"class":252,"line":346},[250,21893,21894],{},"      >\n",[250,21896,21897],{"class":252,"line":352},[250,21898,21899],{},"        Previous\n",[250,21901,21902],{"class":252,"line":358},[250,21903,21904],{},"      \u003C\u002Fbutton>\n",[250,21906,21907],{"class":252,"line":364},[250,21908,17061],{},[250,21910,21911],{"class":252,"line":370},[250,21912,21879],{},[250,21914,21915],{"class":252,"line":376},[250,21916,21917],{},"        onClick={() => setPage(old => old + 1)}\n",[250,21919,21920],{"class":252,"line":382},[250,21921,21922],{},"        disabled={isPlaceholderData || !data?.hasMore}\n",[250,21924,21925],{"class":252,"line":388},[250,21926,21894],{},[250,21928,21929],{"class":252,"line":393},[250,21930,21931],{},"        Next\n",[250,21933,21934],{"class":252,"line":399},[250,21935,21904],{},[250,21937,21938],{"class":252,"line":405},[250,21939,21455],{},[250,21941,21942],{"class":252,"line":410},[250,21943,2859],{},[250,21945,21946],{"class":252,"line":415},[250,21947,991],{},[15,21949,12925],{"id":12924},[24,21951,21952],{"type":26},[20,21953,21954],{},"Always provide appropriate staleTime and gcTime values based on your data's characteristics. Not all data needs real-time updates!",[31,21956,21958],{"id":21957},"configure-cache-times-appropriately","Configure Cache Times Appropriately",[47,21960,21963],{"className":20349,"code":21961,"filename":21962,"language":20351,"meta":55,"style":55},"const queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: 1000 * 60 * 5, \u002F\u002F 5 minutes\n      gcTime: 1000 * 60 * 10, \u002F\u002F 10 minutes (formerly cacheTime)\n      retry: 3,\n      refetchOnWindowFocus: true,\n    },\n  },\n});\n","queryClient.ts",[39,21964,21965,21970,21975,21980,21985,21990,21995,22000,22004,22008],{"__ignoreMap":55},[250,21966,21967],{"class":252,"line":253},[250,21968,21969],{},"const queryClient = new QueryClient({\n",[250,21971,21972],{"class":252,"line":113},[250,21973,21974],{},"  defaultOptions: {\n",[250,21976,21977],{"class":252,"line":110},[250,21978,21979],{},"    queries: {\n",[250,21981,21982],{"class":252,"line":269},[250,21983,21984],{},"      staleTime: 1000 * 60 * 5, \u002F\u002F 5 minutes\n",[250,21986,21987],{"class":252,"line":275},[250,21988,21989],{},"      gcTime: 1000 * 60 * 10, \u002F\u002F 10 minutes (formerly cacheTime)\n",[250,21991,21992],{"class":252,"line":281},[250,21993,21994],{},"      retry: 3,\n",[250,21996,21997],{"class":252,"line":287},[250,21998,21999],{},"      refetchOnWindowFocus: true,\n",[250,22001,22002],{"class":252,"line":293},[250,22003,14039],{},[250,22005,22006],{"class":252,"line":299},[250,22007,1048],{},[250,22009,22010],{"class":252,"line":132},[250,22011,1077],{},[31,22013,22015],{"id":22014},"use-query-keys-consistently","Use Query Keys Consistently",[20,22017,22018],{},"Establish a naming convention for your query keys:",[47,22020,22023],{"className":1010,"code":22021,"filename":22022,"language":1012,"meta":55,"style":55},"export const queryKeys = {\n  users: {\n    all: ['users'] as const,\n    detail: (id: string) => ['users', id] as const,\n    posts: (id: string) => ['users', id, 'posts'] as const,\n  },\n  posts: {\n    all: ['posts'] as const,\n    detail: (id: string) => ['posts', id] as const,\n  },\n};\n","queryKeys.ts",[39,22024,22025,22038,22043,22059,22090,22125,22129,22134,22148,22176,22180],{"__ignoreMap":55},[250,22026,22027,22029,22031,22034,22036],{"class":252,"line":253},[250,22028,1019],{"class":786},[250,22030,4438],{"class":786},[250,22032,22033],{"class":778}," queryKeys",[250,22035,1187],{"class":786},[250,22037,1118],{"class":912},[250,22039,22040],{"class":252,"line":113},[250,22041,22042],{"class":912},"  users: {\n",[250,22044,22045,22048,22050,22053,22055,22057],{"class":252,"line":110},[250,22046,22047],{"class":912},"    all: [",[250,22049,13154],{"class":782},[250,22051,22052],{"class":912},"] ",[250,22054,1472],{"class":786},[250,22056,4438],{"class":786},[250,22058,927],{"class":912},[250,22060,22061,22064,22067,22069,22071,22073,22075,22077,22079,22081,22084,22086,22088],{"class":252,"line":269},[250,22062,22063],{"class":774},"    detail",[250,22065,22066],{"class":912},": (",[250,22068,9727],{"class":1370},[250,22070,1007],{"class":786},[250,22072,2506],{"class":778},[250,22074,1446],{"class":912},[250,22076,1115],{"class":786},[250,22078,7123],{"class":912},[250,22080,13154],{"class":782},[250,22082,22083],{"class":912},", id] ",[250,22085,1472],{"class":786},[250,22087,4438],{"class":786},[250,22089,927],{"class":912},[250,22091,22092,22095,22097,22099,22101,22103,22105,22107,22109,22111,22114,22117,22119,22121,22123],{"class":252,"line":275},[250,22093,22094],{"class":774},"    posts",[250,22096,22066],{"class":912},[250,22098,9727],{"class":1370},[250,22100,1007],{"class":786},[250,22102,2506],{"class":778},[250,22104,1446],{"class":912},[250,22106,1115],{"class":786},[250,22108,7123],{"class":912},[250,22110,13154],{"class":782},[250,22112,22113],{"class":912},", id, ",[250,22115,22116],{"class":782},"'posts'",[250,22118,22052],{"class":912},[250,22120,1472],{"class":786},[250,22122,4438],{"class":786},[250,22124,927],{"class":912},[250,22126,22127],{"class":252,"line":281},[250,22128,1048],{"class":912},[250,22130,22131],{"class":252,"line":287},[250,22132,22133],{"class":912},"  posts: {\n",[250,22135,22136,22138,22140,22142,22144,22146],{"class":252,"line":293},[250,22137,22047],{"class":912},[250,22139,22116],{"class":782},[250,22141,22052],{"class":912},[250,22143,1472],{"class":786},[250,22145,4438],{"class":786},[250,22147,927],{"class":912},[250,22149,22150,22152,22154,22156,22158,22160,22162,22164,22166,22168,22170,22172,22174],{"class":252,"line":299},[250,22151,22063],{"class":774},[250,22153,22066],{"class":912},[250,22155,9727],{"class":1370},[250,22157,1007],{"class":786},[250,22159,2506],{"class":778},[250,22161,1446],{"class":912},[250,22163,1115],{"class":786},[250,22165,7123],{"class":912},[250,22167,22116],{"class":782},[250,22169,22083],{"class":912},[250,22171,1472],{"class":786},[250,22173,4438],{"class":786},[250,22175,927],{"class":912},[250,22177,22178],{"class":252,"line":132},[250,22179,1048],{"class":912},[250,22181,22182],{"class":252,"line":310},[250,22183,10945],{"class":912},[31,22185,22187],{"id":22186},"enable-devtools","Enable DevTools",[20,22189,22190],{},"TanStack Query comes with excellent developer tools:",[47,22192,22194],{"className":20349,"code":22193,"filename":21258,"language":20351,"meta":55,"style":55},"import { ReactQueryDevtools } from '@tanstack\u002Freact-query-devtools';\n\nfunction App() {\n  return (\n    \u003CQueryClientProvider client={queryClient}>\n      \u003CYourApp \u002F>\n      \u003CReactQueryDevtools initialIsOpen={false} \u002F>\n    \u003C\u002FQueryClientProvider>\n  );\n}\n",[39,22195,22196,22201,22205,22209,22213,22217,22221,22226,22230,22234],{"__ignoreMap":55},[250,22197,22198],{"class":252,"line":253},[250,22199,22200],{},"import { ReactQueryDevtools } from '@tanstack\u002Freact-query-devtools';\n",[250,22202,22203],{"class":252,"line":113},[250,22204,795],{"emptyLinePlaceholder":129},[250,22206,22207],{"class":252,"line":110},[250,22208,21283],{},[250,22210,22211],{"class":252,"line":269},[250,22212,21288],{},[250,22214,22215],{"class":252,"line":275},[250,22216,21293],{},[250,22218,22219],{"class":252,"line":281},[250,22220,21298],{},[250,22222,22223],{"class":252,"line":287},[250,22224,22225],{},"      \u003CReactQueryDevtools initialIsOpen={false} \u002F>\n",[250,22227,22228],{"class":252,"line":293},[250,22229,21303],{},[250,22231,22232],{"class":252,"line":299},[250,22233,2859],{},[250,22235,22236],{"class":252,"line":132},[250,22237,991],{},[161,22239,22241],{"icon":7846,"title":22240},"DevTools Pro Tip",[20,22242,22243],{},"The DevTools panel provides real-time insights into your queries, their states, and cached data. It's invaluable for debugging and understanding how TanStack Query manages your data.",[15,22245,22247],{"id":22246},"common-patterns","Common Patterns",[31,22249,22251],{"id":22250},"dependent-queries","Dependent Queries",[20,22253,22254],{},"Sometimes you need to fetch data based on previous query results:",[47,22256,22259],{"className":20349,"code":22257,"filename":22258,"language":20351,"meta":55,"style":55},"function UserPosts({ userId }: { userId: string }) {\n  const { data: user } = useQuery({\n    queryKey: ['user', userId],\n    queryFn: () => fetchUser(userId),\n  });\n\n  const { data: posts } = useQuery({\n    queryKey: ['posts', user?.id],\n    queryFn: () => fetchUserPosts(user!.id),\n    enabled: !!user, \u002F\u002F Only run when user is available\n  });\n\n  return \u003CPostsList posts={posts} \u002F>;\n}\n","DependentQueries.tsx",[39,22260,22261,22266,22271,22275,22279,22283,22287,22292,22297,22302,22307,22311,22315,22320],{"__ignoreMap":55},[250,22262,22263],{"class":252,"line":253},[250,22264,22265],{},"function UserPosts({ userId }: { userId: string }) {\n",[250,22267,22268],{"class":252,"line":113},[250,22269,22270],{},"  const { data: user } = useQuery({\n",[250,22272,22273],{"class":252,"line":110},[250,22274,21404],{},[250,22276,22277],{"class":252,"line":269},[250,22278,21409],{},[250,22280,22281],{"class":252,"line":275},[250,22282,6749],{},[250,22284,22285],{"class":252,"line":281},[250,22286,795],{"emptyLinePlaceholder":129},[250,22288,22289],{"class":252,"line":287},[250,22290,22291],{},"  const { data: posts } = useQuery({\n",[250,22293,22294],{"class":252,"line":293},[250,22295,22296],{},"    queryKey: ['posts', user?.id],\n",[250,22298,22299],{"class":252,"line":299},[250,22300,22301],{},"    queryFn: () => fetchUserPosts(user!.id),\n",[250,22303,22304],{"class":252,"line":132},[250,22305,22306],{},"    enabled: !!user, \u002F\u002F Only run when user is available\n",[250,22308,22309],{"class":252,"line":310},[250,22310,6749],{},[250,22312,22313],{"class":252,"line":316},[250,22314,795],{"emptyLinePlaceholder":129},[250,22316,22317],{"class":252,"line":322},[250,22318,22319],{},"  return \u003CPostsList posts={posts} \u002F>;\n",[250,22321,22322],{"class":252,"line":328},[250,22323,991],{},[31,22325,21201],{"id":22326},"prefetching",[20,22328,22329],{},"Improve perceived performance by prefetching data:",[47,22331,22334],{"className":20349,"code":22332,"filename":22333,"language":20351,"meta":55,"style":55},"function PostList() {\n  const queryClient = useQueryClient();\n\n  const { data: posts } = useQuery({\n    queryKey: ['posts'],\n    queryFn: fetchPosts,\n  });\n\n  const handleMouseEnter = (postId: string) => {\n    queryClient.prefetchQuery({\n      queryKey: ['post', postId],\n      queryFn: () => fetchPost(postId),\n    });\n  };\n\n  return (\n    \u003Cdiv>\n      {posts?.map(post => (\n        \u003Cdiv \n          key={post.id}\n          onMouseEnter={() => handleMouseEnter(post.id)}\n        >\n          \u003CLink to={`\u002Fposts\u002F${post.id}`}>{post.title}\u003C\u002FLink>\n        \u003C\u002Fdiv>\n      ))}\n    \u003C\u002Fdiv>\n  );\n}\n","Prefetching.tsx",[39,22335,22336,22341,22345,22349,22353,22358,22363,22367,22371,22376,22381,22386,22391,22395,22399,22403,22407,22411,22416,22421,22426,22431,22436,22441,22446,22451,22455,22459],{"__ignoreMap":55},[250,22337,22338],{"class":252,"line":253},[250,22339,22340],{},"function PostList() {\n",[250,22342,22343],{"class":252,"line":113},[250,22344,21526],{},[250,22346,22347],{"class":252,"line":110},[250,22348,795],{"emptyLinePlaceholder":129},[250,22350,22351],{"class":252,"line":269},[250,22352,22291],{},[250,22354,22355],{"class":252,"line":275},[250,22356,22357],{},"    queryKey: ['posts'],\n",[250,22359,22360],{"class":252,"line":281},[250,22361,22362],{},"    queryFn: fetchPosts,\n",[250,22364,22365],{"class":252,"line":287},[250,22366,6749],{},[250,22368,22369],{"class":252,"line":293},[250,22370,795],{"emptyLinePlaceholder":129},[250,22372,22373],{"class":252,"line":299},[250,22374,22375],{},"  const handleMouseEnter = (postId: string) => {\n",[250,22377,22378],{"class":252,"line":132},[250,22379,22380],{},"    queryClient.prefetchQuery({\n",[250,22382,22383],{"class":252,"line":310},[250,22384,22385],{},"      queryKey: ['post', postId],\n",[250,22387,22388],{"class":252,"line":316},[250,22389,22390],{},"      queryFn: () => fetchPost(postId),\n",[250,22392,22393],{"class":252,"line":322},[250,22394,1547],{},[250,22396,22397],{"class":252,"line":328},[250,22398,1161],{},[250,22400,22401],{"class":252,"line":334},[250,22402,795],{"emptyLinePlaceholder":129},[250,22404,22405],{"class":252,"line":340},[250,22406,21288],{},[250,22408,22409],{"class":252,"line":346},[250,22410,21440],{},[250,22412,22413],{"class":252,"line":352},[250,22414,22415],{},"      {posts?.map(post => (\n",[250,22417,22418],{"class":252,"line":358},[250,22419,22420],{},"        \u003Cdiv \n",[250,22422,22423],{"class":252,"line":364},[250,22424,22425],{},"          key={post.id}\n",[250,22427,22428],{"class":252,"line":370},[250,22429,22430],{},"          onMouseEnter={() => handleMouseEnter(post.id)}\n",[250,22432,22433],{"class":252,"line":376},[250,22434,22435],{},"        >\n",[250,22437,22438],{"class":252,"line":382},[250,22439,22440],{},"          \u003CLink to={`\u002Fposts\u002F${post.id}`}>{post.title}\u003C\u002FLink>\n",[250,22442,22443],{"class":252,"line":388},[250,22444,22445],{},"        \u003C\u002Fdiv>\n",[250,22447,22448],{"class":252,"line":393},[250,22449,22450],{},"      ))}\n",[250,22452,22453],{"class":252,"line":399},[250,22454,21455],{},[250,22456,22457],{"class":252,"line":405},[250,22458,2859],{},[250,22460,22461],{"class":252,"line":410},[250,22462,991],{},[72,22464],{},[15,22466,3352],{"id":3351},[20,22468,22469],{},"TanStack Query has fundamentally changed how developers approach data fetching and state management in modern applications. By providing intelligent caching, automatic background updates, and a simple yet powerful API, it eliminates much of the boilerplate code traditionally associated with server state management.",[20,22471,22472],{},"Whether you're building a small application or a large-scale enterprise system, TanStack Query's flexibility and performance optimizations make it an excellent choice. The library's active community, comprehensive documentation, and framework-agnostic approach ensure it will remain a valuable tool in your development arsenal.",[20,22474,22475],{},"Start small with basic queries and gradually adopt advanced features like optimistic updates and prefetching as your application grows. Your users will appreciate the snappier experience, and your team will benefit from cleaner, more maintainable code.",[20,22477,22478],{},"Happy querying!",[500,22480,22481],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .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 .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":110,"depth":110,"links":22483},[22484,22485,22486,22487,22488,22489,22492,22493,22494,22495,22496,22497],{"id":21160,"depth":113,"text":21161},{"id":21217,"depth":113,"text":21218},{"id":21250,"depth":113,"text":21251},{"id":21314,"depth":113,"text":21315},{"id":21476,"depth":113,"text":21477},{"id":21670,"depth":113,"text":21671,"children":22490},[22491],{"id":21798,"depth":110,"text":21799},{"id":21805,"depth":113,"text":21806},{"id":21957,"depth":113,"text":21958},{"id":22014,"depth":113,"text":22015},{"id":22186,"depth":113,"text":22187},{"id":22250,"depth":113,"text":22251},{"id":22326,"depth":113,"text":21201},"2026-02-05","Discover how TanStack Query revolutionizes data fetching in React applications with powerful caching, synchronization, and state management capabilities.",{"type":12,"value":22501},[22502,22504],[15,22503,541],{"id":540},[20,22505,21147],{},[22507,22508,22509,22510,22511,8234],"tanstack query","react query","data fetching","caching","react",{},"\u002Fblog\u002Ftanstack-query",{"title":21139,"description":22499},"blog\u002Ftanstack-query","otrAfik85HDuJo-p8O4tK0JRdsM8c8jGeuWVLKo6pxg",{"id":22518,"title":22519,"author":22520,"body":22521,"canonical":115,"categories":115,"date":12959,"description":23302,"excerpt":23303,"extension":118,"img":23323,"keywords":23324,"language":3510,"meta":23326,"navigation":129,"ogImage":115,"path":23327,"rating":275,"readTime":132,"seo":23328,"stem":23329,"tag":3515,"__hash__":23330},"blog\u002Fblog\u002Ftanstack-router.md","Mastering TanStack Router: Type-Safe Routing for Modern Web Apps",{"name":8,"img":10,"website":535},{"type":12,"value":22522,"toc":23285},[22523,22525,22528,22534,22545,22552,22554,22558,22561,22575,22578,22587,22594,22596,22600,22603,22620,22623,22637,22640,22642,22644,22647,22730,22733,22737,22740,22826,22829,22833,22836,22929,22933,22949,22952,22956,22959,23102,23104,23115,23119,23122,23126,23129,23163,23166,23177,23180,23184,23187,23193,23196,23207,23210,23214,23217,23230,23233,23236,23240,23243,23257,23260,23271,23273,23276,23279,23282],[15,22524,541],{"id":540},[20,22526,22527],{},"Routing has always been one of those “it works… until it doesn’t” parts of web development. As applications grow, routes become harder to reason about, parameters drift out of sync, and refactors turn into a game of whack-a-mole.",[20,22529,22530,22533],{},[546,22531,22532],{},"TanStack Router"," was created to solve exactly that problem.",[20,22535,22536,22537,22540,22541,22544],{},"Built with ",[546,22538,22539],{},"type safety first",", TanStack Router flips the traditional routing model on its head. Instead of hoping your routes, params, loaders, and links line up, the router ",[3587,22542,22543],{},"guarantees"," they do—at compile time.",[20,22546,22547,22548,22551],{},"In this post, we’ll explore ",[546,22549,22550],{},"what makes TanStack Router different",", why it matters, and how to use it effectively in real-world applications.",[15,22553,748],{"id":747},[31,22555,22557],{"id":22556},"why-routing-needed-a-rethink","Why Routing Needed a Rethink",[20,22559,22560],{},"Most routers share a few common pain points:",[561,22562,22563,22566,22569,22572],{},[564,22564,22565],{},"Route params are strings (until runtime)",[564,22567,22568],{},"Loaders and components drift apart",[564,22570,22571],{},"Refactors break links silently",[564,22573,22574],{},"Nested routing becomes fragile",[20,22576,22577],{},"These issues don’t show up on day one—but they absolutely show up at scale.",[24,22579,22580],{"type":631},[20,22581,22582,22583,22586],{},"TanStack Router treats routing as a ",[3587,22584,22585],{},"data problem",", not just a URL-matching problem.",[20,22588,22589,22590,22593],{},"Instead of defining routes and hoping everything connects correctly, TanStack Router builds a ",[546,22591,22592],{},"strongly-typed route tree"," that TypeScript understands end to end.",[72,22595],{},[31,22597,22599],{"id":22598},"core-philosophy-of-tanstack-router","Core Philosophy of TanStack Router",[20,22601,22602],{},"At its core, TanStack Router is built around three ideas:",[2922,22604,22605,22610,22615],{},[564,22606,22607],{},[546,22608,22609],{},"Type safety everywhere",[564,22611,22612],{},[546,22613,22614],{},"Colocation of route logic",[564,22616,22617],{},[546,22618,22619],{},"Data-first routing",[20,22621,22622],{},"This means:",[561,22624,22625,22628,22631,22634],{},[564,22626,22627],{},"Routes know their params",[564,22629,22630],{},"Loaders know their return types",[564,22632,22633],{},"Links know where they’re going",[564,22635,22636],{},"Components know what data they receive",[20,22638,22639],{},"No guessing. No runtime surprises.",[72,22641],{},[31,22643,21251],{"id":21250},[20,22645,22646],{},"Here’s a minimal example of defining a route.",[47,22648,22651],{"className":1010,"code":22649,"filename":22650,"language":1012,"meta":55,"style":55},"import { createRouter, createRootRoute } from '@tanstack\u002Freact-router'\n\nconst rootRoute = createRootRoute({\n  component: () => \u003COutlet \u002F>\n})\n\nexport const router = createRouter({\n  routeTree: rootRoute,\n})\n","router.ts",[39,22652,22653,22665,22669,22683,22701,22705,22709,22721,22726],{"__ignoreMap":55},[250,22654,22655,22657,22660,22662],{"class":252,"line":253},[250,22656,1763],{"class":786},[250,22658,22659],{"class":912}," { createRouter, createRootRoute } ",[250,22661,1769],{"class":786},[250,22663,22664],{"class":782}," '@tanstack\u002Freact-router'\n",[250,22666,22667],{"class":252,"line":113},[250,22668,795],{"emptyLinePlaceholder":129},[250,22670,22671,22673,22676,22678,22681],{"class":252,"line":110},[250,22672,1181],{"class":786},[250,22674,22675],{"class":778}," rootRoute",[250,22677,1187],{"class":786},[250,22679,22680],{"class":774}," createRootRoute",[250,22682,1028],{"class":912},[250,22684,22685,22688,22691,22693,22696,22699],{"class":252,"line":269},[250,22686,22687],{"class":774},"  component",[250,22689,22690],{"class":912},": () ",[250,22692,1115],{"class":786},[250,22694,22695],{"class":912}," \u003C",[250,22697,22698],{"class":774},"Outlet",[250,22700,17047],{"class":912},[250,22702,22703],{"class":252,"line":275},[250,22704,474],{"class":912},[250,22706,22707],{"class":252,"line":281},[250,22708,795],{"emptyLinePlaceholder":129},[250,22710,22711,22714,22716,22719],{"class":252,"line":287},[250,22712,22713],{"class":912},"export const router ",[250,22715,1416],{"class":786},[250,22717,22718],{"class":774}," createRouter",[250,22720,1028],{"class":912},[250,22722,22723],{"class":252,"line":293},[250,22724,22725],{"class":912},"  routeTree: rootRoute,\n",[250,22727,22728],{"class":252,"line":299},[250,22729,474],{"class":912},[20,22731,22732],{},"Already, TypeScript understands your route tree—even before adding child routes.",[31,22734,22736],{"id":22735},"defining-routes-with-type-safety","Defining Routes with Type Safety",[20,22738,22739],{},"Now let’s define a real route.",[47,22741,22743],{"className":1010,"code":22742,"language":1012,"meta":55,"style":55},"import { createFileRoute } from '@tanstack\u002Freact-router'\n\nexport const Route = createFileRoute('\u002F')({\n  component: HomePage,\n})\n\nfunction HomePage() {\n  return \u003Ch1>Welcome Home\u003C\u002Fh1>\n}\n",[39,22744,22745,22756,22760,22782,22787,22791,22795,22805,22822],{"__ignoreMap":55},[250,22746,22747,22749,22752,22754],{"class":252,"line":253},[250,22748,1763],{"class":786},[250,22750,22751],{"class":912}," { createFileRoute } ",[250,22753,1769],{"class":786},[250,22755,22664],{"class":782},[250,22757,22758],{"class":252,"line":113},[250,22759,795],{"emptyLinePlaceholder":129},[250,22761,22762,22764,22766,22769,22771,22774,22776,22779],{"class":252,"line":110},[250,22763,1019],{"class":786},[250,22765,4438],{"class":786},[250,22767,22768],{"class":778}," Route",[250,22770,1187],{"class":786},[250,22772,22773],{"class":774}," createFileRoute",[250,22775,1434],{"class":912},[250,22777,22778],{"class":782},"'\u002F'",[250,22780,22781],{"class":912},")({\n",[250,22783,22784],{"class":252,"line":269},[250,22785,22786],{"class":912},"  component: HomePage,\n",[250,22788,22789],{"class":252,"line":275},[250,22790,474],{"class":912},[250,22792,22793],{"class":252,"line":281},[250,22794,795],{"emptyLinePlaceholder":129},[250,22796,22797,22800,22803],{"class":252,"line":287},[250,22798,22799],{"class":786},"function",[250,22801,22802],{"class":774}," HomePage",[250,22804,1851],{"class":912},[250,22806,22807,22809,22811,22813,22816,22818,22820],{"class":252,"line":293},[250,22808,1123],{"class":786},[250,22810,22695],{"class":912},[250,22812,15],{"class":774},[250,22814,22815],{"class":912},">Welcome Home",[250,22817,13209],{"class":786},[250,22819,15],{"class":912},[250,22821,13111],{"class":786},[250,22823,22824],{"class":252,"line":299},[250,22825,991],{"class":912},[20,22827,22828],{},"No string-based route definitions scattered across your app. The route is the source of truth.",[31,22830,22832],{"id":22831},"route-params-that-dont-lie","Route Params That Don’t Lie",[20,22834,22835],{},"Here’s where TanStack Router really shines.",[47,22837,22839],{"className":1010,"code":22838,"language":1012,"meta":55,"style":55},"export const Route = createFileRoute('\u002Fusers\u002F$userId')({\n  component: UserPage,\n})\n\nfunction UserPage() {\n  const { userId } = Route.useParams()\n  return \u003Cdiv>User ID: {userId}\u003C\u002Fdiv>\n}\n",[39,22840,22841,22860,22865,22869,22873,22882,22902,22925],{"__ignoreMap":55},[250,22842,22843,22845,22847,22849,22851,22853,22855,22858],{"class":252,"line":253},[250,22844,1019],{"class":786},[250,22846,4438],{"class":786},[250,22848,22768],{"class":778},[250,22850,1187],{"class":786},[250,22852,22773],{"class":774},[250,22854,1434],{"class":912},[250,22856,22857],{"class":782},"'\u002Fusers\u002F$userId'",[250,22859,22781],{"class":912},[250,22861,22862],{"class":252,"line":113},[250,22863,22864],{"class":912},"  component: UserPage,\n",[250,22866,22867],{"class":252,"line":110},[250,22868,474],{"class":912},[250,22870,22871],{"class":252,"line":269},[250,22872,795],{"emptyLinePlaceholder":129},[250,22874,22875,22877,22880],{"class":252,"line":275},[250,22876,22799],{"class":786},[250,22878,22879],{"class":774}," UserPage",[250,22881,1851],{"class":912},[250,22883,22884,22886,22888,22890,22892,22894,22897,22900],{"class":252,"line":281},[250,22885,1455],{"class":786},[250,22887,7768],{"class":912},[250,22889,14401],{"class":778},[250,22891,11640],{"class":912},[250,22893,1416],{"class":786},[250,22895,22896],{"class":912}," Route.",[250,22898,22899],{"class":774},"useParams",[250,22901,4861],{"class":912},[250,22903,22904,22906,22908,22910,22913,22916,22919,22921,22923],{"class":252,"line":287},[250,22905,1123],{"class":786},[250,22907,22695],{"class":912},[250,22909,16946],{"class":774},[250,22911,22912],{"class":912},">User ",[250,22914,22915],{"class":778},"ID",[250,22917,22918],{"class":912},": {userId}",[250,22920,13209],{"class":786},[250,22922,16946],{"class":912},[250,22924,13111],{"class":786},[250,22926,22927],{"class":252,"line":293},[250,22928,991],{"class":912},[2459,22930,22932],{"id":22931},"whats-different-here","What’s Different Here?",[561,22934,22935,22940,22943,22946],{},[564,22936,22937,22939],{},[39,22938,14401],{}," is typed",[564,22941,22942],{},"You can’t forget it",[564,22944,22945],{},"You can’t mistype it",[564,22947,22948],{},"You can’t pass the wrong param shape",[20,22950,22951],{},"TypeScript will stop you before the app runs.",[31,22953,22955],{"id":22954},"loaders-as-first-class-citizens","Loaders as First-Class Citizens",[20,22957,22958],{},"TanStack Router treats data loading as part of routing—not an afterthought.",[47,22960,22962],{"className":1010,"code":22961,"language":1012,"meta":55,"style":55},"export const Route = createFileRoute('\u002Fusers\u002F$userId')({\n  loader: async ({ params }) => {\n    return fetch(`\u002Fapi\u002Fusers\u002F${params.userId}`).then(res => res.json())\n  },\n  component: UserPage,\n})\n\nfunction UserPage() {\n  const user = Route.useLoaderData()\n  return \u003Cdiv>{user.name}\u003C\u002Fdiv>\n}\n",[39,22963,22964,22982,23003,23042,23046,23050,23054,23058,23066,23081,23098],{"__ignoreMap":55},[250,22965,22966,22968,22970,22972,22974,22976,22978,22980],{"class":252,"line":253},[250,22967,1019],{"class":786},[250,22969,4438],{"class":786},[250,22971,22768],{"class":778},[250,22973,1187],{"class":786},[250,22975,22773],{"class":774},[250,22977,1434],{"class":912},[250,22979,22857],{"class":782},[250,22981,22781],{"class":912},[250,22983,22984,22987,22989,22991,22994,22997,22999,23001],{"class":252,"line":113},[250,22985,22986],{"class":774},"  loader",[250,22988,921],{"class":912},[250,22990,1437],{"class":786},[250,22992,22993],{"class":912}," ({ ",[250,22995,22996],{"class":1370},"params",[250,22998,12305],{"class":912},[250,23000,1115],{"class":786},[250,23002,1118],{"class":912},[250,23004,23005,23007,23009,23011,23014,23016,23018,23020,23022,23024,23026,23028,23031,23034,23037,23039],{"class":252,"line":110},[250,23006,14581],{"class":786},[250,23008,2077],{"class":774},[250,23010,1434],{"class":912},[250,23012,23013],{"class":782},"`\u002Fapi\u002Fusers\u002F${",[250,23015,22996],{"class":912},[250,23017,2230],{"class":782},[250,23019,14401],{"class":912},[250,23021,2355],{"class":782},[250,23023,2380],{"class":912},[250,23025,2837],{"class":774},[250,23027,1434],{"class":912},[250,23029,23030],{"class":1370},"res",[250,23032,23033],{"class":786}," =>",[250,23035,23036],{"class":912}," res.",[250,23038,905],{"class":774},[250,23040,23041],{"class":912},"())\n",[250,23043,23044],{"class":252,"line":269},[250,23045,1048],{"class":912},[250,23047,23048],{"class":252,"line":275},[250,23049,22864],{"class":912},[250,23051,23052],{"class":252,"line":281},[250,23053,474],{"class":912},[250,23055,23056],{"class":252,"line":287},[250,23057,795],{"emptyLinePlaceholder":129},[250,23059,23060,23062,23064],{"class":252,"line":293},[250,23061,22799],{"class":786},[250,23063,22879],{"class":774},[250,23065,1851],{"class":912},[250,23067,23068,23070,23072,23074,23076,23079],{"class":252,"line":299},[250,23069,1455],{"class":786},[250,23071,14943],{"class":778},[250,23073,1187],{"class":786},[250,23075,22896],{"class":912},[250,23077,23078],{"class":774},"useLoaderData",[250,23080,4861],{"class":912},[250,23082,23083,23085,23087,23089,23092,23094,23096],{"class":252,"line":132},[250,23084,1123],{"class":786},[250,23086,22695],{"class":912},[250,23088,16946],{"class":774},[250,23090,23091],{"class":912},">{user.name}",[250,23093,13209],{"class":786},[250,23095,16946],{"class":912},[250,23097,13111],{"class":786},[250,23099,23100],{"class":252,"line":310},[250,23101,991],{"class":912},[2459,23103,12902],{"id":12901},[561,23105,23106,23109,23112],{},[564,23107,23108],{},"Loader data is typed",[564,23110,23111],{},"Components can’t access data that doesn’t exist",[564,23113,23114],{},"Refactors stay safe",[31,23116,23118],{"id":23117},"tanstack-router-tanstack-query","TanStack Router + TanStack Query",[20,23120,23121],{},"When paired with TanStack Query, loaders become even more powerful—combining caching, background refetching, and route awareness.",[31,23123,23125],{"id":23124},"navigation-without-fear","Navigation Without Fear",[20,23127,23128],{},"Links are another classic source of bugs. TanStack Router eliminates them.",[47,23130,23132],{"className":20349,"code":23131,"language":20351,"meta":55,"style":55},"\u003CLink\n  to=\"\u002Fusers\u002F$userId\"\n  params={{ userId: '42' }}\n>\n  View User\n\u003C\u002FLink>\n",[39,23133,23134,23139,23144,23149,23153,23158],{"__ignoreMap":55},[250,23135,23136],{"class":252,"line":253},[250,23137,23138],{},"\u003CLink\n",[250,23140,23141],{"class":252,"line":113},[250,23142,23143],{},"  to=\"\u002Fusers\u002F$userId\"\n",[250,23145,23146],{"class":252,"line":110},[250,23147,23148],{},"  params={{ userId: '42' }}\n",[250,23150,23151],{"class":252,"line":269},[250,23152,13111],{},[250,23154,23155],{"class":252,"line":275},[250,23156,23157],{},"  View User\n",[250,23159,23160],{"class":252,"line":281},[250,23161,23162],{},"\u003C\u002FLink>\n",[20,23164,23165],{},"If you:",[561,23167,23168,23171,23174],{},[564,23169,23170],{},"Forget a param ❌",[564,23172,23173],{},"Misspell a route ❌",[564,23175,23176],{},"Pass the wrong param type ❌",[20,23178,23179],{},"TypeScript catches it instantly.",[31,23181,23183],{"id":23182},"nested-routes-done-right","Nested Routes Done Right",[20,23185,23186],{},"Nested routing is simple, explicit, and predictable.",[47,23188,23191],{"className":23189,"code":23190,"language":52},[50],"\u002Fusers\n\u002Fusers\u002F$userId\n\u002Fusers\u002F$userId\u002Fsettings\n",[39,23192,23190],{"__ignoreMap":55},[20,23194,23195],{},"Each route:",[561,23197,23198,23201,23204],{},[564,23199,23200],{},"Knows its parent",[564,23202,23203],{},"Inherits context safely",[564,23205,23206],{},"Composes layouts naturally",[20,23208,23209],{},"No magic. No hidden behavior.",[31,23211,23213],{"id":23212},"how-tanstack-router-fits-modern-stacks","How TanStack Router Fits Modern Stacks",[20,23215,23216],{},"TanStack Router pairs especially well with:",[561,23218,23219,23222,23224,23227],{},[564,23220,23221],{},"TanStack Query",[564,23223,11130],{},[564,23225,23226],{},"Server-first architectures",[564,23228,23229],{},"Typed backends",[20,23231,23232],{},"If you care about refactoring confidence and long-term maintainability, TanStack Router pays for itself very quickly.",[20,23234,23235],{},"It’s not about being flashy—it’s about eliminating entire classes of bugs.",[31,23237,23239],{"id":23238},"when-should-you-use-tanstack-router","When Should You Use TanStack Router?",[20,23241,23242],{},"TanStack Router is ideal if:",[561,23244,23245,23248,23251,23254],{},[564,23246,23247],{},"You use TypeScript seriously",[564,23249,23250],{},"Your app has complex routing or data needs",[564,23252,23253],{},"You value refactor safety",[564,23255,23256],{},"You’re building long-lived applications",[20,23258,23259],{},"It might be overkill for:",[561,23261,23262,23265,23268],{},[564,23263,23264],{},"Tiny apps",[564,23266,23267],{},"One-page demos",[564,23269,23270],{},"Projects without TypeScript",[15,23272,3352],{"id":3351},[20,23274,23275],{},"TanStack Router isn’t just another router—it’s a rethinking of what routing should be in modern web applications. By embracing type safety, colocation, and data-first design, it gives developers something rare: confidence.",[20,23277,23278],{},"Confidence to refactor.\nConfidence to scale.\nConfidence that your routes won’t betray you at runtime.",[20,23280,23281],{},"If you’ve ever been burned by routing bugs, TanStack Router is absolutely worth your time.",[500,23283,23284],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":110,"depth":110,"links":23286},[23287,23288,23289,23290,23291,23294,23297,23298,23299,23300,23301],{"id":22556,"depth":113,"text":22557},{"id":22598,"depth":113,"text":22599},{"id":21250,"depth":113,"text":21251},{"id":22735,"depth":113,"text":22736},{"id":22831,"depth":113,"text":22832,"children":23292},[23293],{"id":22931,"depth":110,"text":22932},{"id":22954,"depth":113,"text":22955,"children":23295},[23296],{"id":12901,"depth":110,"text":12902},{"id":23117,"depth":113,"text":23118},{"id":23124,"depth":113,"text":23125},{"id":23182,"depth":113,"text":23183},{"id":23212,"depth":113,"text":23213},{"id":23238,"depth":113,"text":23239},"A deep dive into TanStack Router, exploring why type-safe routing matters, how it compares to traditional routers, and how to build scalable applications with confidence.",{"type":12,"value":23304},[23305,23307,23309,23313,23319],[15,23306,541],{"id":540},[20,23308,22527],{},[20,23310,23311,22533],{},[546,23312,22532],{},[20,23314,22536,23315,22540,23317,22544],{},[546,23316,22539],{},[3587,23318,22543],{},[20,23320,22547,23321,22551],{},[546,23322,22550],{},"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c",[11332,23325,8234,22511,10986],"tanstack router",{},"\u002Fblog\u002Ftanstack-router",{"title":22519,"description":23302},"blog\u002Ftanstack-router","PWnsv5PO_qkfN_djpIbv3v8k1z6BPhhRM9l-lLwmDVI",{"id":23332,"title":23333,"author":23334,"body":23335,"canonical":115,"categories":115,"date":24446,"description":24447,"excerpt":24448,"extension":118,"img":12028,"keywords":24464,"language":3510,"meta":24466,"navigation":129,"ogImage":115,"path":24467,"rating":275,"readTime":132,"seo":24468,"stem":24469,"tag":3515,"__hash__":24470},"blog\u002Fblog\u002Funjs-packages.md","Using Core UnJS Packages to Build a Modern JavaScript Application",{"name":8,"img":10,"website":535},{"type":12,"value":23336,"toc":24426},[23337,23339,23352,23359,23361,23368,23370,23374,23377,23383,23392,23395,23484,23493,23495,23502,23512,23569,23575,23577,23584,23593,23645,23651,23653,23660,23669,23672,23780,23786,23788,23795,23804,23874,23880,23882,23889,23892,23942,23948,23950,23960,23981,24058,24064,24066,24070,24073,24128,24131,24133,24137,24140,24388,24398,24400,24402,24416,24423],[15,23338,541],{"id":540},[20,23340,23341,23342,23345,23346,23349,23350],{},"The ",[546,23343,23344],{},"UnJS ecosystem"," is a large collection of focused, composable JavaScript utilities and tools created to empower developers with performant, agnostic building blocks. Instead of monolithic frameworks with opinionated APIs, UnJS packages are ",[546,23347,23348],{},"small, well-scoped, and interoperable"," — letting you pick exactly what you need for your app’s architecture and tooling. ",[3540,23351,3543],{"index":3542},[20,23353,23354,23355,23358],{},"In this post, we’ll focus on the ",[546,23356,23357],{},"main UnJS packages"," you’d use to build a real-world application and how they integrate together.",[15,23360,748],{"id":747},[24,23362,23363],{"type":631},[20,23364,23365,23366],{},"UnJS packages follow a Unix philosophy — each one does one thing well and can be composed with others to form a complete solution. ",[3540,23367,3570],{"index":1198},[72,23369],{},[31,23371,23373],{"id":23372},"key-unjs-packages-for-your-application","Key UnJS Packages for Your Application",[20,23375,23376],{},"Here’s a curated list of the most impactful UnJS packages you’ll likely use in a modern JavaScript\u002FTypeScript application:",[2459,23378,23380,23382],{"id":23379},"nitro-a-universal-server-engine",[546,23381,555],{}," — A Universal Server Engine",[20,23384,23385,23387,23388,23391],{},[39,23386,3504],{}," lets you build ",[546,23389,23390],{},"fast, portable servers"," that run on Node.js, Deno, Bun, Cloudflare Workers, and more.",[20,23393,23394],{},"Use Nitro to create API routes and server logic without worrying about runtime differences:",[47,23396,23400],{"className":23397,"code":23398,"language":23399,"meta":55,"style":55},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F server\u002Findex.ts\nimport { createNitro } from \"nitro\";\n\nexport default createNitro({\n  handlers: [\n    {\n      route: \"\u002Fapi\u002Fhello\",\n      handler: () => ({ message: \"Hello from Nitro!\" })\n    }\n  ]\n});\n","js",[39,23401,23402,23407,23421,23425,23436,23441,23446,23456,23472,23476,23480],{"__ignoreMap":55},[250,23403,23404],{"class":252,"line":253},[250,23405,23406],{"class":768},"\u002F\u002F server\u002Findex.ts\n",[250,23408,23409,23411,23414,23416,23419],{"class":252,"line":113},[250,23410,1763],{"class":786},[250,23412,23413],{"class":912}," { createNitro } ",[250,23415,1769],{"class":786},[250,23417,23418],{"class":782}," \"nitro\"",[250,23420,1379],{"class":912},[250,23422,23423],{"class":252,"line":110},[250,23424,795],{"emptyLinePlaceholder":129},[250,23426,23427,23429,23431,23434],{"class":252,"line":269},[250,23428,1019],{"class":786},[250,23430,1022],{"class":786},[250,23432,23433],{"class":774}," createNitro",[250,23435,1028],{"class":912},[250,23437,23438],{"class":252,"line":275},[250,23439,23440],{"class":912},"  handlers: [\n",[250,23442,23443],{"class":252,"line":281},[250,23444,23445],{"class":912},"    {\n",[250,23447,23448,23451,23454],{"class":252,"line":287},[250,23449,23450],{"class":912},"      route: ",[250,23452,23453],{"class":782},"\"\u002Fapi\u002Fhello\"",[250,23455,927],{"class":912},[250,23457,23458,23461,23463,23465,23468,23470],{"class":252,"line":293},[250,23459,23460],{"class":774},"      handler",[250,23462,22690],{"class":912},[250,23464,1115],{"class":786},[250,23466,23467],{"class":912}," ({ message: ",[250,23469,11562],{"class":782},[250,23471,4599],{"class":912},[250,23473,23474],{"class":252,"line":299},[250,23475,3684],{"class":912},[250,23477,23478],{"class":252,"line":132},[250,23479,19356],{"class":912},[250,23481,23482],{"class":252,"line":310},[250,23483,1077],{"class":912},[20,23485,23486,23487,2390],{},"Nitro becomes the backbone of your backend layer, powering APIs consistently across environments. (",[203,23488,23492],{"href":23489,"rel":23490,"title":23491},"https:\u002F\u002Funjs.io\u002Fpackages\u002F",[207],"Packages · UnJS","UnJS",[72,23494],{},[2459,23496,23498,23501],{"id":23497},"c12-smart-configuration-loader",[546,23499,23500],{},"c12"," — Smart Configuration Loader",[20,23503,23504,23506,23507,2390],{},[39,23505,23500],{}," simplifies loading configuration from multiple sources (JSON, JSONC, YAML, TOML, .env, RC files) and merges them intelligently. This is useful for environment configs, feature flags, and CLI apps. (",[203,23508,23492],{"href":23509,"rel":23510,"title":23511},"https:\u002F\u002Funjs.io\u002Fpackages\u002Fc12",[207],"c12 · Packages · UnJS",[47,23513,23515],{"className":1010,"code":23514,"language":1012,"meta":55,"style":55},"import { loadConfig } from \"c12\";\n\nconst { config } = await loadConfig({});\nconsole.log(\"App Config:\", config);\n",[39,23516,23517,23531,23535,23555],{"__ignoreMap":55},[250,23518,23519,23521,23524,23526,23529],{"class":252,"line":253},[250,23520,1763],{"class":786},[250,23522,23523],{"class":912}," { loadConfig } ",[250,23525,1769],{"class":786},[250,23527,23528],{"class":782}," \"c12\"",[250,23530,1379],{"class":912},[250,23532,23533],{"class":252,"line":113},[250,23534,795],{"emptyLinePlaceholder":129},[250,23536,23537,23539,23541,23543,23545,23547,23549,23552],{"class":252,"line":110},[250,23538,1181],{"class":786},[250,23540,7768],{"class":912},[250,23542,227],{"class":778},[250,23544,11640],{"class":912},[250,23546,1416],{"class":786},[250,23548,1463],{"class":786},[250,23550,23551],{"class":774}," loadConfig",[250,23553,23554],{"class":912},"({});\n",[250,23556,23557,23559,23561,23563,23566],{"class":252,"line":269},[250,23558,10954],{"class":912},[250,23560,1859],{"class":774},[250,23562,1434],{"class":912},[250,23564,23565],{"class":782},"\"App Config:\"",[250,23567,23568],{"class":912},", config);\n",[20,23570,23571,23572,2390],{},"It supports layering configs, environment overrides, and HMR during development — making config management a breeze. (",[203,23573,23492],{"href":23509,"rel":23574,"title":23511},[207],[72,23576],{},[2459,23578,23580,23583],{"id":23579},"ofetch-a-universal-fetch-api",[546,23581,23582],{},"ofetch"," — A Universal Fetch API",[20,23585,23586,23588,23589,23592],{},[39,23587,23582],{}," gives you a robust, cross-environment ",[39,23590,23591],{},"fetch"," API compatible with Node, browsers, and workers:",[47,23594,23596],{"className":1010,"code":23595,"language":1012,"meta":55,"style":55},"import { ofetch } from \"ofetch\";\n\nconst user = await ofetch(\"\u002Fapi\u002Fuser\");\nconsole.log(user);\n",[39,23597,23598,23612,23616,23636],{"__ignoreMap":55},[250,23599,23600,23602,23605,23607,23610],{"class":252,"line":253},[250,23601,1763],{"class":786},[250,23603,23604],{"class":912}," { ofetch } ",[250,23606,1769],{"class":786},[250,23608,23609],{"class":782}," \"ofetch\"",[250,23611,1379],{"class":912},[250,23613,23614],{"class":252,"line":113},[250,23615,795],{"emptyLinePlaceholder":129},[250,23617,23618,23620,23622,23624,23626,23629,23631,23634],{"class":252,"line":110},[250,23619,1181],{"class":786},[250,23621,14943],{"class":778},[250,23623,1187],{"class":786},[250,23625,1463],{"class":786},[250,23627,23628],{"class":774}," ofetch",[250,23630,1434],{"class":912},[250,23632,23633],{"class":782},"\"\u002Fapi\u002Fuser\"",[250,23635,1885],{"class":912},[250,23637,23638,23640,23642],{"class":252,"line":269},[250,23639,10954],{"class":912},[250,23641,1859],{"class":774},[250,23643,23644],{"class":912},"(user);\n",[20,23646,23647,23648,2390],{},"Use it in your client and server code without worrying about environment differences. (",[203,23649,23492],{"href":23489,"rel":23650,"title":23491},[207],[72,23652],{},[2459,23654,23656,23659],{"id":23655},"unplugin-plugin-system-across-bundlers",[546,23657,23658],{},"unplugin"," — Plugin System Across Bundlers",[20,23661,23662,23664,23665,23668],{},[39,23663,23658],{}," lets you write ",[546,23666,23667],{},"one plugin"," that works with Vite, Rollup, webpack, and esbuild — ideal for extending builds consistently.",[20,23670,23671],{},"For example, creating a custom import transform:",[47,23673,23675],{"className":23397,"code":23674,"language":23399,"meta":55,"style":55},"import Unplugin from \"unplugin\";\n\nexport default Unplugin(() => ({\n  name: \"example-plugin\",\n  transform(code) {\n    return code.replace(\u002FENV_VAR\u002Fg, JSON.stringify(process.env.NODE_ENV));\n  }\n}));\n",[39,23676,23677,23691,23695,23711,23720,23731,23771,23775],{"__ignoreMap":55},[250,23678,23679,23681,23684,23686,23689],{"class":252,"line":253},[250,23680,1763],{"class":786},[250,23682,23683],{"class":912}," Unplugin ",[250,23685,1769],{"class":786},[250,23687,23688],{"class":782}," \"unplugin\"",[250,23690,1379],{"class":912},[250,23692,23693],{"class":252,"line":113},[250,23694,795],{"emptyLinePlaceholder":129},[250,23696,23697,23699,23701,23704,23706,23708],{"class":252,"line":110},[250,23698,1019],{"class":786},[250,23700,1022],{"class":786},[250,23702,23703],{"class":774}," Unplugin",[250,23705,1112],{"class":912},[250,23707,1115],{"class":786},[250,23709,23710],{"class":912}," ({\n",[250,23712,23713,23715,23718],{"class":252,"line":269},[250,23714,4478],{"class":912},[250,23716,23717],{"class":782},"\"example-plugin\"",[250,23719,927],{"class":912},[250,23721,23722,23725,23727,23729],{"class":252,"line":275},[250,23723,23724],{"class":774},"  transform",[250,23726,1434],{"class":912},[250,23728,39],{"class":1370},[250,23730,1512],{"class":912},[250,23732,23733,23735,23738,23741,23743,23745,23749,23751,23754,23756,23759,23761,23764,23767,23769],{"class":252,"line":281},[250,23734,14581],{"class":786},[250,23736,23737],{"class":912}," code.",[250,23739,23740],{"class":774},"replace",[250,23742,1434],{"class":912},[250,23744,2293],{"class":782},[250,23746,23748],{"class":23747},"sA_wV","ENV_VAR",[250,23750,2293],{"class":782},[250,23752,23753],{"class":786},"g",[250,23755,7128],{"class":912},[250,23757,23758],{"class":778},"JSON",[250,23760,2230],{"class":912},[250,23762,23763],{"class":774},"stringify",[250,23765,23766],{"class":912},"(process.env.",[250,23768,15523],{"class":778},[250,23770,1593],{"class":912},[250,23772,23773],{"class":252,"line":287},[250,23774,986],{"class":912},[250,23776,23777],{"class":252,"line":293},[250,23778,23779],{"class":912},"}));\n",[20,23781,23782,23783,2390],{},"It’s data-agnostic and integrates with major build systems seamlessly. (",[203,23784,23492],{"href":23489,"rel":23785,"title":23491},[207],[72,23787],{},[2459,23789,23791,23794],{"id":23790},"jiti-runtime-typescript-and-esm-support",[546,23792,23793],{},"jiti"," — Runtime TypeScript and ESM Support",[20,23796,23797,23799,23800,23803],{},[39,23798,23793],{}," makes it easy to load ",[39,23801,23802],{},".ts"," modules at runtime without manual compilation:",[47,23805,23807],{"className":23397,"code":23806,"language":23399,"meta":55,"style":55},"import { createRequire } from \"module\";\nimport jiti from \"jiti\";\n\nconst requireTs = jiti(__filename);\nconst config = requireTs(\".\u002Fconfig.ts\").default;\n",[39,23808,23809,23823,23837,23841,23856],{"__ignoreMap":55},[250,23810,23811,23813,23816,23818,23821],{"class":252,"line":253},[250,23812,1763],{"class":786},[250,23814,23815],{"class":912}," { createRequire } ",[250,23817,1769],{"class":786},[250,23819,23820],{"class":782}," \"module\"",[250,23822,1379],{"class":912},[250,23824,23825,23827,23830,23832,23835],{"class":252,"line":113},[250,23826,1763],{"class":786},[250,23828,23829],{"class":912}," jiti ",[250,23831,1769],{"class":786},[250,23833,23834],{"class":782}," \"jiti\"",[250,23836,1379],{"class":912},[250,23838,23839],{"class":252,"line":110},[250,23840,795],{"emptyLinePlaceholder":129},[250,23842,23843,23845,23848,23850,23853],{"class":252,"line":269},[250,23844,1181],{"class":786},[250,23846,23847],{"class":778}," requireTs",[250,23849,1187],{"class":786},[250,23851,23852],{"class":774}," jiti",[250,23854,23855],{"class":912},"(__filename);\n",[250,23857,23858,23860,23862,23864,23866,23868,23871],{"class":252,"line":275},[250,23859,1181],{"class":786},[250,23861,8983],{"class":778},[250,23863,1187],{"class":786},[250,23865,23847],{"class":774},[250,23867,1434],{"class":912},[250,23869,23870],{"class":782},"\".\u002Fconfig.ts\"",[250,23872,23873],{"class":912},").default;\n",[20,23875,23876,23877,2390],{},"This is invaluable for quick prototyping, custom servers, and tooling that needs TypeScript support without build steps. (",[203,23878,23492],{"href":23489,"rel":23879,"title":23491},[207],[72,23881],{},[2459,23883,23885,23888],{"id":23884},"consola-elegant-console-logging",[546,23886,23887],{},"consola"," — Elegant Console Logging",[20,23890,23891],{},"A lightweight yet powerful wrapper around console logs with levels, formatting, and grouping:",[47,23893,23895],{"className":1010,"code":23894,"language":1012,"meta":55,"style":55},"import { consola } from \"consola\";\n\nconsola.info(\"Server started\");\nconsola.error(\"Unexpected error\");\n",[39,23896,23897,23911,23915,23929],{"__ignoreMap":55},[250,23898,23899,23901,23904,23906,23909],{"class":252,"line":253},[250,23900,1763],{"class":786},[250,23902,23903],{"class":912}," { consola } ",[250,23905,1769],{"class":786},[250,23907,23908],{"class":782}," \"consola\"",[250,23910,1379],{"class":912},[250,23912,23913],{"class":252,"line":113},[250,23914,795],{"emptyLinePlaceholder":129},[250,23916,23917,23920,23922,23924,23927],{"class":252,"line":110},[250,23918,23919],{"class":912},"consola.",[250,23921,631],{"class":774},[250,23923,1434],{"class":912},[250,23925,23926],{"class":782},"\"Server started\"",[250,23928,1885],{"class":912},[250,23930,23931,23933,23935,23937,23940],{"class":252,"line":269},[250,23932,23919],{"class":912},[250,23934,12297],{"class":774},[250,23936,1434],{"class":912},[250,23938,23939],{"class":782},"\"Unexpected error\"",[250,23941,1885],{"class":912},[20,23943,23944,23945,2390],{},"It improves readability of logs in production and development environments. (",[203,23946,23492],{"href":23489,"rel":23947,"title":23491},[207],[72,23949],{},[2459,23951,23953,20180,23956,23959],{"id":23952},"defu-and-destr-defaults-safe-parsing",[546,23954,23955],{},"defu",[546,23957,23958],{},"destr"," — Defaults & Safe Parsing",[561,23961,23962,23970],{},[564,23963,23964,23966,23967,2390],{},[39,23965,23955],{}," lets you merge objects with recursive defaults — perfect for configs. (",[203,23968,23492],{"href":23489,"rel":23969,"title":23491},[207],[564,23971,23972,23974,23975,3890,23978,2390],{},[39,23973,23958],{}," safely parses JSON with better performance and security than ",[39,23976,23977],{},"JSON.parse",[203,23979,23492],{"href":23489,"rel":23980,"title":23491},[207],[47,23982,23984],{"className":1010,"code":23983,"language":1012,"meta":55,"style":55},"import { defu } from \"defu\";\nimport { destr } from \"destr\";\n\nconst defaults = { port: 3000 };\nconst config = defu(destr(process.env.APP_CONFIG), defaults);\n",[39,23985,23986,24000,24014,24018,24035],{"__ignoreMap":55},[250,23987,23988,23990,23993,23995,23998],{"class":252,"line":253},[250,23989,1763],{"class":786},[250,23991,23992],{"class":912}," { defu } ",[250,23994,1769],{"class":786},[250,23996,23997],{"class":782}," \"defu\"",[250,23999,1379],{"class":912},[250,24001,24002,24004,24007,24009,24012],{"class":252,"line":113},[250,24003,1763],{"class":786},[250,24005,24006],{"class":912}," { destr } ",[250,24008,1769],{"class":786},[250,24010,24011],{"class":782}," \"destr\"",[250,24013,1379],{"class":912},[250,24015,24016],{"class":252,"line":110},[250,24017,795],{"emptyLinePlaceholder":129},[250,24019,24020,24022,24025,24027,24030,24033],{"class":252,"line":269},[250,24021,1181],{"class":786},[250,24023,24024],{"class":778}," defaults",[250,24026,1187],{"class":786},[250,24028,24029],{"class":912}," { port: ",[250,24031,24032],{"class":778},"3000",[250,24034,5784],{"class":912},[250,24036,24037,24039,24041,24043,24046,24048,24050,24052,24055],{"class":252,"line":275},[250,24038,1181],{"class":786},[250,24040,8983],{"class":778},[250,24042,1187],{"class":786},[250,24044,24045],{"class":774}," defu",[250,24047,1434],{"class":912},[250,24049,23958],{"class":774},[250,24051,23766],{"class":912},[250,24053,24054],{"class":778},"APP_CONFIG",[250,24056,24057],{"class":912},"), defaults);\n",[20,24059,24060,24061,24063],{},"These utilities pair well with ",[39,24062,23500],{}," for robust config and data handling.",[72,24065],{},[31,24067,24069],{"id":24068},"how-these-fit-together-in-a-real-app","How These Fit Together in a Real App",[20,24071,24072],{},"Let’s imagine building a minimal app with UnJS tools:",[2922,24074,24075,24083,24091,24099,24108,24116],{},[564,24076,24077,24079,24080,24082],{},[546,24078,18816],{}," – Use ",[39,24081,23500],{}," to load app configs, merging defaults and environment settings.",[564,24084,24085,24079,24088,24090],{},[546,24086,24087],{},"Server Setup",[39,24089,3504],{}," to define API endpoints and middleware.",[564,24092,24093,24079,24096,24098],{},[546,24094,24095],{},"Data Fetching",[39,24097,23582],{}," on both client-side and server-side for HTTP requests.",[564,24100,24101,24104,24105,24107],{},[546,24102,24103],{},"Build\u002FPlugin Support"," – Enhance the build pipeline with ",[39,24106,23658],{}," for consistent tooling across environments.",[564,24109,24110,24079,24113,24115],{},[546,24111,24112],{},"Runtime TypeScript",[39,24114,23793],{}," in scripts or custom tooling parts of the app.",[564,24117,24118,24079,24121,7128,24123,21086,24125,24127],{},[546,24119,24120],{},"Logging & Utilities",[39,24122,23887],{},[39,24124,23955],{},[39,24126,23958],{}," for reliable logging, defaults handling, and parsing.",[20,24129,24130],{},"Each UnJS package is independent and tree-shakeable. Only install what you need to keep your bundles lean.\n(::)",[72,24132],{},[31,24134,24136],{"id":24135},"code-example-putting-it-all-together","Code Example: Putting It All Together",[20,24138,24139],{},"Below is a simple example of a Nitro server with config loading and fetch utility:",[47,24141,24144],{"className":1010,"code":24142,"filename":24143,"language":1012,"meta":55,"style":55},"import { createNitro } from \"nitro\";\nimport { loadConfig } from \"c12\";\nimport { ofetch } from \"ofetch\";\nimport { consola } from \"consola\";\n\nconst { config } = await loadConfig({});\n\nexport default createNitro({\n  async handlers() {\n    return [\n      {\n        route: \"\u002Fapi\u002Fhello\",\n        handler: () => ({\n          message: \"Hello from UnJS App!\",\n          env: config.NODE_ENV\n        })\n      },\n      {\n        route: \"\u002Fapi\u002Fuser\",\n        handler: async () => {\n          const user = await ofetch(\"https:\u002F\u002Fjsonplaceholder.typicode.com\u002Fusers\u002F1\");\n          consola.info(\"Fetched user:\", user);\n          return user;\n        }\n      }\n    ];\n  }\n});\n","example.ts",[39,24145,24146,24158,24170,24182,24194,24198,24216,24220,24230,24240,24246,24251,24260,24271,24281,24289,24294,24298,24302,24310,24324,24344,24359,24367,24371,24375,24380,24384],{"__ignoreMap":55},[250,24147,24148,24150,24152,24154,24156],{"class":252,"line":253},[250,24149,1763],{"class":786},[250,24151,23413],{"class":912},[250,24153,1769],{"class":786},[250,24155,23418],{"class":782},[250,24157,1379],{"class":912},[250,24159,24160,24162,24164,24166,24168],{"class":252,"line":113},[250,24161,1763],{"class":786},[250,24163,23523],{"class":912},[250,24165,1769],{"class":786},[250,24167,23528],{"class":782},[250,24169,1379],{"class":912},[250,24171,24172,24174,24176,24178,24180],{"class":252,"line":110},[250,24173,1763],{"class":786},[250,24175,23604],{"class":912},[250,24177,1769],{"class":786},[250,24179,23609],{"class":782},[250,24181,1379],{"class":912},[250,24183,24184,24186,24188,24190,24192],{"class":252,"line":269},[250,24185,1763],{"class":786},[250,24187,23903],{"class":912},[250,24189,1769],{"class":786},[250,24191,23908],{"class":782},[250,24193,1379],{"class":912},[250,24195,24196],{"class":252,"line":275},[250,24197,795],{"emptyLinePlaceholder":129},[250,24199,24200,24202,24204,24206,24208,24210,24212,24214],{"class":252,"line":281},[250,24201,1181],{"class":786},[250,24203,7768],{"class":912},[250,24205,227],{"class":778},[250,24207,11640],{"class":912},[250,24209,1416],{"class":786},[250,24211,1463],{"class":786},[250,24213,23551],{"class":774},[250,24215,23554],{"class":912},[250,24217,24218],{"class":252,"line":287},[250,24219,795],{"emptyLinePlaceholder":129},[250,24221,24222,24224,24226,24228],{"class":252,"line":293},[250,24223,1019],{"class":786},[250,24225,1022],{"class":786},[250,24227,23433],{"class":774},[250,24229,1028],{"class":912},[250,24231,24232,24235,24238],{"class":252,"line":299},[250,24233,24234],{"class":786},"  async",[250,24236,24237],{"class":774}," handlers",[250,24239,1851],{"class":912},[250,24241,24242,24244],{"class":252,"line":132},[250,24243,14581],{"class":786},[250,24245,1190],{"class":912},[250,24247,24248],{"class":252,"line":310},[250,24249,24250],{"class":912},"      {\n",[250,24252,24253,24256,24258],{"class":252,"line":316},[250,24254,24255],{"class":912},"        route: ",[250,24257,23453],{"class":782},[250,24259,927],{"class":912},[250,24261,24262,24265,24267,24269],{"class":252,"line":322},[250,24263,24264],{"class":774},"        handler",[250,24266,22690],{"class":912},[250,24268,1115],{"class":786},[250,24270,23710],{"class":912},[250,24272,24273,24276,24279],{"class":252,"line":328},[250,24274,24275],{"class":912},"          message: ",[250,24277,24278],{"class":782},"\"Hello from UnJS App!\"",[250,24280,927],{"class":912},[250,24282,24283,24286],{"class":252,"line":334},[250,24284,24285],{"class":912},"          env: config.",[250,24287,24288],{"class":778},"NODE_ENV\n",[250,24290,24291],{"class":252,"line":340},[250,24292,24293],{"class":912},"        })\n",[250,24295,24296],{"class":252,"line":346},[250,24297,456],{"class":912},[250,24299,24300],{"class":252,"line":352},[250,24301,24250],{"class":912},[250,24303,24304,24306,24308],{"class":252,"line":358},[250,24305,24255],{"class":912},[250,24307,23633],{"class":782},[250,24309,927],{"class":912},[250,24311,24312,24314,24316,24318,24320,24322],{"class":252,"line":364},[250,24313,24264],{"class":774},[250,24315,921],{"class":912},[250,24317,1437],{"class":786},[250,24319,2015],{"class":912},[250,24321,1115],{"class":786},[250,24323,1118],{"class":912},[250,24325,24326,24329,24331,24333,24335,24337,24339,24342],{"class":252,"line":370},[250,24327,24328],{"class":786},"          const",[250,24330,14943],{"class":778},[250,24332,1187],{"class":786},[250,24334,1463],{"class":786},[250,24336,23628],{"class":774},[250,24338,1434],{"class":912},[250,24340,24341],{"class":782},"\"https:\u002F\u002Fjsonplaceholder.typicode.com\u002Fusers\u002F1\"",[250,24343,1885],{"class":912},[250,24345,24346,24349,24351,24353,24356],{"class":252,"line":376},[250,24347,24348],{"class":912},"          consola.",[250,24350,631],{"class":774},[250,24352,1434],{"class":912},[250,24354,24355],{"class":782},"\"Fetched user:\"",[250,24357,24358],{"class":912},", user);\n",[250,24360,24361,24364],{"class":252,"line":382},[250,24362,24363],{"class":786},"          return",[250,24365,24366],{"class":912}," user;\n",[250,24368,24369],{"class":252,"line":388},[250,24370,3875],{"class":912},[250,24372,24373],{"class":252,"line":393},[250,24374,10550],{"class":912},[250,24376,24377],{"class":252,"line":399},[250,24378,24379],{"class":912},"    ];\n",[250,24381,24382],{"class":252,"line":405},[250,24383,986],{"class":912},[250,24385,24386],{"class":252,"line":410},[250,24387,1077],{"class":912},[20,24389,24390,24391,24394,24395,2390],{},"This sample shows how ",[546,24392,24393],{},"Nitro, c12, ofetch, and consola"," can power a flexible, full-featured backend. (",[203,24396,23492],{"href":23489,"rel":24397,"title":23491},[207],[72,24399],{},[15,24401,3352],{"id":3351},[20,24403,23341,24404,24406,24407,24410,24411,2390],{},[546,24405,23344],{}," offers a rich — yet modular — toolkit for modern JavaScript applications. By adopting packages like ",[546,24408,24409],{},"Nitro, c12, ofetch, unplugin, jiti, consola, defu, and destr",", you can assemble a highly productive development environment while keeping your dependencies lean. (",[203,24412,23492],{"href":24413,"rel":24414,"title":24415},"https:\u002F\u002Funjs.io\u002F",[207],"UnJS: Unleash JavaScript's Potential",[20,24417,24418,24419,24422],{},"Whether you're building servers, tooling, or full-stack apps, UnJS packages empower you to choose ",[3587,24420,24421],{},"exactly the components you need"," — embracing composability and simplicity in equal measure. 🚀",[500,24424,24425],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":55,"searchDepth":110,"depth":110,"links":24427},[24428,24444,24445],{"id":23372,"depth":113,"text":23373,"children":24429},[24430,24432,24434,24436,24438,24440,24442],{"id":23379,"depth":110,"text":24431},"Nitro — A Universal Server Engine",{"id":23497,"depth":110,"text":24433},"c12 — Smart Configuration Loader",{"id":23579,"depth":110,"text":24435},"ofetch — A Universal Fetch API",{"id":23655,"depth":110,"text":24437},"unplugin — Plugin System Across Bundlers",{"id":23790,"depth":110,"text":24439},"jiti — Runtime TypeScript and ESM Support",{"id":23884,"depth":110,"text":24441},"consola — Elegant Console Logging",{"id":23952,"depth":110,"text":24443},"defu and destr — Defaults & Safe Parsing",{"id":24068,"depth":113,"text":24069},{"id":24135,"depth":113,"text":24136},"2026-01-12","Explore the main UnJS packages and learn how to use them together in a real-world application — from config loading and HTTP servers to fetch utilities and building tools.",{"type":12,"value":24449},[24450,24452,24460],[15,24451,541],{"id":540},[20,24453,23341,24454,23345,24456,23349,24458],{},[546,24455,23344],{},[546,24457,23348],{},[3540,24459,3543],{"index":3542},[20,24461,23354,24462,23358],{},[546,24463,23357],{},[10783,3504,23582,23658,24465,23500],"unstorage",{},"\u002Fblog\u002Funjs-packages",{"title":23333,"description":24447},"blog\u002Funjs-packages","vdCQko37SZVB8LKaQh1u-JLdHqeOhRnmKgH-aZdC6mA",{"id":24472,"title":24473,"author":24474,"body":24475,"canonical":115,"categories":115,"date":28128,"description":28129,"excerpt":28130,"extension":118,"img":28148,"keywords":28149,"language":3510,"meta":28155,"navigation":129,"ogImage":115,"path":28156,"rating":275,"readTime":132,"seo":28157,"stem":28158,"tag":3515,"__hash__":28159},"blog\u002Fblog\u002Fviteplus-teacher-toolkit-package.md","Building a Teacher's Grading Toolkit with Vite+",{"name":8,"img":10,"website":535},{"type":12,"value":24476,"toc":28120},[24477,24479,24482,24489,24504,24513,24517,24520,24552,24555,24559,24562,24584,24595,24598,24633,24637,24642,24842,24846,24850,25265,25269,25499,25502,25590,25594,25894,25898,26362,26366,26443,26447,26452,27333,27336,27348,27363,27367,27372,27460,27463,27477,27481,27493,27496,27526,27539,27543,27548,27724,27727,27739,27743,27746,27759,27972,27976,28046,28051,28063,28067,28099,28101,28111,28114,28117],[15,24478,541],{"id":540},[20,24480,24481],{},"Teachers spend hours every week calculating grades, curving scores, and converting percentages to letter grades. Most of this work happens in spreadsheets with fragile formulas that break the moment a student is added out of order.",[20,24483,24484,24485,24488],{},"What if we packaged those utilities as a reusable TypeScript library — something any teacher or school app developer could ",[39,24486,24487],{},"npm install"," and use?",[20,24490,24491,24492,24495,24496,24499,24500,24503],{},"In this post, we'll build ",[546,24493,24494],{},"teacher-toolkit"," — an npm package for grade calculations — using ",[546,24497,24498],{},"Vite+"," and its ",[39,24501,24502],{},"vp pack"," command. No Webpack config. No tsconfig gymnastics. Just code, test, and ship.",[24,24505,24506],{"type":631},[20,24507,24508,24509,24512],{},"This tutorial assumes you have Vite+ installed. If not, run ",[39,24510,24511],{},"curl -fsSL https:\u002F\u002Fvite.plus | bash"," and open a new terminal.",[15,24514,24516],{"id":24515},"what-were-building","What We're Building",[20,24518,24519],{},"A lightweight TypeScript library that provides:",[561,24521,24522,24528,24534,24540,24546],{},[564,24523,24524,24527],{},[546,24525,24526],{},"Letter grade conversion"," — percentage to A\u002FB\u002FC\u002FD\u002FF",[564,24529,24530,24533],{},[546,24531,24532],{},"Weighted grade calculation"," — combine homework, exams, participation",[564,24535,24536,24539],{},[546,24537,24538],{},"Score curving"," — boost grades based on class highest score",[564,24541,24542,24545],{},[546,24543,24544],{},"GPA conversion"," — letter grades to 4.0 scale",[564,24547,24548,24551],{},[546,24549,24550],{},"Class statistics"," — mean, median, standard deviation",[20,24553,24554],{},"All with full type safety and zero dependencies.",[15,24556,24558],{"id":24557},"step-1-scaffold-the-library","Step 1: Scaffold the Library",[20,24560,24561],{},"Vite+ has a built-in library template. Run:",[47,24563,24565],{"className":758,"code":24564,"language":761,"meta":55,"style":55},"vp create vite:library -- teacher-toolkit\n",[39,24566,24567],{"__ignoreMap":55},[250,24568,24569,24572,24575,24578,24581],{"class":252,"line":253},[250,24570,24571],{"class":774},"vp",[250,24573,24574],{"class":782}," create",[250,24576,24577],{"class":782}," vite:library",[250,24579,24580],{"class":778}," --",[250,24582,24583],{"class":782}," teacher-toolkit\n",[47,24585,24587],{"className":758,"code":24586,"language":761,"meta":55,"style":55},"vp install\n",[39,24588,24589],{"__ignoreMap":55},[250,24590,24591,24593],{"class":252,"line":253},[250,24592,24571],{"class":774},[250,24594,896],{"class":782},[20,24596,24597],{},"This gives us a project structure like:",[47,24599,24601],{"className":12725,"code":24600,"language":12727,"meta":55,"style":55},"teacher-toolkit\u002F\n  src\u002F\n    index.ts        # Entry point\n  vite.config.ts\n  package.json\n  tsconfig.json\n",[39,24602,24603,24608,24613,24618,24623,24628],{"__ignoreMap":55},[250,24604,24605],{"class":252,"line":253},[250,24606,24607],{},"teacher-toolkit\u002F\n",[250,24609,24610],{"class":252,"line":113},[250,24611,24612],{},"  src\u002F\n",[250,24614,24615],{"class":252,"line":110},[250,24616,24617],{},"    index.ts        # Entry point\n",[250,24619,24620],{"class":252,"line":269},[250,24621,24622],{},"  vite.config.ts\n",[250,24624,24625],{"class":252,"line":275},[250,24626,24627],{},"  package.json\n",[250,24629,24630],{"class":252,"line":281},[250,24631,24632],{},"  tsconfig.json\n",[15,24634,24636],{"id":24635},"step-2-define-the-types","Step 2: Define the Types",[20,24638,1092,24639,1007],{},[39,24640,24641],{},"src\u002Ftypes.ts",[47,24643,24645],{"className":1010,"code":24644,"filename":24641,"language":1012,"meta":55,"style":55},"export interface GradeScale {\n  letter: string;\n  min: number;\n  max: number;\n  gpa: number;\n}\n\nexport interface WeightedComponent {\n  name: string;\n  score: number;\n  weight: number;\n}\n\nexport interface ClassStats {\n  mean: number;\n  median: number;\n  stdDev: number;\n  highest: number;\n  lowest: number;\n  count: number;\n}\n",[39,24646,24647,24658,24669,24680,24691,24702,24706,24710,24721,24731,24742,24753,24757,24761,24772,24783,24794,24805,24816,24827,24838],{"__ignoreMap":55},[250,24648,24649,24651,24653,24656],{"class":252,"line":253},[250,24650,1019],{"class":786},[250,24652,8532],{"class":786},[250,24654,24655],{"class":774}," GradeScale",[250,24657,1118],{"class":912},[250,24659,24660,24663,24665,24667],{"class":252,"line":113},[250,24661,24662],{"class":1370},"  letter",[250,24664,1007],{"class":786},[250,24666,2506],{"class":778},[250,24668,1379],{"class":912},[250,24670,24671,24674,24676,24678],{"class":252,"line":110},[250,24672,24673],{"class":1370},"  min",[250,24675,1007],{"class":786},[250,24677,1376],{"class":778},[250,24679,1379],{"class":912},[250,24681,24682,24685,24687,24689],{"class":252,"line":269},[250,24683,24684],{"class":1370},"  max",[250,24686,1007],{"class":786},[250,24688,1376],{"class":778},[250,24690,1379],{"class":912},[250,24692,24693,24696,24698,24700],{"class":252,"line":275},[250,24694,24695],{"class":1370},"  gpa",[250,24697,1007],{"class":786},[250,24699,1376],{"class":778},[250,24701,1379],{"class":912},[250,24703,24704],{"class":252,"line":281},[250,24705,991],{"class":912},[250,24707,24708],{"class":252,"line":287},[250,24709,795],{"emptyLinePlaceholder":129},[250,24711,24712,24714,24716,24719],{"class":252,"line":293},[250,24713,1019],{"class":786},[250,24715,8532],{"class":786},[250,24717,24718],{"class":774}," WeightedComponent",[250,24720,1118],{"class":912},[250,24722,24723,24725,24727,24729],{"class":252,"line":299},[250,24724,2501],{"class":1370},[250,24726,1007],{"class":786},[250,24728,2506],{"class":778},[250,24730,1379],{"class":912},[250,24732,24733,24736,24738,24740],{"class":252,"line":132},[250,24734,24735],{"class":1370},"  score",[250,24737,1007],{"class":786},[250,24739,1376],{"class":778},[250,24741,1379],{"class":912},[250,24743,24744,24747,24749,24751],{"class":252,"line":310},[250,24745,24746],{"class":1370},"  weight",[250,24748,1007],{"class":786},[250,24750,1376],{"class":778},[250,24752,1379],{"class":912},[250,24754,24755],{"class":252,"line":316},[250,24756,991],{"class":912},[250,24758,24759],{"class":252,"line":322},[250,24760,795],{"emptyLinePlaceholder":129},[250,24762,24763,24765,24767,24770],{"class":252,"line":328},[250,24764,1019],{"class":786},[250,24766,8532],{"class":786},[250,24768,24769],{"class":774}," ClassStats",[250,24771,1118],{"class":912},[250,24773,24774,24777,24779,24781],{"class":252,"line":334},[250,24775,24776],{"class":1370},"  mean",[250,24778,1007],{"class":786},[250,24780,1376],{"class":778},[250,24782,1379],{"class":912},[250,24784,24785,24788,24790,24792],{"class":252,"line":340},[250,24786,24787],{"class":1370},"  median",[250,24789,1007],{"class":786},[250,24791,1376],{"class":778},[250,24793,1379],{"class":912},[250,24795,24796,24799,24801,24803],{"class":252,"line":346},[250,24797,24798],{"class":1370},"  stdDev",[250,24800,1007],{"class":786},[250,24802,1376],{"class":778},[250,24804,1379],{"class":912},[250,24806,24807,24810,24812,24814],{"class":252,"line":352},[250,24808,24809],{"class":1370},"  highest",[250,24811,1007],{"class":786},[250,24813,1376],{"class":778},[250,24815,1379],{"class":912},[250,24817,24818,24821,24823,24825],{"class":252,"line":358},[250,24819,24820],{"class":1370},"  lowest",[250,24822,1007],{"class":786},[250,24824,1376],{"class":778},[250,24826,1379],{"class":912},[250,24828,24829,24832,24834,24836],{"class":252,"line":364},[250,24830,24831],{"class":1370},"  count",[250,24833,1007],{"class":786},[250,24835,1376],{"class":778},[250,24837,1379],{"class":912},[250,24839,24840],{"class":252,"line":370},[250,24841,991],{"class":912},[15,24843,24845],{"id":24844},"step-3-build-the-core-utilities","Step 3: Build the Core Utilities",[31,24847,24849],{"id":24848},"letter-grade-conversion","Letter Grade Conversion",[47,24851,24854],{"className":1010,"code":24852,"filename":24853,"language":1012,"meta":55,"style":55},"import type { GradeScale } from '.\u002Ftypes';\n\nconst DEFAULT_SCALE: GradeScale[] = [\n  { letter: 'A', min: 90, max: 100, gpa: 4.0 },\n  { letter: 'B', min: 80, max: 89, gpa: 3.0 },\n  { letter: 'C', min: 70, max: 79, gpa: 2.0 },\n  { letter: 'D', min: 60, max: 69, gpa: 1.0 },\n  { letter: 'F', min: 0, max: 59, gpa: 0.0 },\n];\n\nexport function toLetterGrade(\n  percentage: number,\n  scale: GradeScale[] = DEFAULT_SCALE\n): string {\n  const clamped = Math.max(0, Math.min(100, percentage));\n  const match = scale.find(s => clamped >= s.min && clamped \u003C= s.max);\n  return match?.letter ?? 'F';\n}\n\nexport function toGPA(\n  percentage: number,\n  scale: GradeScale[] = DEFAULT_SCALE\n): number {\n  const letter = toLetterGrade(percentage, scale);\n  const match = scale.find(s => s.letter === letter);\n  return match?.gpa ?? 0;\n}\n","src\u002Fgrades.ts",[39,24855,24856,24872,24876,24893,24919,24942,24966,24989,25012,25016,25020,25031,25042,25058,25068,25099,25139,25154,25158,25162,25173,25183,25197,25207,25221,25248,25261],{"__ignoreMap":55},[250,24857,24858,24860,24862,24865,24867,24870],{"class":252,"line":253},[250,24859,1763],{"class":786},[250,24861,4974],{"class":786},[250,24863,24864],{"class":912}," { GradeScale } ",[250,24866,1769],{"class":786},[250,24868,24869],{"class":782}," '.\u002Ftypes'",[250,24871,1379],{"class":912},[250,24873,24874],{"class":252,"line":113},[250,24875,795],{"emptyLinePlaceholder":129},[250,24877,24878,24880,24883,24885,24887,24889,24891],{"class":252,"line":110},[250,24879,1181],{"class":786},[250,24881,24882],{"class":778}," DEFAULT_SCALE",[250,24884,1007],{"class":786},[250,24886,24655],{"class":774},[250,24888,1413],{"class":912},[250,24890,1416],{"class":786},[250,24892,1190],{"class":912},[250,24894,24895,24898,24901,24904,24907,24910,24912,24915,24917],{"class":252,"line":269},[250,24896,24897],{"class":912},"  { letter: ",[250,24899,24900],{"class":782},"'A'",[250,24902,24903],{"class":912},", min: ",[250,24905,24906],{"class":778},"90",[250,24908,24909],{"class":912},", max: ",[250,24911,1590],{"class":778},[250,24913,24914],{"class":912},", gpa: ",[250,24916,1283],{"class":778},[250,24918,1219],{"class":912},[250,24920,24921,24923,24926,24928,24931,24933,24936,24938,24940],{"class":252,"line":275},[250,24922,24897],{"class":912},[250,24924,24925],{"class":782},"'B'",[250,24927,24903],{"class":912},[250,24929,24930],{"class":778},"80",[250,24932,24909],{"class":912},[250,24934,24935],{"class":778},"89",[250,24937,24914],{"class":912},[250,24939,1236],{"class":778},[250,24941,1219],{"class":912},[250,24943,24944,24946,24949,24951,24954,24956,24959,24961,24964],{"class":252,"line":281},[250,24945,24897],{"class":912},[250,24947,24948],{"class":782},"'C'",[250,24950,24903],{"class":912},[250,24952,24953],{"class":778},"70",[250,24955,24909],{"class":912},[250,24957,24958],{"class":778},"79",[250,24960,24914],{"class":912},[250,24962,24963],{"class":778},"2.0",[250,24965,1219],{"class":912},[250,24967,24968,24970,24973,24975,24977,24979,24982,24984,24987],{"class":252,"line":287},[250,24969,24897],{"class":912},[250,24971,24972],{"class":782},"'D'",[250,24974,24903],{"class":912},[250,24976,15548],{"class":778},[250,24978,24909],{"class":912},[250,24980,24981],{"class":778},"69",[250,24983,24914],{"class":912},[250,24985,24986],{"class":778},"1.0",[250,24988,1219],{"class":912},[250,24990,24991,24993,24996,24998,25000,25002,25005,25007,25010],{"class":252,"line":293},[250,24992,24897],{"class":912},[250,24994,24995],{"class":782},"'F'",[250,24997,24903],{"class":912},[250,24999,3542],{"class":778},[250,25001,24909],{"class":912},[250,25003,25004],{"class":778},"59",[250,25006,24914],{"class":912},[250,25008,25009],{"class":778},"0.0",[250,25011,1219],{"class":912},[250,25013,25014],{"class":252,"line":299},[250,25015,1317],{"class":912},[250,25017,25018],{"class":252,"line":132},[250,25019,795],{"emptyLinePlaceholder":129},[250,25021,25022,25024,25026,25029],{"class":252,"line":310},[250,25023,1019],{"class":786},[250,25025,1845],{"class":786},[250,25027,25028],{"class":774}," toLetterGrade",[250,25030,1982],{"class":912},[250,25032,25033,25036,25038,25040],{"class":252,"line":316},[250,25034,25035],{"class":1370},"  percentage",[250,25037,1007],{"class":786},[250,25039,1376],{"class":778},[250,25041,927],{"class":912},[250,25043,25044,25047,25049,25051,25053,25055],{"class":252,"line":322},[250,25045,25046],{"class":1370},"  scale",[250,25048,1007],{"class":786},[250,25050,24655],{"class":774},[250,25052,1413],{"class":912},[250,25054,1416],{"class":786},[250,25056,25057],{"class":778}," DEFAULT_SCALE\n",[250,25059,25060,25062,25064,25066],{"class":252,"line":328},[250,25061,2390],{"class":912},[250,25063,1007],{"class":786},[250,25065,2506],{"class":778},[250,25067,1118],{"class":912},[250,25069,25070,25072,25075,25077,25079,25082,25084,25086,25089,25092,25094,25096],{"class":252,"line":334},[250,25071,1455],{"class":786},[250,25073,25074],{"class":778}," clamped",[250,25076,1187],{"class":786},[250,25078,2277],{"class":912},[250,25080,25081],{"class":774},"max",[250,25083,1434],{"class":912},[250,25085,3542],{"class":778},[250,25087,25088],{"class":912},", Math.",[250,25090,25091],{"class":774},"min",[250,25093,1434],{"class":912},[250,25095,1590],{"class":778},[250,25097,25098],{"class":912},", percentage));\n",[250,25100,25101,25103,25106,25108,25111,25114,25116,25119,25121,25124,25126,25129,25131,25133,25136],{"class":252,"line":340},[250,25102,1455],{"class":786},[250,25104,25105],{"class":778}," match",[250,25107,1187],{"class":786},[250,25109,25110],{"class":912}," scale.",[250,25112,25113],{"class":774},"find",[250,25115,1434],{"class":912},[250,25117,25118],{"class":1370},"s",[250,25120,23033],{"class":786},[250,25122,25123],{"class":912}," clamped ",[250,25125,2030],{"class":786},[250,25127,25128],{"class":912}," s.min ",[250,25130,10479],{"class":786},[250,25132,25123],{"class":912},[250,25134,25135],{"class":786},"\u003C=",[250,25137,25138],{"class":912}," s.max);\n",[250,25140,25141,25143,25146,25149,25152],{"class":252,"line":346},[250,25142,1123],{"class":786},[250,25144,25145],{"class":912}," match?.letter ",[250,25147,25148],{"class":786},"??",[250,25150,25151],{"class":782}," 'F'",[250,25153,1379],{"class":912},[250,25155,25156],{"class":252,"line":352},[250,25157,991],{"class":912},[250,25159,25160],{"class":252,"line":358},[250,25161,795],{"emptyLinePlaceholder":129},[250,25163,25164,25166,25168,25171],{"class":252,"line":364},[250,25165,1019],{"class":786},[250,25167,1845],{"class":786},[250,25169,25170],{"class":774}," toGPA",[250,25172,1982],{"class":912},[250,25174,25175,25177,25179,25181],{"class":252,"line":370},[250,25176,25035],{"class":1370},[250,25178,1007],{"class":786},[250,25180,1376],{"class":778},[250,25182,927],{"class":912},[250,25184,25185,25187,25189,25191,25193,25195],{"class":252,"line":376},[250,25186,25046],{"class":1370},[250,25188,1007],{"class":786},[250,25190,24655],{"class":774},[250,25192,1413],{"class":912},[250,25194,1416],{"class":786},[250,25196,25057],{"class":778},[250,25198,25199,25201,25203,25205],{"class":252,"line":382},[250,25200,2390],{"class":912},[250,25202,1007],{"class":786},[250,25204,1376],{"class":778},[250,25206,1118],{"class":912},[250,25208,25209,25211,25214,25216,25218],{"class":252,"line":388},[250,25210,1455],{"class":786},[250,25212,25213],{"class":778}," letter",[250,25215,1187],{"class":786},[250,25217,25028],{"class":774},[250,25219,25220],{"class":912},"(percentage, scale);\n",[250,25222,25223,25225,25227,25229,25231,25233,25235,25237,25239,25242,25245],{"class":252,"line":393},[250,25224,1455],{"class":786},[250,25226,25105],{"class":778},[250,25228,1187],{"class":786},[250,25230,25110],{"class":912},[250,25232,25113],{"class":774},[250,25234,1434],{"class":912},[250,25236,25118],{"class":1370},[250,25238,23033],{"class":786},[250,25240,25241],{"class":912}," s.letter ",[250,25243,25244],{"class":786},"===",[250,25246,25247],{"class":912}," letter);\n",[250,25249,25250,25252,25255,25257,25259],{"class":252,"line":399},[250,25251,1123],{"class":786},[250,25253,25254],{"class":912}," match?.gpa ",[250,25256,25148],{"class":786},[250,25258,1509],{"class":778},[250,25260,1379],{"class":912},[250,25262,25263],{"class":252,"line":405},[250,25264,991],{"class":912},[31,25266,25268],{"id":25267},"weighted-grade-calculation","Weighted Grade Calculation",[47,25270,25273],{"className":1010,"code":25271,"filename":25272,"language":1012,"meta":55,"style":55},"import type { WeightedComponent } from '.\u002Ftypes';\n\nexport function weightedAverage(components: WeightedComponent[]): number {\n  if (components.length === 0) return 0;\n\n  const totalWeight = components.reduce((sum, c) => sum + c.weight, 0);\n  if (totalWeight === 0) return 0;\n\n  const weighted = components.reduce(\n    (sum, c) => sum + c.score * c.weight,\n    0\n  );\n\n  return Math.round((weighted \u002F totalWeight) * 100) \u002F 100;\n}\n","src\u002Fweights.ts",[39,25274,25275,25290,25294,25321,25343,25347,25389,25408,25412,25427,25454,25459,25463,25467,25495],{"__ignoreMap":55},[250,25276,25277,25279,25281,25284,25286,25288],{"class":252,"line":253},[250,25278,1763],{"class":786},[250,25280,4974],{"class":786},[250,25282,25283],{"class":912}," { WeightedComponent } ",[250,25285,1769],{"class":786},[250,25287,24869],{"class":782},[250,25289,1379],{"class":912},[250,25291,25292],{"class":252,"line":113},[250,25293,795],{"emptyLinePlaceholder":129},[250,25295,25296,25298,25300,25303,25305,25308,25310,25312,25315,25317,25319],{"class":252,"line":110},[250,25297,1019],{"class":786},[250,25299,1845],{"class":786},[250,25301,25302],{"class":774}," weightedAverage",[250,25304,1434],{"class":912},[250,25306,25307],{"class":1370},"components",[250,25309,1007],{"class":786},[250,25311,24718],{"class":774},[250,25313,25314],{"class":912},"[])",[250,25316,1007],{"class":786},[250,25318,1376],{"class":778},[250,25320,1118],{"class":912},[250,25322,25323,25325,25328,25330,25332,25334,25336,25339,25341],{"class":252,"line":269},[250,25324,1486],{"class":786},[250,25326,25327],{"class":912}," (components.",[250,25329,1503],{"class":778},[250,25331,1506],{"class":786},[250,25333,1509],{"class":778},[250,25335,1446],{"class":912},[250,25337,25338],{"class":786},"return",[250,25340,1509],{"class":778},[250,25342,1379],{"class":912},[250,25344,25345],{"class":252,"line":275},[250,25346,795],{"emptyLinePlaceholder":129},[250,25348,25349,25351,25354,25356,25359,25362,25364,25367,25369,25372,25374,25376,25379,25382,25385,25387],{"class":252,"line":281},[250,25350,1455],{"class":786},[250,25352,25353],{"class":778}," totalWeight",[250,25355,1187],{"class":786},[250,25357,25358],{"class":912}," components.",[250,25360,25361],{"class":774},"reduce",[250,25363,1574],{"class":912},[250,25365,25366],{"class":1370},"sum",[250,25368,7128],{"class":912},[250,25370,25371],{"class":1370},"c",[250,25373,1446],{"class":912},[250,25375,1115],{"class":786},[250,25377,25378],{"class":912}," sum ",[250,25380,25381],{"class":786},"+",[250,25383,25384],{"class":912}," c.weight, ",[250,25386,3542],{"class":778},[250,25388,1885],{"class":912},[250,25390,25391,25393,25396,25398,25400,25402,25404,25406],{"class":252,"line":287},[250,25392,1486],{"class":786},[250,25394,25395],{"class":912}," (totalWeight ",[250,25397,25244],{"class":786},[250,25399,1509],{"class":778},[250,25401,1446],{"class":912},[250,25403,25338],{"class":786},[250,25405,1509],{"class":778},[250,25407,1379],{"class":912},[250,25409,25410],{"class":252,"line":293},[250,25411,795],{"emptyLinePlaceholder":129},[250,25413,25414,25416,25419,25421,25423,25425],{"class":252,"line":299},[250,25415,1455],{"class":786},[250,25417,25418],{"class":778}," weighted",[250,25420,1187],{"class":786},[250,25422,25358],{"class":912},[250,25424,25361],{"class":774},[250,25426,1982],{"class":912},[250,25428,25429,25432,25434,25436,25438,25440,25442,25444,25446,25449,25451],{"class":252,"line":132},[250,25430,25431],{"class":912},"    (",[250,25433,25366],{"class":1370},[250,25435,7128],{"class":912},[250,25437,25371],{"class":1370},[250,25439,1446],{"class":912},[250,25441,1115],{"class":786},[250,25443,25378],{"class":912},[250,25445,25381],{"class":786},[250,25447,25448],{"class":912}," c.score ",[250,25450,6594],{"class":786},[250,25452,25453],{"class":912}," c.weight,\n",[250,25455,25456],{"class":252,"line":310},[250,25457,25458],{"class":778},"    0\n",[250,25460,25461],{"class":252,"line":316},[250,25462,2859],{"class":912},[250,25464,25465],{"class":252,"line":322},[250,25466,795],{"emptyLinePlaceholder":129},[250,25468,25469,25471,25473,25475,25478,25480,25483,25485,25487,25489,25491,25493],{"class":252,"line":328},[250,25470,1123],{"class":786},[250,25472,2277],{"class":912},[250,25474,2280],{"class":774},[250,25476,25477],{"class":912},"((weighted ",[250,25479,2293],{"class":786},[250,25481,25482],{"class":912}," totalWeight) ",[250,25484,6594],{"class":786},[250,25486,1832],{"class":778},[250,25488,1446],{"class":912},[250,25490,2293],{"class":786},[250,25492,1832],{"class":778},[250,25494,1379],{"class":912},[250,25496,25497],{"class":252,"line":334},[250,25498,991],{"class":912},[20,25500,25501],{},"A teacher can use this like:",[47,25503,25505],{"className":1010,"code":25504,"language":1012,"meta":55,"style":55},"const finalGrade = weightedAverage([\n  { name: 'Homework', score: 88, weight: 0.3 },\n  { name: 'Midterm', score: 76, weight: 0.3 },\n  { name: 'Final Exam', score: 82, weight: 0.4 },\n]);\n\u002F\u002F => 81.8\n",[39,25506,25507,25521,25543,25561,25580,25585],{"__ignoreMap":55},[250,25508,25509,25511,25514,25516,25518],{"class":252,"line":253},[250,25510,1181],{"class":786},[250,25512,25513],{"class":778}," finalGrade",[250,25515,1187],{"class":786},[250,25517,25302],{"class":774},[250,25519,25520],{"class":912},"([\n",[250,25522,25523,25526,25529,25532,25535,25538,25541],{"class":252,"line":113},[250,25524,25525],{"class":912},"  { name: ",[250,25527,25528],{"class":782},"'Homework'",[250,25530,25531],{"class":912},", score: ",[250,25533,25534],{"class":778},"88",[250,25536,25537],{"class":912},", weight: ",[250,25539,25540],{"class":778},"0.3",[250,25542,1219],{"class":912},[250,25544,25545,25547,25550,25552,25555,25557,25559],{"class":252,"line":110},[250,25546,25525],{"class":912},[250,25548,25549],{"class":782},"'Midterm'",[250,25551,25531],{"class":912},[250,25553,25554],{"class":778},"76",[250,25556,25537],{"class":912},[250,25558,25540],{"class":778},[250,25560,1219],{"class":912},[250,25562,25563,25565,25568,25570,25573,25575,25578],{"class":252,"line":269},[250,25564,25525],{"class":912},[250,25566,25567],{"class":782},"'Final Exam'",[250,25569,25531],{"class":912},[250,25571,25572],{"class":778},"82",[250,25574,25537],{"class":912},[250,25576,25577],{"class":778},"0.4",[250,25579,1219],{"class":912},[250,25581,25582],{"class":252,"line":275},[250,25583,25584],{"class":912},"]);\n",[250,25586,25587],{"class":252,"line":281},[250,25588,25589],{"class":768},"\u002F\u002F => 81.8\n",[31,25591,25593],{"id":25592},"score-curving","Score Curving",[47,25595,25598],{"className":1010,"code":25596,"filename":25597,"language":1012,"meta":55,"style":55},"export function curveByHighest(\n  scores: number[],\n  targetHigh: number = 100\n): number[] {\n  const highest = Math.max(...scores);\n  if (highest >= targetHigh) return scores;\n\n  const boost = targetHigh - highest;\n  return scores.map(s => Math.min(100, s + boost));\n}\n\nexport function curveByMean(\n  scores: number[],\n  targetMean: number = 75\n): number[] {\n  const mean = scores.reduce((a, b) => a + b, 0) \u002F scores.length;\n  const shift = targetMean - mean;\n  return scores.map(s => Math.max(0, Math.min(100, s + shift)));\n}\n","src\u002Fcurve.ts",[39,25599,25600,25611,25623,25637,25648,25668,25685,25689,25706,25737,25741,25745,25756,25766,25780,25790,25836,25853,25890],{"__ignoreMap":55},[250,25601,25602,25604,25606,25609],{"class":252,"line":253},[250,25603,1019],{"class":786},[250,25605,1845],{"class":786},[250,25607,25608],{"class":774}," curveByHighest",[250,25610,1982],{"class":912},[250,25612,25613,25616,25618,25620],{"class":252,"line":113},[250,25614,25615],{"class":1370},"  scores",[250,25617,1007],{"class":786},[250,25619,1376],{"class":778},[250,25621,25622],{"class":912},"[],\n",[250,25624,25625,25628,25630,25632,25634],{"class":252,"line":110},[250,25626,25627],{"class":1370},"  targetHigh",[250,25629,1007],{"class":786},[250,25631,1376],{"class":778},[250,25633,1187],{"class":786},[250,25635,25636],{"class":778}," 100\n",[250,25638,25639,25641,25643,25645],{"class":252,"line":269},[250,25640,2390],{"class":912},[250,25642,1007],{"class":786},[250,25644,1376],{"class":778},[250,25646,25647],{"class":912},"[] {\n",[250,25649,25650,25652,25655,25657,25659,25661,25663,25665],{"class":252,"line":275},[250,25651,1455],{"class":786},[250,25653,25654],{"class":778}," highest",[250,25656,1187],{"class":786},[250,25658,2277],{"class":912},[250,25660,25081],{"class":774},[250,25662,1434],{"class":912},[250,25664,7771],{"class":786},[250,25666,25667],{"class":912},"scores);\n",[250,25669,25670,25672,25675,25677,25680,25682],{"class":252,"line":281},[250,25671,1486],{"class":786},[250,25673,25674],{"class":912}," (highest ",[250,25676,2030],{"class":786},[250,25678,25679],{"class":912}," targetHigh) ",[250,25681,25338],{"class":786},[250,25683,25684],{"class":912}," scores;\n",[250,25686,25687],{"class":252,"line":287},[250,25688,795],{"emptyLinePlaceholder":129},[250,25690,25691,25693,25696,25698,25701,25703],{"class":252,"line":293},[250,25692,1455],{"class":786},[250,25694,25695],{"class":778}," boost",[250,25697,1187],{"class":786},[250,25699,25700],{"class":912}," targetHigh ",[250,25702,2261],{"class":786},[250,25704,25705],{"class":912}," highest;\n",[250,25707,25708,25710,25713,25715,25717,25719,25721,25723,25725,25727,25729,25732,25734],{"class":252,"line":299},[250,25709,1123],{"class":786},[250,25711,25712],{"class":912}," scores.",[250,25714,2820],{"class":774},[250,25716,1434],{"class":912},[250,25718,25118],{"class":1370},[250,25720,23033],{"class":786},[250,25722,2277],{"class":912},[250,25724,25091],{"class":774},[250,25726,1434],{"class":912},[250,25728,1590],{"class":778},[250,25730,25731],{"class":912},", s ",[250,25733,25381],{"class":786},[250,25735,25736],{"class":912}," boost));\n",[250,25738,25739],{"class":252,"line":132},[250,25740,991],{"class":912},[250,25742,25743],{"class":252,"line":310},[250,25744,795],{"emptyLinePlaceholder":129},[250,25746,25747,25749,25751,25754],{"class":252,"line":316},[250,25748,1019],{"class":786},[250,25750,1845],{"class":786},[250,25752,25753],{"class":774}," curveByMean",[250,25755,1982],{"class":912},[250,25757,25758,25760,25762,25764],{"class":252,"line":322},[250,25759,25615],{"class":1370},[250,25761,1007],{"class":786},[250,25763,1376],{"class":778},[250,25765,25622],{"class":912},[250,25767,25768,25771,25773,25775,25777],{"class":252,"line":328},[250,25769,25770],{"class":1370},"  targetMean",[250,25772,1007],{"class":786},[250,25774,1376],{"class":778},[250,25776,1187],{"class":786},[250,25778,25779],{"class":778}," 75\n",[250,25781,25782,25784,25786,25788],{"class":252,"line":334},[250,25783,2390],{"class":912},[250,25785,1007],{"class":786},[250,25787,1376],{"class":778},[250,25789,25647],{"class":912},[250,25791,25792,25794,25797,25799,25801,25803,25805,25807,25809,25812,25814,25816,25819,25821,25824,25826,25828,25830,25832,25834],{"class":252,"line":340},[250,25793,1455],{"class":786},[250,25795,25796],{"class":778}," mean",[250,25798,1187],{"class":786},[250,25800,25712],{"class":912},[250,25802,25361],{"class":774},[250,25804,1574],{"class":912},[250,25806,203],{"class":1370},[250,25808,7128],{"class":912},[250,25810,25811],{"class":1370},"b",[250,25813,1446],{"class":912},[250,25815,1115],{"class":786},[250,25817,25818],{"class":912}," a ",[250,25820,25381],{"class":786},[250,25822,25823],{"class":912}," b, ",[250,25825,3542],{"class":778},[250,25827,1446],{"class":912},[250,25829,2293],{"class":786},[250,25831,25712],{"class":912},[250,25833,1503],{"class":778},[250,25835,1379],{"class":912},[250,25837,25838,25840,25843,25845,25848,25850],{"class":252,"line":346},[250,25839,1455],{"class":786},[250,25841,25842],{"class":778}," shift",[250,25844,1187],{"class":786},[250,25846,25847],{"class":912}," targetMean ",[250,25849,2261],{"class":786},[250,25851,25852],{"class":912}," mean;\n",[250,25854,25855,25857,25859,25861,25863,25865,25867,25869,25871,25873,25875,25877,25879,25881,25883,25885,25887],{"class":252,"line":352},[250,25856,1123],{"class":786},[250,25858,25712],{"class":912},[250,25860,2820],{"class":774},[250,25862,1434],{"class":912},[250,25864,25118],{"class":1370},[250,25866,23033],{"class":786},[250,25868,2277],{"class":912},[250,25870,25081],{"class":774},[250,25872,1434],{"class":912},[250,25874,3542],{"class":778},[250,25876,25088],{"class":912},[250,25878,25091],{"class":774},[250,25880,1434],{"class":912},[250,25882,1590],{"class":778},[250,25884,25731],{"class":912},[250,25886,25381],{"class":786},[250,25888,25889],{"class":912}," shift)));\n",[250,25891,25892],{"class":252,"line":358},[250,25893,991],{"class":912},[31,25895,25897],{"id":25896},"class-statistics","Class Statistics",[47,25899,25902],{"className":1010,"code":25900,"filename":25901,"language":1012,"meta":55,"style":55},"import type { ClassStats } from '.\u002Ftypes';\n\nexport function classStats(scores: number[]): ClassStats {\n  if (scores.length === 0) {\n    return { mean: 0, median: 0, stdDev: 0, highest: 0, lowest: 0, count: 0 };\n  }\n\n  const sorted = [...scores].sort((a, b) => a - b);\n  const count = sorted.length;\n  const sum = sorted.reduce((a, b) => a + b, 0);\n  const mean = sum \u002F count;\n\n  const mid = Math.floor(count \u002F 2);\n  const median = count % 2 === 0\n    ? (sorted[mid - 1] + sorted[mid]) \u002F 2\n    : sorted[mid];\n\n  const variance = sorted.reduce((acc, s) => acc + (s - mean) ** 2, 0) \u002F count;\n  const stdDev = Math.round(Math.sqrt(variance) * 100) \u002F 100;\n\n  return {\n    mean: Math.round(mean * 100) \u002F 100,\n    median,\n    stdDev,\n    highest: sorted[count - 1],\n    lowest: sorted[0],\n    count,\n  };\n}\n","src\u002Fstats.ts\"",[39,25903,25904,25919,25923,25949,25964,26000,26004,26008,26046,26062,26097,26112,26116,26140,26162,26187,26195,26199,26253,26287,26291,26297,26319,26324,26329,26340,26349,26354,26358],{"__ignoreMap":55},[250,25905,25906,25908,25910,25913,25915,25917],{"class":252,"line":253},[250,25907,1763],{"class":786},[250,25909,4974],{"class":786},[250,25911,25912],{"class":912}," { ClassStats } ",[250,25914,1769],{"class":786},[250,25916,24869],{"class":782},[250,25918,1379],{"class":912},[250,25920,25921],{"class":252,"line":113},[250,25922,795],{"emptyLinePlaceholder":129},[250,25924,25925,25927,25929,25932,25934,25937,25939,25941,25943,25945,25947],{"class":252,"line":110},[250,25926,1019],{"class":786},[250,25928,1845],{"class":786},[250,25930,25931],{"class":774}," classStats",[250,25933,1434],{"class":912},[250,25935,25936],{"class":1370},"scores",[250,25938,1007],{"class":786},[250,25940,1376],{"class":778},[250,25942,25314],{"class":912},[250,25944,1007],{"class":786},[250,25946,24769],{"class":774},[250,25948,1118],{"class":912},[250,25950,25951,25953,25956,25958,25960,25962],{"class":252,"line":269},[250,25952,1486],{"class":786},[250,25954,25955],{"class":912}," (scores.",[250,25957,1503],{"class":778},[250,25959,1506],{"class":786},[250,25961,1509],{"class":778},[250,25963,1512],{"class":912},[250,25965,25966,25968,25971,25973,25976,25978,25981,25983,25986,25988,25991,25993,25996,25998],{"class":252,"line":275},[250,25967,14581],{"class":786},[250,25969,25970],{"class":912}," { mean: ",[250,25972,3542],{"class":778},[250,25974,25975],{"class":912},", median: ",[250,25977,3542],{"class":778},[250,25979,25980],{"class":912},", stdDev: ",[250,25982,3542],{"class":778},[250,25984,25985],{"class":912},", highest: ",[250,25987,3542],{"class":778},[250,25989,25990],{"class":912},", lowest: ",[250,25992,3542],{"class":778},[250,25994,25995],{"class":912},", count: ",[250,25997,3542],{"class":778},[250,25999,5784],{"class":912},[250,26001,26002],{"class":252,"line":281},[250,26003,986],{"class":912},[250,26005,26006],{"class":252,"line":287},[250,26007,795],{"emptyLinePlaceholder":129},[250,26009,26010,26012,26015,26017,26019,26021,26024,26027,26029,26031,26033,26035,26037,26039,26041,26043],{"class":252,"line":293},[250,26011,1455],{"class":786},[250,26013,26014],{"class":778}," sorted",[250,26016,1187],{"class":786},[250,26018,7123],{"class":912},[250,26020,7771],{"class":786},[250,26022,26023],{"class":912},"scores].",[250,26025,26026],{"class":774},"sort",[250,26028,1574],{"class":912},[250,26030,203],{"class":1370},[250,26032,7128],{"class":912},[250,26034,25811],{"class":1370},[250,26036,1446],{"class":912},[250,26038,1115],{"class":786},[250,26040,25818],{"class":912},[250,26042,2261],{"class":786},[250,26044,26045],{"class":912}," b);\n",[250,26047,26048,26050,26053,26055,26058,26060],{"class":252,"line":299},[250,26049,1455],{"class":786},[250,26051,26052],{"class":778}," count",[250,26054,1187],{"class":786},[250,26056,26057],{"class":912}," sorted.",[250,26059,1503],{"class":778},[250,26061,1379],{"class":912},[250,26063,26064,26066,26069,26071,26073,26075,26077,26079,26081,26083,26085,26087,26089,26091,26093,26095],{"class":252,"line":132},[250,26065,1455],{"class":786},[250,26067,26068],{"class":778}," sum",[250,26070,1187],{"class":786},[250,26072,26057],{"class":912},[250,26074,25361],{"class":774},[250,26076,1574],{"class":912},[250,26078,203],{"class":1370},[250,26080,7128],{"class":912},[250,26082,25811],{"class":1370},[250,26084,1446],{"class":912},[250,26086,1115],{"class":786},[250,26088,25818],{"class":912},[250,26090,25381],{"class":786},[250,26092,25823],{"class":912},[250,26094,3542],{"class":778},[250,26096,1885],{"class":912},[250,26098,26099,26101,26103,26105,26107,26109],{"class":252,"line":310},[250,26100,1455],{"class":786},[250,26102,25796],{"class":778},[250,26104,1187],{"class":786},[250,26106,25378],{"class":912},[250,26108,2293],{"class":786},[250,26110,26111],{"class":912}," count;\n",[250,26113,26114],{"class":252,"line":316},[250,26115,795],{"emptyLinePlaceholder":129},[250,26117,26118,26120,26123,26125,26127,26130,26133,26135,26138],{"class":252,"line":322},[250,26119,1455],{"class":786},[250,26121,26122],{"class":778}," mid",[250,26124,1187],{"class":786},[250,26126,2277],{"class":912},[250,26128,26129],{"class":774},"floor",[250,26131,26132],{"class":912},"(count ",[250,26134,2293],{"class":786},[250,26136,26137],{"class":778}," 2",[250,26139,1885],{"class":912},[250,26141,26142,26144,26147,26149,26152,26155,26157,26159],{"class":252,"line":328},[250,26143,1455],{"class":786},[250,26145,26146],{"class":778}," median",[250,26148,1187],{"class":786},[250,26150,26151],{"class":912}," count ",[250,26153,26154],{"class":786},"%",[250,26156,26137],{"class":778},[250,26158,1506],{"class":786},[250,26160,26161],{"class":778}," 0\n",[250,26163,26164,26167,26170,26172,26175,26177,26179,26182,26184],{"class":252,"line":334},[250,26165,26166],{"class":786},"    ?",[250,26168,26169],{"class":912}," (sorted[mid ",[250,26171,2261],{"class":786},[250,26173,26174],{"class":778}," 1",[250,26176,22052],{"class":912},[250,26178,25381],{"class":786},[250,26180,26181],{"class":912}," sorted[mid]) ",[250,26183,2293],{"class":786},[250,26185,26186],{"class":778}," 2\n",[250,26188,26189,26192],{"class":252,"line":340},[250,26190,26191],{"class":786},"    :",[250,26193,26194],{"class":912}," sorted[mid];\n",[250,26196,26197],{"class":252,"line":346},[250,26198,795],{"emptyLinePlaceholder":129},[250,26200,26201,26203,26206,26208,26210,26212,26214,26217,26219,26221,26223,26225,26228,26230,26233,26235,26238,26241,26243,26245,26247,26249,26251],{"class":252,"line":352},[250,26202,1455],{"class":786},[250,26204,26205],{"class":778}," variance",[250,26207,1187],{"class":786},[250,26209,26057],{"class":912},[250,26211,25361],{"class":774},[250,26213,1574],{"class":912},[250,26215,26216],{"class":1370},"acc",[250,26218,7128],{"class":912},[250,26220,25118],{"class":1370},[250,26222,1446],{"class":912},[250,26224,1115],{"class":786},[250,26226,26227],{"class":912}," acc ",[250,26229,25381],{"class":786},[250,26231,26232],{"class":912}," (s ",[250,26234,2261],{"class":786},[250,26236,26237],{"class":912}," mean) ",[250,26239,26240],{"class":786},"**",[250,26242,26137],{"class":778},[250,26244,7128],{"class":912},[250,26246,3542],{"class":778},[250,26248,1446],{"class":912},[250,26250,2293],{"class":786},[250,26252,26111],{"class":912},[250,26254,26255,26257,26260,26262,26264,26266,26269,26272,26275,26277,26279,26281,26283,26285],{"class":252,"line":358},[250,26256,1455],{"class":786},[250,26258,26259],{"class":778}," stdDev",[250,26261,1187],{"class":786},[250,26263,2277],{"class":912},[250,26265,2280],{"class":774},[250,26267,26268],{"class":912},"(Math.",[250,26270,26271],{"class":774},"sqrt",[250,26273,26274],{"class":912},"(variance) ",[250,26276,6594],{"class":786},[250,26278,1832],{"class":778},[250,26280,1446],{"class":912},[250,26282,2293],{"class":786},[250,26284,1832],{"class":778},[250,26286,1379],{"class":912},[250,26288,26289],{"class":252,"line":364},[250,26290,795],{"emptyLinePlaceholder":129},[250,26292,26293,26295],{"class":252,"line":370},[250,26294,1123],{"class":786},[250,26296,1118],{"class":912},[250,26298,26299,26302,26304,26307,26309,26311,26313,26315,26317],{"class":252,"line":376},[250,26300,26301],{"class":912},"    mean: Math.",[250,26303,2280],{"class":774},[250,26305,26306],{"class":912},"(mean ",[250,26308,6594],{"class":786},[250,26310,1832],{"class":778},[250,26312,1446],{"class":912},[250,26314,2293],{"class":786},[250,26316,1832],{"class":778},[250,26318,927],{"class":912},[250,26320,26321],{"class":252,"line":382},[250,26322,26323],{"class":912},"    median,\n",[250,26325,26326],{"class":252,"line":388},[250,26327,26328],{"class":912},"    stdDev,\n",[250,26330,26331,26334,26336,26338],{"class":252,"line":393},[250,26332,26333],{"class":912},"    highest: sorted[count ",[250,26335,2261],{"class":786},[250,26337,26174],{"class":778},[250,26339,14000],{"class":912},[250,26341,26342,26345,26347],{"class":252,"line":399},[250,26343,26344],{"class":912},"    lowest: sorted[",[250,26346,3542],{"class":778},[250,26348,14000],{"class":912},[250,26350,26351],{"class":252,"line":405},[250,26352,26353],{"class":912},"    count,\n",[250,26355,26356],{"class":252,"line":410},[250,26357,1161],{"class":912},[250,26359,26360],{"class":252,"line":415},[250,26361,991],{"class":912},[15,26363,26365],{"id":26364},"step-4-wire-up-the-entry-point","Step 4: Wire Up the Entry Point",[47,26367,26370],{"className":1010,"code":26368,"filename":26369,"language":1012,"meta":55,"style":55},"export { toLetterGrade, toGPA } from '.\u002Fgrades';\nexport { weightedAverage } from '.\u002Fweights';\nexport { curveByHighest, curveByMean } from '.\u002Fcurve';\nexport { classStats } from '.\u002Fstats';\nexport type { GradeScale, WeightedComponent, ClassStats } from '.\u002Ftypes';\n","src\u002Findex.ts",[39,26371,26372,26386,26400,26414,26428],{"__ignoreMap":55},[250,26373,26374,26376,26379,26381,26384],{"class":252,"line":253},[250,26375,1019],{"class":786},[250,26377,26378],{"class":912}," { toLetterGrade, toGPA } ",[250,26380,1769],{"class":786},[250,26382,26383],{"class":782}," '.\u002Fgrades'",[250,26385,1379],{"class":912},[250,26387,26388,26390,26393,26395,26398],{"class":252,"line":113},[250,26389,1019],{"class":786},[250,26391,26392],{"class":912}," { weightedAverage } ",[250,26394,1769],{"class":786},[250,26396,26397],{"class":782}," '.\u002Fweights'",[250,26399,1379],{"class":912},[250,26401,26402,26404,26407,26409,26412],{"class":252,"line":110},[250,26403,1019],{"class":786},[250,26405,26406],{"class":912}," { curveByHighest, curveByMean } ",[250,26408,1769],{"class":786},[250,26410,26411],{"class":782}," '.\u002Fcurve'",[250,26413,1379],{"class":912},[250,26415,26416,26418,26421,26423,26426],{"class":252,"line":269},[250,26417,1019],{"class":786},[250,26419,26420],{"class":912}," { classStats } ",[250,26422,1769],{"class":786},[250,26424,26425],{"class":782}," '.\u002Fstats'",[250,26427,1379],{"class":912},[250,26429,26430,26432,26434,26437,26439,26441],{"class":252,"line":275},[250,26431,1019],{"class":786},[250,26433,4974],{"class":786},[250,26435,26436],{"class":912}," { GradeScale, WeightedComponent, ClassStats } ",[250,26438,1769],{"class":786},[250,26440,24869],{"class":782},[250,26442,1379],{"class":912},[15,26444,26446],{"id":26445},"step-5-write-tests","Step 5: Write Tests",[20,26448,1092,26449,1007],{},[39,26450,26451],{},"src\u002Fgrades.test.ts",[47,26453,26455],{"className":1010,"code":26454,"filename":26451,"language":1012,"meta":55,"style":55},"import { describe, it, expect } from 'vitest';\nimport { toLetterGrade, toGPA } from '.\u002Fgrades';\nimport { weightedAverage } from '.\u002Fweights';\nimport { curveByHighest, curveByMean } from '.\u002Fcurve';\nimport { classStats } from '.\u002Fstats';\n\ndescribe('toLetterGrade', () => {\n  it('converts percentages to letter grades', () => {\n    expect(toLetterGrade(95)).toBe('A');\n    expect(toLetterGrade(83)).toBe('B');\n    expect(toLetterGrade(72)).toBe('C');\n    expect(toLetterGrade(65)).toBe('D');\n    expect(toLetterGrade(40)).toBe('F');\n  });\n\n  it('clamps out-of-range values', () => {\n    expect(toLetterGrade(110)).toBe('A');\n    expect(toLetterGrade(-5)).toBe('F');\n  });\n});\n\ndescribe('toGPA', () => {\n  it('converts to 4.0 scale', () => {\n    expect(toGPA(92)).toBe(4.0);\n    expect(toGPA(85)).toBe(3.0);\n    expect(toGPA(55)).toBe(0.0);\n  });\n});\n\ndescribe('weightedAverage', () => {\n  it('calculates weighted grade', () => {\n    const result = weightedAverage([\n      { name: 'Homework', score: 90, weight: 0.4 },\n      { name: 'Exam', score: 80, weight: 0.6 },\n    ]);\n    expect(result).toBe(84);\n  });\n\n  it('returns 0 for empty input', () => {\n    expect(weightedAverage([])).toBe(0);\n  });\n});\n\ndescribe('curveByHighest', () => {\n  it('curves scores up to target', () => {\n    const curved = curveByHighest([70, 80, 90], 100);\n    expect(curved).toEqual([80, 90, 100]);\n  });\n\n  it('does not curve if highest already meets target', () => {\n    const scores = [70, 80, 95];\n    expect(curveByHighest(scores, 100)).toEqual(scores);\n  });\n});\n\ndescribe('classStats', () => {\n  it('calculates stats correctly', () => {\n    const stats = classStats([90, 80, 70, 60, 50]);\n    expect(stats.mean).toBe(70);\n    expect(stats.median).toBe(70);\n    expect(stats.highest).toBe(90);\n    expect(stats.lowest).toBe(50);\n    expect(stats.count).toBe(5);\n  });\n});\n",[39,26456,26457,26471,26483,26495,26507,26519,26523,26539,26555,26582,26605,26628,26651,26674,26678,26682,26697,26720,26744,26748,26752,26756,26771,26786,26810,26833,26856,26860,26864,26868,26883,26898,26911,26928,26946,26951,26967,26971,26975,26990,27010,27014,27018,27022,27037,27052,27083,27107,27111,27115,27130,27153,27174,27178,27182,27186,27201,27216,27250,27265,27280,27295,27310,27325,27329],{"__ignoreMap":55},[250,26458,26459,26461,26464,26466,26469],{"class":252,"line":253},[250,26460,1763],{"class":786},[250,26462,26463],{"class":912}," { describe, it, expect } ",[250,26465,1769],{"class":786},[250,26467,26468],{"class":782}," 'vitest'",[250,26470,1379],{"class":912},[250,26472,26473,26475,26477,26479,26481],{"class":252,"line":113},[250,26474,1763],{"class":786},[250,26476,26378],{"class":912},[250,26478,1769],{"class":786},[250,26480,26383],{"class":782},[250,26482,1379],{"class":912},[250,26484,26485,26487,26489,26491,26493],{"class":252,"line":110},[250,26486,1763],{"class":786},[250,26488,26392],{"class":912},[250,26490,1769],{"class":786},[250,26492,26397],{"class":782},[250,26494,1379],{"class":912},[250,26496,26497,26499,26501,26503,26505],{"class":252,"line":269},[250,26498,1763],{"class":786},[250,26500,26406],{"class":912},[250,26502,1769],{"class":786},[250,26504,26411],{"class":782},[250,26506,1379],{"class":912},[250,26508,26509,26511,26513,26515,26517],{"class":252,"line":275},[250,26510,1763],{"class":786},[250,26512,26420],{"class":912},[250,26514,1769],{"class":786},[250,26516,26425],{"class":782},[250,26518,1379],{"class":912},[250,26520,26521],{"class":252,"line":281},[250,26522,795],{"emptyLinePlaceholder":129},[250,26524,26525,26528,26530,26533,26535,26537],{"class":252,"line":287},[250,26526,26527],{"class":774},"describe",[250,26529,1434],{"class":912},[250,26531,26532],{"class":782},"'toLetterGrade'",[250,26534,13157],{"class":912},[250,26536,1115],{"class":786},[250,26538,1118],{"class":912},[250,26540,26541,26544,26546,26549,26551,26553],{"class":252,"line":293},[250,26542,26543],{"class":774},"  it",[250,26545,1434],{"class":912},[250,26547,26548],{"class":782},"'converts percentages to letter grades'",[250,26550,13157],{"class":912},[250,26552,1115],{"class":786},[250,26554,1118],{"class":912},[250,26556,26557,26560,26562,26565,26567,26570,26573,26576,26578,26580],{"class":252,"line":299},[250,26558,26559],{"class":774},"    expect",[250,26561,1434],{"class":912},[250,26563,26564],{"class":774},"toLetterGrade",[250,26566,1434],{"class":912},[250,26568,26569],{"class":778},"95",[250,26571,26572],{"class":912},")).",[250,26574,26575],{"class":774},"toBe",[250,26577,1434],{"class":912},[250,26579,24900],{"class":782},[250,26581,1885],{"class":912},[250,26583,26584,26586,26588,26590,26592,26595,26597,26599,26601,26603],{"class":252,"line":132},[250,26585,26559],{"class":774},[250,26587,1434],{"class":912},[250,26589,26564],{"class":774},[250,26591,1434],{"class":912},[250,26593,26594],{"class":778},"83",[250,26596,26572],{"class":912},[250,26598,26575],{"class":774},[250,26600,1434],{"class":912},[250,26602,24925],{"class":782},[250,26604,1885],{"class":912},[250,26606,26607,26609,26611,26613,26615,26618,26620,26622,26624,26626],{"class":252,"line":310},[250,26608,26559],{"class":774},[250,26610,1434],{"class":912},[250,26612,26564],{"class":774},[250,26614,1434],{"class":912},[250,26616,26617],{"class":778},"72",[250,26619,26572],{"class":912},[250,26621,26575],{"class":774},[250,26623,1434],{"class":912},[250,26625,24948],{"class":782},[250,26627,1885],{"class":912},[250,26629,26630,26632,26634,26636,26638,26641,26643,26645,26647,26649],{"class":252,"line":316},[250,26631,26559],{"class":774},[250,26633,1434],{"class":912},[250,26635,26564],{"class":774},[250,26637,1434],{"class":912},[250,26639,26640],{"class":778},"65",[250,26642,26572],{"class":912},[250,26644,26575],{"class":774},[250,26646,1434],{"class":912},[250,26648,24972],{"class":782},[250,26650,1885],{"class":912},[250,26652,26653,26655,26657,26659,26661,26664,26666,26668,26670,26672],{"class":252,"line":322},[250,26654,26559],{"class":774},[250,26656,1434],{"class":912},[250,26658,26564],{"class":774},[250,26660,1434],{"class":912},[250,26662,26663],{"class":778},"40",[250,26665,26572],{"class":912},[250,26667,26575],{"class":774},[250,26669,1434],{"class":912},[250,26671,24995],{"class":782},[250,26673,1885],{"class":912},[250,26675,26676],{"class":252,"line":328},[250,26677,6749],{"class":912},[250,26679,26680],{"class":252,"line":334},[250,26681,795],{"emptyLinePlaceholder":129},[250,26683,26684,26686,26688,26691,26693,26695],{"class":252,"line":340},[250,26685,26543],{"class":774},[250,26687,1434],{"class":912},[250,26689,26690],{"class":782},"'clamps out-of-range values'",[250,26692,13157],{"class":912},[250,26694,1115],{"class":786},[250,26696,1118],{"class":912},[250,26698,26699,26701,26703,26705,26707,26710,26712,26714,26716,26718],{"class":252,"line":346},[250,26700,26559],{"class":774},[250,26702,1434],{"class":912},[250,26704,26564],{"class":774},[250,26706,1434],{"class":912},[250,26708,26709],{"class":778},"110",[250,26711,26572],{"class":912},[250,26713,26575],{"class":774},[250,26715,1434],{"class":912},[250,26717,24900],{"class":782},[250,26719,1885],{"class":912},[250,26721,26722,26724,26726,26728,26730,26732,26734,26736,26738,26740,26742],{"class":252,"line":352},[250,26723,26559],{"class":774},[250,26725,1434],{"class":912},[250,26727,26564],{"class":774},[250,26729,1434],{"class":912},[250,26731,2261],{"class":786},[250,26733,1297],{"class":778},[250,26735,26572],{"class":912},[250,26737,26575],{"class":774},[250,26739,1434],{"class":912},[250,26741,24995],{"class":782},[250,26743,1885],{"class":912},[250,26745,26746],{"class":252,"line":358},[250,26747,6749],{"class":912},[250,26749,26750],{"class":252,"line":364},[250,26751,1077],{"class":912},[250,26753,26754],{"class":252,"line":370},[250,26755,795],{"emptyLinePlaceholder":129},[250,26757,26758,26760,26762,26765,26767,26769],{"class":252,"line":376},[250,26759,26527],{"class":774},[250,26761,1434],{"class":912},[250,26763,26764],{"class":782},"'toGPA'",[250,26766,13157],{"class":912},[250,26768,1115],{"class":786},[250,26770,1118],{"class":912},[250,26772,26773,26775,26777,26780,26782,26784],{"class":252,"line":382},[250,26774,26543],{"class":774},[250,26776,1434],{"class":912},[250,26778,26779],{"class":782},"'converts to 4.0 scale'",[250,26781,13157],{"class":912},[250,26783,1115],{"class":786},[250,26785,1118],{"class":912},[250,26787,26788,26790,26792,26795,26797,26800,26802,26804,26806,26808],{"class":252,"line":388},[250,26789,26559],{"class":774},[250,26791,1434],{"class":912},[250,26793,26794],{"class":774},"toGPA",[250,26796,1434],{"class":912},[250,26798,26799],{"class":778},"92",[250,26801,26572],{"class":912},[250,26803,26575],{"class":774},[250,26805,1434],{"class":912},[250,26807,1283],{"class":778},[250,26809,1885],{"class":912},[250,26811,26812,26814,26816,26818,26820,26823,26825,26827,26829,26831],{"class":252,"line":393},[250,26813,26559],{"class":774},[250,26815,1434],{"class":912},[250,26817,26794],{"class":774},[250,26819,1434],{"class":912},[250,26821,26822],{"class":778},"85",[250,26824,26572],{"class":912},[250,26826,26575],{"class":774},[250,26828,1434],{"class":912},[250,26830,1236],{"class":778},[250,26832,1885],{"class":912},[250,26834,26835,26837,26839,26841,26843,26846,26848,26850,26852,26854],{"class":252,"line":399},[250,26836,26559],{"class":774},[250,26838,1434],{"class":912},[250,26840,26794],{"class":774},[250,26842,1434],{"class":912},[250,26844,26845],{"class":778},"55",[250,26847,26572],{"class":912},[250,26849,26575],{"class":774},[250,26851,1434],{"class":912},[250,26853,25009],{"class":778},[250,26855,1885],{"class":912},[250,26857,26858],{"class":252,"line":405},[250,26859,6749],{"class":912},[250,26861,26862],{"class":252,"line":410},[250,26863,1077],{"class":912},[250,26865,26866],{"class":252,"line":415},[250,26867,795],{"emptyLinePlaceholder":129},[250,26869,26870,26872,26874,26877,26879,26881],{"class":252,"line":420},[250,26871,26527],{"class":774},[250,26873,1434],{"class":912},[250,26875,26876],{"class":782},"'weightedAverage'",[250,26878,13157],{"class":912},[250,26880,1115],{"class":786},[250,26882,1118],{"class":912},[250,26884,26885,26887,26889,26892,26894,26896],{"class":252,"line":426},[250,26886,26543],{"class":774},[250,26888,1434],{"class":912},[250,26890,26891],{"class":782},"'calculates weighted grade'",[250,26893,13157],{"class":912},[250,26895,1115],{"class":786},[250,26897,1118],{"class":912},[250,26899,26900,26902,26905,26907,26909],{"class":252,"line":431},[250,26901,6403],{"class":786},[250,26903,26904],{"class":778}," result",[250,26906,1187],{"class":786},[250,26908,25302],{"class":774},[250,26910,25520],{"class":912},[250,26912,26913,26916,26918,26920,26922,26924,26926],{"class":252,"line":436},[250,26914,26915],{"class":912},"      { name: ",[250,26917,25528],{"class":782},[250,26919,25531],{"class":912},[250,26921,24906],{"class":778},[250,26923,25537],{"class":912},[250,26925,25577],{"class":778},[250,26927,1219],{"class":912},[250,26929,26930,26932,26935,26937,26939,26941,26944],{"class":252,"line":442},[250,26931,26915],{"class":912},[250,26933,26934],{"class":782},"'Exam'",[250,26936,25531],{"class":912},[250,26938,24930],{"class":778},[250,26940,25537],{"class":912},[250,26942,26943],{"class":778},"0.6",[250,26945,1219],{"class":912},[250,26947,26948],{"class":252,"line":447},[250,26949,26950],{"class":912},"    ]);\n",[250,26952,26953,26955,26958,26960,26962,26965],{"class":252,"line":453},[250,26954,26559],{"class":774},[250,26956,26957],{"class":912},"(result).",[250,26959,26575],{"class":774},[250,26961,1434],{"class":912},[250,26963,26964],{"class":778},"84",[250,26966,1885],{"class":912},[250,26968,26969],{"class":252,"line":459},[250,26970,6749],{"class":912},[250,26972,26973],{"class":252,"line":465},[250,26974,795],{"emptyLinePlaceholder":129},[250,26976,26977,26979,26981,26984,26986,26988],{"class":252,"line":471},[250,26978,26543],{"class":774},[250,26980,1434],{"class":912},[250,26982,26983],{"class":782},"'returns 0 for empty input'",[250,26985,13157],{"class":912},[250,26987,1115],{"class":786},[250,26989,1118],{"class":912},[250,26991,26992,26994,26996,26999,27002,27004,27006,27008],{"class":252,"line":2201},[250,26993,26559],{"class":774},[250,26995,1434],{"class":912},[250,26997,26998],{"class":774},"weightedAverage",[250,27000,27001],{"class":912},"([])).",[250,27003,26575],{"class":774},[250,27005,1434],{"class":912},[250,27007,3542],{"class":778},[250,27009,1885],{"class":912},[250,27011,27012],{"class":252,"line":2207},[250,27013,6749],{"class":912},[250,27015,27016],{"class":252,"line":2213},[250,27017,1077],{"class":912},[250,27019,27020],{"class":252,"line":2218},[250,27021,795],{"emptyLinePlaceholder":129},[250,27023,27024,27026,27028,27031,27033,27035],{"class":252,"line":2223},[250,27025,26527],{"class":774},[250,27027,1434],{"class":912},[250,27029,27030],{"class":782},"'curveByHighest'",[250,27032,13157],{"class":912},[250,27034,1115],{"class":786},[250,27036,1118],{"class":912},[250,27038,27039,27041,27043,27046,27048,27050],{"class":252,"line":2239},[250,27040,26543],{"class":774},[250,27042,1434],{"class":912},[250,27044,27045],{"class":782},"'curves scores up to target'",[250,27047,13157],{"class":912},[250,27049,1115],{"class":786},[250,27051,1118],{"class":912},[250,27053,27054,27056,27059,27061,27063,27066,27068,27070,27072,27074,27076,27079,27081],{"class":252,"line":2244},[250,27055,6403],{"class":786},[250,27057,27058],{"class":778}," curved",[250,27060,1187],{"class":786},[250,27062,25608],{"class":774},[250,27064,27065],{"class":912},"([",[250,27067,24953],{"class":778},[250,27069,7128],{"class":912},[250,27071,24930],{"class":778},[250,27073,7128],{"class":912},[250,27075,24906],{"class":778},[250,27077,27078],{"class":912},"], ",[250,27080,1590],{"class":778},[250,27082,1885],{"class":912},[250,27084,27085,27087,27090,27093,27095,27097,27099,27101,27103,27105],{"class":252,"line":2267},[250,27086,26559],{"class":774},[250,27088,27089],{"class":912},"(curved).",[250,27091,27092],{"class":774},"toEqual",[250,27094,27065],{"class":912},[250,27096,24930],{"class":778},[250,27098,7128],{"class":912},[250,27100,24906],{"class":778},[250,27102,7128],{"class":912},[250,27104,1590],{"class":778},[250,27106,25584],{"class":912},[250,27108,27109],{"class":252,"line":2301},[250,27110,6749],{"class":912},[250,27112,27113],{"class":252,"line":2306},[250,27114,795],{"emptyLinePlaceholder":129},[250,27116,27117,27119,27121,27124,27126,27128],{"class":252,"line":2320},[250,27118,26543],{"class":774},[250,27120,1434],{"class":912},[250,27122,27123],{"class":782},"'does not curve if highest already meets target'",[250,27125,13157],{"class":912},[250,27127,1115],{"class":786},[250,27129,1118],{"class":912},[250,27131,27132,27134,27137,27139,27141,27143,27145,27147,27149,27151],{"class":252,"line":2340},[250,27133,6403],{"class":786},[250,27135,27136],{"class":778}," scores",[250,27138,1187],{"class":786},[250,27140,7123],{"class":912},[250,27142,24953],{"class":778},[250,27144,7128],{"class":912},[250,27146,24930],{"class":778},[250,27148,7128],{"class":912},[250,27150,26569],{"class":778},[250,27152,1317],{"class":912},[250,27154,27155,27157,27159,27162,27165,27167,27169,27171],{"class":252,"line":2360},[250,27156,26559],{"class":774},[250,27158,1434],{"class":912},[250,27160,27161],{"class":774},"curveByHighest",[250,27163,27164],{"class":912},"(scores, ",[250,27166,1590],{"class":778},[250,27168,26572],{"class":912},[250,27170,27092],{"class":774},[250,27172,27173],{"class":912},"(scores);\n",[250,27175,27176],{"class":252,"line":2397},[250,27177,6749],{"class":912},[250,27179,27180],{"class":252,"line":2402},[250,27181,1077],{"class":912},[250,27183,27184],{"class":252,"line":2407},[250,27185,795],{"emptyLinePlaceholder":129},[250,27187,27188,27190,27192,27195,27197,27199],{"class":252,"line":6667},[250,27189,26527],{"class":774},[250,27191,1434],{"class":912},[250,27193,27194],{"class":782},"'classStats'",[250,27196,13157],{"class":912},[250,27198,1115],{"class":786},[250,27200,1118],{"class":912},[250,27202,27203,27205,27207,27210,27212,27214],{"class":252,"line":6672},[250,27204,26543],{"class":774},[250,27206,1434],{"class":912},[250,27208,27209],{"class":782},"'calculates stats correctly'",[250,27211,13157],{"class":912},[250,27213,1115],{"class":786},[250,27215,1118],{"class":912},[250,27217,27218,27220,27223,27225,27227,27229,27231,27233,27235,27237,27239,27241,27243,27245,27248],{"class":252,"line":6688},[250,27219,6403],{"class":786},[250,27221,27222],{"class":778}," stats",[250,27224,1187],{"class":786},[250,27226,25931],{"class":774},[250,27228,27065],{"class":912},[250,27230,24906],{"class":778},[250,27232,7128],{"class":912},[250,27234,24930],{"class":778},[250,27236,7128],{"class":912},[250,27238,24953],{"class":778},[250,27240,7128],{"class":912},[250,27242,15548],{"class":778},[250,27244,7128],{"class":912},[250,27246,27247],{"class":778},"50",[250,27249,25584],{"class":912},[250,27251,27252,27254,27257,27259,27261,27263],{"class":252,"line":6694},[250,27253,26559],{"class":774},[250,27255,27256],{"class":912},"(stats.mean).",[250,27258,26575],{"class":774},[250,27260,1434],{"class":912},[250,27262,24953],{"class":778},[250,27264,1885],{"class":912},[250,27266,27267,27269,27272,27274,27276,27278],{"class":252,"line":6707},[250,27268,26559],{"class":774},[250,27270,27271],{"class":912},"(stats.median).",[250,27273,26575],{"class":774},[250,27275,1434],{"class":912},[250,27277,24953],{"class":778},[250,27279,1885],{"class":912},[250,27281,27282,27284,27287,27289,27291,27293],{"class":252,"line":6716},[250,27283,26559],{"class":774},[250,27285,27286],{"class":912},"(stats.highest).",[250,27288,26575],{"class":774},[250,27290,1434],{"class":912},[250,27292,24906],{"class":778},[250,27294,1885],{"class":912},[250,27296,27297,27299,27302,27304,27306,27308],{"class":252,"line":6722},[250,27298,26559],{"class":774},[250,27300,27301],{"class":912},"(stats.lowest).",[250,27303,26575],{"class":774},[250,27305,1434],{"class":912},[250,27307,27247],{"class":778},[250,27309,1885],{"class":912},[250,27311,27312,27314,27317,27319,27321,27323],{"class":252,"line":6734},[250,27313,26559],{"class":774},[250,27315,27316],{"class":912},"(stats.count).",[250,27318,26575],{"class":774},[250,27320,1434],{"class":912},[250,27322,1297],{"class":778},[250,27324,1885],{"class":912},[250,27326,27327],{"class":252,"line":6746},[250,27328,6749],{"class":912},[250,27330,27331],{"class":252,"line":6752},[250,27332,1077],{"class":912},[20,27334,27335],{},"Run the tests:",[47,27337,27339],{"className":758,"code":27338,"language":761,"meta":55,"style":55},"vp test\n",[39,27340,27341],{"__ignoreMap":55},[250,27342,27343,27345],{"class":252,"line":253},[250,27344,24571],{"class":774},[250,27346,27347],{"class":782}," test\n",[161,27349,27352],{"icon":27350,"title":27351},"✅","Vitest Is Built In",[20,27353,27354,27355,27358,27359,27362],{},"No extra install or config. ",[39,27356,27357],{},"vp test"," picks up ",[39,27360,27361],{},".test.ts"," files automatically using the same transform pipeline as your source code.",[15,27364,27366],{"id":27365},"step-6-configure-packaging","Step 6: Configure Packaging",[20,27368,1003,27369,1007],{},[39,27370,27371],{},"vite.config.ts",[47,27373,27375],{"className":1010,"code":27374,"filename":27371,"language":1012,"meta":55,"style":55},"import { defineConfig } from 'vite-plus';\n\nexport default defineConfig({\n  pack: {\n    entry: ['src\u002Findex.ts'],\n    dts: true,\n    format: ['esm', 'cjs'],\n    sourcemap: true,\n  },\n});\n",[39,27376,27377,27390,27394,27404,27409,27419,27428,27443,27452,27456],{"__ignoreMap":55},[250,27378,27379,27381,27383,27385,27388],{"class":252,"line":253},[250,27380,1763],{"class":786},[250,27382,4280],{"class":912},[250,27384,1769],{"class":786},[250,27386,27387],{"class":782}," 'vite-plus'",[250,27389,1379],{"class":912},[250,27391,27392],{"class":252,"line":113},[250,27393,795],{"emptyLinePlaceholder":129},[250,27395,27396,27398,27400,27402],{"class":252,"line":110},[250,27397,1019],{"class":786},[250,27399,1022],{"class":786},[250,27401,4300],{"class":774},[250,27403,1028],{"class":912},[250,27405,27406],{"class":252,"line":269},[250,27407,27408],{"class":912},"  pack: {\n",[250,27410,27411,27414,27417],{"class":252,"line":275},[250,27412,27413],{"class":912},"    entry: [",[250,27415,27416],{"class":782},"'src\u002Findex.ts'",[250,27418,14000],{"class":912},[250,27420,27421,27424,27426],{"class":252,"line":281},[250,27422,27423],{"class":912},"    dts: ",[250,27425,1066],{"class":778},[250,27427,927],{"class":912},[250,27429,27430,27433,27436,27438,27441],{"class":252,"line":287},[250,27431,27432],{"class":912},"    format: [",[250,27434,27435],{"class":782},"'esm'",[250,27437,7128],{"class":912},[250,27439,27440],{"class":782},"'cjs'",[250,27442,14000],{"class":912},[250,27444,27445,27448,27450],{"class":252,"line":293},[250,27446,27447],{"class":912},"    sourcemap: ",[250,27449,1066],{"class":778},[250,27451,927],{"class":912},[250,27453,27454],{"class":252,"line":299},[250,27455,1048],{"class":912},[250,27457,27458],{"class":252,"line":132},[250,27459,1077],{"class":912},[20,27461,27462],{},"This tells Vite+ to:",[561,27464,27465,27471,27474],{},[564,27466,27467,27468,2390],{},"Generate TypeScript declaration files (",[39,27469,27470],{},".d.ts",[564,27472,27473],{},"Output both ESM and CJS formats",[564,27475,27476],{},"Include source maps for debugging",[15,27478,27480],{"id":27479},"step-7-build-the-package","Step 7: Build the Package",[47,27482,27484],{"className":758,"code":27483,"language":761,"meta":55,"style":55},"vp pack\n",[39,27485,27486],{"__ignoreMap":55},[250,27487,27488,27490],{"class":252,"line":253},[250,27489,24571],{"class":774},[250,27491,27492],{"class":782}," pack\n",[20,27494,27495],{},"You'll see output like:",[47,27497,27499],{"className":12725,"code":27498,"language":12727,"meta":55,"style":55},"CLI Building entry: src\u002Findex.ts\nESM dist\u002Findex.js     2.1 kB\nCJS dist\u002Findex.cjs    2.2 kB\nDTS dist\u002Findex.d.ts   1.4 kB\n✓ Pack completed in 94ms\n",[39,27500,27501,27506,27511,27516,27521],{"__ignoreMap":55},[250,27502,27503],{"class":252,"line":253},[250,27504,27505],{},"CLI Building entry: src\u002Findex.ts\n",[250,27507,27508],{"class":252,"line":113},[250,27509,27510],{},"ESM dist\u002Findex.js     2.1 kB\n",[250,27512,27513],{"class":252,"line":110},[250,27514,27515],{},"CJS dist\u002Findex.cjs    2.2 kB\n",[250,27517,27518],{"class":252,"line":269},[250,27519,27520],{},"DTS dist\u002Findex.d.ts   1.4 kB\n",[250,27522,27523],{"class":252,"line":275},[250,27524,27525],{},"✓ Pack completed in 94ms\n",[24,27527,27528],{"type":631},[20,27529,27530,27532,27533,27538],{},[39,27531,24502],{}," uses ",[203,27534,27537],{"href":27535,"rel":27536},"https:\u002F\u002Ftsdown.dev\u002F",[207],"tsdown"," under the hood — powered by Rolldown, which itself is written in Rust. That's why it's fast.",[15,27540,27542],{"id":27541},"step-8-publish-to-npm","Step 8: Publish to npm",[20,27544,1003,27545,27547],{},[39,27546,904],{}," with the essentials:",[47,27549,27551],{"className":902,"code":27550,"filename":904,"language":905,"meta":55,"style":55},"{\n  \"name\": \"teacher-toolkit\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Grade calculation utilities for teachers\",\n  \"type\": \"module\",\n  \"main\": \"dist\u002Findex.cjs\",\n  \"module\": \"dist\u002Findex.js\",\n  \"types\": \"dist\u002Findex.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": \".\u002Fdist\u002Findex.js\",\n      \"require\": \".\u002Fdist\u002Findex.cjs\",\n      \"types\": \".\u002Fdist\u002Findex.d.ts\"\n    }\n  },\n  \"files\": [\"dist\"],\n  \"license\": \"MIT\"\n}\n",[39,27552,27553,27557,27569,27581,27593,27605,27617,27629,27641,27648,27655,27667,27679,27689,27693,27697,27710,27720],{"__ignoreMap":55},[250,27554,27555],{"class":252,"line":253},[250,27556,913],{"class":912},[250,27558,27559,27562,27564,27567],{"class":252,"line":113},[250,27560,27561],{"class":778},"  \"name\"",[250,27563,921],{"class":912},[250,27565,27566],{"class":782},"\"teacher-toolkit\"",[250,27568,927],{"class":912},[250,27570,27571,27574,27576,27579],{"class":252,"line":110},[250,27572,27573],{"class":778},"  \"version\"",[250,27575,921],{"class":912},[250,27577,27578],{"class":782},"\"1.0.0\"",[250,27580,927],{"class":912},[250,27582,27583,27586,27588,27591],{"class":252,"line":269},[250,27584,27585],{"class":778},"  \"description\"",[250,27587,921],{"class":912},[250,27589,27590],{"class":782},"\"Grade calculation utilities for teachers\"",[250,27592,927],{"class":912},[250,27594,27595,27598,27600,27603],{"class":252,"line":275},[250,27596,27597],{"class":778},"  \"type\"",[250,27599,921],{"class":912},[250,27601,27602],{"class":782},"\"module\"",[250,27604,927],{"class":912},[250,27606,27607,27610,27612,27615],{"class":252,"line":281},[250,27608,27609],{"class":778},"  \"main\"",[250,27611,921],{"class":912},[250,27613,27614],{"class":782},"\"dist\u002Findex.cjs\"",[250,27616,927],{"class":912},[250,27618,27619,27622,27624,27627],{"class":252,"line":287},[250,27620,27621],{"class":778},"  \"module\"",[250,27623,921],{"class":912},[250,27625,27626],{"class":782},"\"dist\u002Findex.js\"",[250,27628,927],{"class":912},[250,27630,27631,27634,27636,27639],{"class":252,"line":293},[250,27632,27633],{"class":778},"  \"types\"",[250,27635,921],{"class":912},[250,27637,27638],{"class":782},"\"dist\u002Findex.d.ts\"",[250,27640,927],{"class":912},[250,27642,27643,27646],{"class":252,"line":299},[250,27644,27645],{"class":778},"  \"exports\"",[250,27647,935],{"class":912},[250,27649,27650,27653],{"class":252,"line":132},[250,27651,27652],{"class":778},"    \".\"",[250,27654,935],{"class":912},[250,27656,27657,27660,27662,27665],{"class":252,"line":310},[250,27658,27659],{"class":778},"      \"import\"",[250,27661,921],{"class":912},[250,27663,27664],{"class":782},"\".\u002Fdist\u002Findex.js\"",[250,27666,927],{"class":912},[250,27668,27669,27672,27674,27677],{"class":252,"line":316},[250,27670,27671],{"class":778},"      \"require\"",[250,27673,921],{"class":912},[250,27675,27676],{"class":782},"\".\u002Fdist\u002Findex.cjs\"",[250,27678,927],{"class":912},[250,27680,27681,27684,27686],{"class":252,"line":322},[250,27682,27683],{"class":778},"      \"types\"",[250,27685,921],{"class":912},[250,27687,27688],{"class":782},"\".\u002Fdist\u002Findex.d.ts\"\n",[250,27690,27691],{"class":252,"line":328},[250,27692,3684],{"class":912},[250,27694,27695],{"class":252,"line":334},[250,27696,1048],{"class":912},[250,27698,27699,27702,27705,27708],{"class":252,"line":340},[250,27700,27701],{"class":778},"  \"files\"",[250,27703,27704],{"class":912},": [",[250,27706,27707],{"class":782},"\"dist\"",[250,27709,14000],{"class":912},[250,27711,27712,27715,27717],{"class":252,"line":346},[250,27713,27714],{"class":778},"  \"license\"",[250,27716,921],{"class":912},[250,27718,27719],{"class":782},"\"MIT\"\n",[250,27721,27722],{"class":252,"line":352},[250,27723,991],{"class":912},[20,27725,27726],{},"Then publish:",[47,27728,27730],{"className":758,"code":27729,"language":761,"meta":55,"style":55},"npm publish\n",[39,27731,27732],{"__ignoreMap":55},[250,27733,27734,27736],{"class":252,"line":253},[250,27735,4226],{"class":774},[250,27737,27738],{"class":782}," publish\n",[15,27740,27742],{"id":27741},"using-the-package","Using the Package",[20,27744,27745],{},"Once published, any teacher or developer can install it:",[47,27747,27749],{"className":758,"code":27748,"language":761,"meta":55,"style":55},"npm install teacher-toolkit\n",[39,27750,27751],{"__ignoreMap":55},[250,27752,27753,27755,27757],{"class":252,"line":253},[250,27754,4226],{"class":774},[250,27756,808],{"class":782},[250,27758,24583],{"class":782},[47,27760,27762],{"className":1010,"code":27761,"language":1012,"meta":55,"style":55},"import { toLetterGrade, weightedAverage, curveByHighest, classStats } from 'teacher-toolkit';\n\n\u002F\u002F Convert a score\ntoLetterGrade(87);              \u002F\u002F => \"B\"\n\n\u002F\u002F Calculate a final grade\nconst final = weightedAverage([\n  { name: 'Quiz', score: 92, weight: 0.2 },\n  { name: 'Project', score: 78, weight: 0.3 },\n  { name: 'Final', score: 85, weight: 0.5 },\n]);                             \u002F\u002F => 84.2\n\n\u002F\u002F Curve a set of exam scores\nconst curved = curveByHighest([62, 74, 81, 90]);  \u002F\u002F => [72, 84, 91, 100]\n\n\u002F\u002F Get class overview\nclassStats([90, 82, 75, 68, 55]);\n\u002F\u002F => { mean: 74, median: 75, stdDev: 12.49, highest: 90, lowest: 55, count: 5 }\n",[39,27763,27764,27778,27782,27787,27802,27806,27811,27824,27842,27860,27877,27885,27889,27894,27929,27933,27938,27967],{"__ignoreMap":55},[250,27765,27766,27768,27771,27773,27776],{"class":252,"line":253},[250,27767,1763],{"class":786},[250,27769,27770],{"class":912}," { toLetterGrade, weightedAverage, curveByHighest, classStats } ",[250,27772,1769],{"class":786},[250,27774,27775],{"class":782}," 'teacher-toolkit'",[250,27777,1379],{"class":912},[250,27779,27780],{"class":252,"line":113},[250,27781,795],{"emptyLinePlaceholder":129},[250,27783,27784],{"class":252,"line":110},[250,27785,27786],{"class":768},"\u002F\u002F Convert a score\n",[250,27788,27789,27791,27793,27796,27799],{"class":252,"line":269},[250,27790,26564],{"class":774},[250,27792,1434],{"class":912},[250,27794,27795],{"class":778},"87",[250,27797,27798],{"class":912},");              ",[250,27800,27801],{"class":768},"\u002F\u002F => \"B\"\n",[250,27803,27804],{"class":252,"line":275},[250,27805,795],{"emptyLinePlaceholder":129},[250,27807,27808],{"class":252,"line":281},[250,27809,27810],{"class":768},"\u002F\u002F Calculate a final grade\n",[250,27812,27813,27815,27818,27820,27822],{"class":252,"line":287},[250,27814,1181],{"class":786},[250,27816,27817],{"class":778}," final",[250,27819,1187],{"class":786},[250,27821,25302],{"class":774},[250,27823,25520],{"class":912},[250,27825,27826,27828,27831,27833,27835,27837,27840],{"class":252,"line":293},[250,27827,25525],{"class":912},[250,27829,27830],{"class":782},"'Quiz'",[250,27832,25531],{"class":912},[250,27834,26799],{"class":778},[250,27836,25537],{"class":912},[250,27838,27839],{"class":778},"0.2",[250,27841,1219],{"class":912},[250,27843,27844,27846,27849,27851,27854,27856,27858],{"class":252,"line":299},[250,27845,25525],{"class":912},[250,27847,27848],{"class":782},"'Project'",[250,27850,25531],{"class":912},[250,27852,27853],{"class":778},"78",[250,27855,25537],{"class":912},[250,27857,25540],{"class":778},[250,27859,1219],{"class":912},[250,27861,27862,27864,27867,27869,27871,27873,27875],{"class":252,"line":132},[250,27863,25525],{"class":912},[250,27865,27866],{"class":782},"'Final'",[250,27868,25531],{"class":912},[250,27870,26822],{"class":778},[250,27872,25537],{"class":912},[250,27874,19138],{"class":778},[250,27876,1219],{"class":912},[250,27878,27879,27882],{"class":252,"line":310},[250,27880,27881],{"class":912},"]);                             ",[250,27883,27884],{"class":768},"\u002F\u002F => 84.2\n",[250,27886,27887],{"class":252,"line":316},[250,27888,795],{"emptyLinePlaceholder":129},[250,27890,27891],{"class":252,"line":322},[250,27892,27893],{"class":768},"\u002F\u002F Curve a set of exam scores\n",[250,27895,27896,27898,27900,27902,27904,27906,27909,27911,27914,27916,27919,27921,27923,27926],{"class":252,"line":328},[250,27897,1181],{"class":786},[250,27899,27058],{"class":778},[250,27901,1187],{"class":786},[250,27903,25608],{"class":774},[250,27905,27065],{"class":912},[250,27907,27908],{"class":778},"62",[250,27910,7128],{"class":912},[250,27912,27913],{"class":778},"74",[250,27915,7128],{"class":912},[250,27917,27918],{"class":778},"81",[250,27920,7128],{"class":912},[250,27922,24906],{"class":778},[250,27924,27925],{"class":912},"]);  ",[250,27927,27928],{"class":768},"\u002F\u002F => [72, 84, 91, 100]\n",[250,27930,27931],{"class":252,"line":334},[250,27932,795],{"emptyLinePlaceholder":129},[250,27934,27935],{"class":252,"line":340},[250,27936,27937],{"class":768},"\u002F\u002F Get class overview\n",[250,27939,27940,27943,27945,27947,27949,27951,27953,27956,27958,27961,27963,27965],{"class":252,"line":346},[250,27941,27942],{"class":774},"classStats",[250,27944,27065],{"class":912},[250,27946,24906],{"class":778},[250,27948,7128],{"class":912},[250,27950,25572],{"class":778},[250,27952,7128],{"class":912},[250,27954,27955],{"class":778},"75",[250,27957,7128],{"class":912},[250,27959,27960],{"class":778},"68",[250,27962,7128],{"class":912},[250,27964,26845],{"class":778},[250,27966,25584],{"class":912},[250,27968,27969],{"class":252,"line":352},[250,27970,27971],{"class":768},"\u002F\u002F => { mean: 74, median: 75, stdDev: 12.49, highest: 90, lowest: 55, count: 5 }\n",[15,27973,27975],{"id":27974},"full-workflow-recap","Full Workflow Recap",[47,27977,27979],{"className":758,"code":27978,"language":761,"meta":55,"style":55},"vp create vite:library -- teacher-toolkit   # Scaffold\nvp install                                   # Install deps\nvp check                                     # Format + lint + type-check\nvp test                                      # Run tests\nvp pack                                      # Build for npm\nnpm publish                                  # Ship it\n",[39,27980,27981,27997,28006,28016,28026,28036],{"__ignoreMap":55},[250,27982,27983,27985,27987,27989,27991,27994],{"class":252,"line":253},[250,27984,24571],{"class":774},[250,27986,24574],{"class":782},[250,27988,24577],{"class":782},[250,27990,24580],{"class":778},[250,27992,27993],{"class":782}," teacher-toolkit",[250,27995,27996],{"class":768},"   # Scaffold\n",[250,27998,27999,28001,28003],{"class":252,"line":113},[250,28000,24571],{"class":774},[250,28002,808],{"class":782},[250,28004,28005],{"class":768},"                                   # Install deps\n",[250,28007,28008,28010,28013],{"class":252,"line":110},[250,28009,24571],{"class":774},[250,28011,28012],{"class":782}," check",[250,28014,28015],{"class":768},"                                     # Format + lint + type-check\n",[250,28017,28018,28020,28023],{"class":252,"line":269},[250,28019,24571],{"class":774},[250,28021,28022],{"class":782}," test",[250,28024,28025],{"class":768},"                                      # Run tests\n",[250,28027,28028,28030,28033],{"class":252,"line":275},[250,28029,24571],{"class":774},[250,28031,28032],{"class":782}," pack",[250,28034,28035],{"class":768},"                                      # Build for npm\n",[250,28037,28038,28040,28043],{"class":252,"line":281},[250,28039,4226],{"class":774},[250,28041,28042],{"class":782}," publish",[250,28044,28045],{"class":768},"                                  # Ship it\n",[20,28047,28048,28049,2230],{},"Six commands. Zero config files beyond ",[39,28050,27371],{},[10834,28052,28053,28057],{},[2459,28054,28056],{"id":28055},"why-vite-for-libraries","Why Vite+ for Libraries?",[20,28058,28059,28060,28062],{},"With ",[39,28061,24502],{},", you get DTS generation, dual ESM\u002FCJS output, and source maps without touching Rollup, tsup, or unbuild configs. The Vitest and Oxc integrations mean testing and linting are already part of the workflow.",[15,28064,28066],{"id":28065},"ideas-to-extend-this-package","Ideas to Extend This Package",[561,28068,28069,28075,28081,28087,28093],{},[564,28070,28071,28074],{},[546,28072,28073],{},"Letter grade with +\u002F-"," — A+, A, A-, B+, etc.",[564,28076,28077,28080],{},[546,28078,28079],{},"Rubric scoring"," — multi-criteria evaluation helpers",[564,28082,28083,28086],{},[546,28084,28085],{},"Attendance percentage"," — days present vs. total",[564,28088,28089,28092],{},[546,28090,28091],{},"Assignment deadline tracker"," — date math utilities",[564,28094,28095,28098],{},[546,28096,28097],{},"Export to CSV"," — grade reports for school systems",[15,28100,3352],{"id":3351},[20,28102,28103,28104,28107,28108,28110],{},"Vite+ makes it trivial to go from idea to published package. The ",[39,28105,28106],{},"vite:library"," template, built-in Vitest, and ",[39,28109,24502],{}," remove the usual friction of library authoring — no build config rabbit holes, no DTS plugin debugging.",[20,28112,28113],{},"For teachers and education developers, this means you can spend your time solving real problems (grade calculations, student analytics) instead of fighting tooling.",[20,28115,28116],{},"Ship the package. Help a teacher.",[500,28118,28119],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":55,"searchDepth":110,"depth":110,"links":28121},[28122,28123,28124,28125],{"id":24848,"depth":113,"text":24849},{"id":25267,"depth":113,"text":25268},{"id":25592,"depth":113,"text":25593},{"id":25896,"depth":113,"text":25897,"children":28126},[28127],{"id":28055,"depth":110,"text":28056},"2026-03-30","A hands-on guide to packaging a reusable npm library for educators using Vite+ — covering grade calculations, score curving, and GPA utilities.",{"type":12,"value":28131},[28132,28134,28136,28140],[15,28133,541],{"id":540},[20,28135,24481],{},[20,28137,24484,28138,24488],{},[39,28139,24487],{},[20,28141,24491,28142,24495,28144,24499,28146,24503],{},[546,28143,24494],{},[546,28145,24498],{},[39,28147,24502],{},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1775009589\u002Fviteplus_et4prw.png",[28150,126,28151,4226,28152,28153,28154,8234],"vite+","library","education","teachers","grading",{},"\u002Fblog\u002Fviteplus-teacher-toolkit-package",{"title":24473,"description":28129},"blog\u002Fviteplus-teacher-toolkit-package","xWzhCaOm5SYTix9V__dTbVoVpqXgQRSVWUv-Tvrd76w",{"id":28161,"title":28162,"author":28163,"body":28165,"canonical":115,"categories":115,"date":28128,"description":28726,"excerpt":28727,"extension":118,"img":28148,"keywords":28742,"language":3510,"meta":28747,"navigation":129,"ogImage":115,"path":28748,"rating":275,"readTime":293,"seo":28749,"stem":28750,"tag":3515,"__hash__":28751},"blog\u002Fblog\u002Fviteplus-unified-toolchain.md","Vite+: The Unified Toolchain That Replaces Your Entire Frontend Setup",{"name":8,"img":28164,"website":535},"https:\u002F\u002Fres.cloudinary.com\u002Fddszyeplg\u002Fimage\u002Fupload\u002Fv1767533048\u002FPXL_20251010_202726442_2_hhudfr.jpg",{"type":12,"value":28166,"toc":28720},[28167,28169,28172,28185,28197,28201,28204,28254,28272,28274,28276,28279,28297,28300,28318,28321,28333,28337,28351,28354,28358,28361,28422,28428,28453,28460,28463,28486,28512,28529,28535,28538,28552,28559,28565,28592,28595,28601,28607,28617,28620,28624,28627,28639,28648,28652,28660,28670,28674,28706,28708,28711,28717],[15,28168,541],{"id":540},[20,28170,28171],{},"If you've been juggling Node version managers, package managers, linters, formatters, test runners, and build tools — you're not alone. The JavaScript tooling landscape has gotten out of hand.",[20,28173,28174,28176,28177,28182,28183,2230],{},[546,28175,24498],{}," aims to fix that. Created by ",[203,28178,28181],{"href":28179,"rel":28180},"https:\u002F\u002Fvoidzero.dev\u002F",[207],"VoidZero"," — the team behind Vite, Vitest, Oxc, and Rolldown — it unifies your entire development workflow into a single CLI tool called ",[39,28184,24571],{},[24,28186,28187],{"type":631},[20,28188,28189,28190,28192,28193,28196],{},"Vite+ ships in two parts: ",[39,28191,24571],{},", the global command-line tool, and ",[39,28194,28195],{},"vite-plus",", the local package installed in each project.",[15,28198,28200],{"id":28199},"what-is-vite","What Is Vite+?",[20,28202,28203],{},"Vite+ is the unified toolchain and entry point for web development. It manages your runtime, package manager, and frontend stack by combining:",[561,28205,28206,28214,28222,28230,28237,28245,28251],{},[564,28207,28208,28213],{},[203,28209,28212],{"href":28210,"rel":28211},"https:\u002F\u002Fvite.dev\u002F",[207],"Vite"," — dev server and builds",[564,28215,28216,28221],{},[203,28217,28220],{"href":28218,"rel":28219},"https:\u002F\u002Fvitest.dev\u002F",[207],"Vitest"," — testing",[564,28223,28224,28229],{},[203,28225,28228],{"href":28226,"rel":28227},"https:\u002F\u002Foxc.rs\u002F",[207],"Oxlint"," — linting",[564,28231,28232,28236],{},[203,28233,28235],{"href":28226,"rel":28234},[207],"Oxfmt"," — formatting",[564,28238,28239,28244],{},[203,28240,28243],{"href":28241,"rel":28242},"https:\u002F\u002Frolldown.rs\u002F",[207],"Rolldown"," — bundling",[564,28246,28247,28250],{},[203,28248,27537],{"href":27535,"rel":28249},[207]," — library packaging",[564,28252,28253],{},"Vite Task — monorepo task orchestration",[161,28255,28257],{"icon":1713,"title":28256},"Rust-Powered Performance",[20,28258,28259,28260,28263,28264,28267,28268,28271],{},"With low-level components written in Rust, Vite+ delivers up to ",[546,28261,28262],{},"40x faster builds"," than Webpack, ",[546,28265,28266],{},"~50–100x faster linting"," than ESLint, and ",[546,28269,28270],{},"~30x faster formatting"," than Prettier.",[15,28273,21211],{"id":21210},[31,28275,21218],{"id":21217},[20,28277,28278],{},"macOS \u002F Linux:",[47,28280,28282],{"className":758,"code":28281,"language":761,"meta":55,"style":55},"curl -fsSL https:\u002F\u002Fvite.plus | bash\n",[39,28283,28284],{"__ignoreMap":55},[250,28285,28286,28288,28290,28293,28295],{"class":252,"line":253},[250,28287,775],{"class":774},[250,28289,779],{"class":778},[250,28291,28292],{"class":782}," https:\u002F\u002Fvite.plus",[250,28294,787],{"class":786},[250,28296,790],{"class":774},[20,28298,28299],{},"Windows (PowerShell):",[47,28301,28303],{"className":758,"code":28302,"language":761,"meta":55,"style":55},"irm https:\u002F\u002Fvite.plus\u002Fps1 | iex\n",[39,28304,28305],{"__ignoreMap":55},[250,28306,28307,28310,28313,28315],{"class":252,"line":253},[250,28308,28309],{"class":774},"irm",[250,28311,28312],{"class":782}," https:\u002F\u002Fvite.plus\u002Fps1",[250,28314,787],{"class":786},[250,28316,28317],{"class":774}," iex\n",[20,28319,28320],{},"Open a new terminal session and verify:",[47,28322,28324],{"className":758,"code":28323,"language":761,"meta":55,"style":55},"vp help\n",[39,28325,28326],{"__ignoreMap":55},[250,28327,28328,28330],{"class":252,"line":253},[250,28329,24571],{"class":774},[250,28331,28332],{"class":782}," help\n",[31,28334,28336],{"id":28335},"create-a-new-project","Create a New Project",[47,28338,28340],{"className":758,"code":28339,"language":761,"meta":55,"style":55},"vp create my-app\n",[39,28341,28342],{"__ignoreMap":55},[250,28343,28344,28346,28348],{"class":252,"line":253},[250,28345,24571],{"class":774},[250,28347,24574],{"class":782},[250,28349,28350],{"class":782}," my-app\n",[20,28352,28353],{},"Vite+ supports every framework built on Vite — React, Vue, Svelte, Solid, and 20+ more.",[15,28355,28357],{"id":28356},"core-commands","Core Commands",[20,28359,28360],{},"Vite+ handles the entire local frontend development cycle. Here's the workflow:",[47,28362,28364],{"className":758,"code":28363,"language":761,"meta":55,"style":55},"vp create        # Scaffold a new project\nvp install       # Install dependencies (auto-detects pnpm\u002Fnpm\u002Fyarn)\nvp dev           # Start the dev server\nvp check         # Format, lint, and type-check in one pass\nvp test          # Run tests with Vitest\nvp build         # Build for production\n",[39,28365,28366,28375,28384,28394,28403,28412],{"__ignoreMap":55},[250,28367,28368,28370,28372],{"class":252,"line":253},[250,28369,24571],{"class":774},[250,28371,24574],{"class":782},[250,28373,28374],{"class":768},"        # Scaffold a new project\n",[250,28376,28377,28379,28381],{"class":252,"line":113},[250,28378,24571],{"class":774},[250,28380,808],{"class":782},[250,28382,28383],{"class":768},"       # Install dependencies (auto-detects pnpm\u002Fnpm\u002Fyarn)\n",[250,28385,28386,28388,28391],{"class":252,"line":110},[250,28387,24571],{"class":774},[250,28389,28390],{"class":782}," dev",[250,28392,28393],{"class":768},"           # Start the dev server\n",[250,28395,28396,28398,28400],{"class":252,"line":269},[250,28397,24571],{"class":774},[250,28399,28012],{"class":782},[250,28401,28402],{"class":768},"         # Format, lint, and type-check in one pass\n",[250,28404,28405,28407,28409],{"class":252,"line":275},[250,28406,24571],{"class":774},[250,28408,28022],{"class":782},[250,28410,28411],{"class":768},"          # Run tests with Vitest\n",[250,28413,28414,28416,28419],{"class":252,"line":281},[250,28415,24571],{"class":774},[250,28417,28418],{"class":782}," build",[250,28420,28421],{"class":768},"         # Build for production\n",[20,28423,28424,28425,28427],{},"You can also run ",[39,28426,24571],{}," on its own for an interactive command picker.",[10834,28429,28430,28432],{},[2459,28431,12902],{"id":12901},[20,28433,28434,28435,7128,28438,7128,28440,7128,28443,7128,28446,28449,28450,28452],{},"Instead of configuring ",[39,28436,28437],{},"nvm",[39,28439,4226],{},[39,28441,28442],{},"vitest",[39,28444,28445],{},"eslint",[39,28447,28448],{},"prettier",", and build scripts separately, ",[39,28451,24571],{}," handles all of it with a consistent interface across every project.",[15,28454,28456,28457],{"id":28455},"format-lint-and-type-check-with-vp-check","Format, Lint, and Type-Check with ",[39,28458,28459],{},"vp check",[20,28461,28462],{},"One command runs all three — powered by Oxc under the hood:",[561,28464,28465,28471,28477],{},[564,28466,28467,28470],{},[546,28468,28469],{},"Prettier-compatible"," formatting via Oxfmt",[564,28472,28473,28476],{},[546,28474,28475],{},"600+ ESLint-compatible"," rules via Oxlint",[564,28478,28479,28482,28483],{},[546,28480,28481],{},"Type-aware linting"," and fast type checks via ",[39,28484,28485],{},"tsgo",[47,28487,28489],{"className":758,"code":28488,"language":761,"meta":55,"style":55},"vp check         # Run all checks\nvp check --fix   # Auto-fix where possible\n",[39,28490,28491,28500],{"__ignoreMap":55},[250,28492,28493,28495,28497],{"class":252,"line":253},[250,28494,24571],{"class":774},[250,28496,28012],{"class":782},[250,28498,28499],{"class":768},"         # Run all checks\n",[250,28501,28502,28504,28506,28509],{"class":252,"line":113},[250,28503,24571],{"class":774},[250,28505,28012],{"class":782},[250,28507,28508],{"class":778}," --fix",[250,28510,28511],{"class":768},"   # Auto-fix where possible\n",[24,28513,28514],{"type":26},[20,28515,28516,28518,28519,7128,28522,28525,28526,28528],{},[39,28517,28459],{}," runs format, lint, and type checks together in a single pass. To run them individually, use ",[39,28520,28521],{},"vp fmt",[39,28523,28524],{},"vp lint",", or invoke ",[39,28527,28485],{}," directly.",[15,28530,28532,28533],{"id":28531},"testing-with-vp-test","Testing with ",[39,28534,27357],{},[20,28536,28537],{},"Vitest is built in — no separate install or config needed. It reuses the same resolve and transform config from your application.",[561,28539,28540,28543,28546,28549],{},[564,28541,28542],{},"Jest-compatible API",[564,28544,28545],{},"Test isolation by default",[564,28547,28548],{},"Browser Mode: run unit tests in actual browsers",[564,28550,28551],{},"Coverage, snapshots, type tests, visual regression",[15,28553,28555,28556],{"id":28554},"monorepo-task-caching-with-vp-run","Monorepo Task Caching with ",[39,28557,28558],{},"vp run",[20,28560,28561,28562,28564],{},"For monorepos, ",[39,28563,28558],{}," provides automated caching and dependency-aware execution:",[47,28566,28568],{"className":758,"code":28567,"language":761,"meta":55,"style":55},"vp run build     # Run build across workspaces with caching\nvp run test      # Run tests with input tracking\n",[39,28569,28570,28581],{"__ignoreMap":55},[250,28571,28572,28574,28576,28578],{"class":252,"line":253},[250,28573,24571],{"class":774},[250,28575,1707],{"class":782},[250,28577,28418],{"class":782},[250,28579,28580],{"class":768},"     # Run build across workspaces with caching\n",[250,28582,28583,28585,28587,28589],{"class":252,"line":113},[250,28584,24571],{"class":774},[250,28586,1707],{"class":782},[250,28588,28022],{"class":782},[250,28590,28591],{"class":768},"      # Run tests with input tracking\n",[20,28593,28594],{},"Tasks are cached automatically based on input files — no Turborepo config needed.",[15,28596,28598,28599],{"id":28597},"library-packaging-with-vp-pack","Library Packaging with ",[39,28600,24502],{},[20,28602,28603,28604,28606],{},"Publishing a library? ",[39,28605,24502],{}," handles DTS generation, bundling, and automatic package exports:",[47,28608,28609],{"className":758,"code":27483,"language":761,"meta":55,"style":55},[39,28610,28611],{"__ignoreMap":55},[250,28612,28613,28615],{"class":252,"line":253},[250,28614,24571],{"class":774},[250,28616,27492],{"class":782},[20,28618,28619],{},"Powered by Rolldown \u002F tsdown, it outputs ESM, CJS, and declaration files.",[15,28621,28623],{"id":28622},"migrating-an-existing-vite-project","Migrating an Existing Vite Project",[20,28625,28626],{},"Already have a Vite project? Migrate it with:",[47,28628,28630],{"className":758,"code":28629,"language":761,"meta":55,"style":55},"vp migrate\n",[39,28631,28632],{"__ignoreMap":55},[250,28633,28634,28636],{"class":252,"line":253},[250,28635,24571],{"class":774},[250,28637,28638],{"class":782}," migrate\n",[20,28640,28641,28642,28647],{},"Or paste the ",[203,28643,28646],{"href":28644,"rel":28645},"https:\u002F\u002Fviteplus.dev\u002Fguide\u002Fmigrate#migration-prompt",[207],"migration prompt"," into your coding agent.",[15,28649,28651],{"id":28650},"deployment","Deployment",[20,28653,28654,28655,28659],{},"Vite+ pairs with ",[203,28656,555],{"href":28657,"rel":28658},"https:\u002F\u002Fnitro.unjs.io\u002F",[207]," for platform-agnostic deployment. First-class support for Vercel, Netlify, Cloudflare Workers, and Render.",[161,28661,28663],{"icon":3246,"title":28662},"Platform Agnostic",[20,28664,28665,28666,28669],{},"Build once with ",[39,28667,28668],{},"vp build"," and deploy anywhere — Nitro handles the server runtime transformation.",[15,28671,28673],{"id":28672},"why-vite","Why Vite+?",[561,28675,28676,28682,28688,28694,28700],{},[564,28677,28678,28681],{},[546,28679,28680],{},"Stop wasting time on tooling maintenance"," — one CLI, one config, one workflow",[564,28683,28684,28687],{},[546,28685,28686],{},"Improve cross-team mobility"," — consistent DX across every project",[564,28689,28690,28693],{},[546,28691,28692],{},"Stay fast at scale"," — Rust-powered internals, enterprise-grade performance",[564,28695,28696,28699],{},[546,28697,28698],{},"Supply chain security"," — rigorous dependency vetting across the unified toolchain",[564,28701,28702,28705],{},[546,28703,28704],{},"Free and open source"," — MIT license, maintained by VoidZero and community contributors",[72,28707],{},[20,28709,28710],{},"Vite+ isn't reinventing the wheel — it's putting high-performance tires on it. By unifying your runtime, package manager, linter, formatter, test runner, and bundler into a single CLI, it removes the tooling tax that slows down every new project.",[20,28712,28713,28714,2230],{},"If Vite was the upgrade from Webpack, Vite+ is the upgrade from ",[3587,28715,28716],{},"tool fatigue",[500,28718,28719],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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}",{"title":55,"searchDepth":110,"depth":110,"links":28721},[28722,28723],{"id":21217,"depth":113,"text":21218},{"id":28335,"depth":113,"text":28336,"children":28724},[28725],{"id":12901,"depth":110,"text":12902},"Vite+ combines Vite, Vitest, Oxlint, Oxfmt, and Rolldown into a single CLI — managing your runtime, package manager, and toolchain in one place.",{"type":12,"value":28728},[28729,28731,28733],[15,28730,541],{"id":540},[20,28732,28171],{},[20,28734,28735,28176,28737,28182,28740,2230],{},[546,28736,24498],{},[203,28738,28181],{"href":28179,"rel":28739},[207],[39,28741,24571],{},[28150,126,28743,28744,3509,8234,28745,28442,28746],"frontend","toolchain","oxc","rolldown",{},"\u002Fblog\u002Fviteplus-unified-toolchain",{"title":28162,"description":28726},"blog\u002Fviteplus-unified-toolchain","Sg_ro7CXnz7y9Ugam_dig_kH9YpHYV1P7cVDEIlkyKE",{"id":28753,"title":28754,"author":28755,"body":28756,"canonical":115,"categories":115,"date":11328,"description":28766,"excerpt":115,"extension":118,"img":119,"keywords":115,"language":115,"meta":28767,"navigation":129,"ogImage":115,"path":28768,"rating":115,"readTime":115,"seo":28769,"stem":28770,"tag":28771,"__hash__":28772},"blog\u002Fblog\u002Fwork-in-progress.md","Work in Progress",{"name":8,"img":10},{"type":12,"value":28757,"toc":28764},[28758,28761],[15,28759,28754],{"id":28760},"work-in-progress",[20,28762,28763],{},"This post is currently under construction. Check back soon!",{"title":55,"searchDepth":110,"depth":110,"links":28765},[],"A placeholder for an upcoming post.",{},"\u002Fblog\u002Fwork-in-progress",{"title":28754,"description":28766},"blog\u002Fwork-in-progress","General","D2XqR3BH1UxjrAkn93_s4Kxi2i8goOhVluLzMwmSYLA",{"id":4080,"title":4081,"author":28774,"body":28775,"canonical":115,"categories":115,"date":3470,"description":8209,"excerpt":32354,"extension":118,"img":3502,"keywords":32372,"language":3510,"meta":32373,"navigation":129,"ogImage":115,"path":8236,"rating":275,"readTime":316,"seo":32374,"stem":8238,"tag":3515,"__hash__":8239},{"name":8,"img":10,"website":535},{"type":12,"value":28776,"toc":32329},[28777,28779,28783,28787,28789,28793,28795,28797,28819,28823,28825,28827,28829,28831,28839,28841,28843,28845,28897,28901,28903,28905,28907,28911,28985,28987,28989,28991,29005,29009,29573,29577,29579,29581,29583,29587,29833,29835,29837,29839,29843,30225,30227,30229,30231,30235,30319,30321,30325,30537,30539,30541,30545,31339,31341,31345,31815,31817,31821,32025,32027,32029,32031,32063,32071,32073,32075,32077,32089,32091,32105,32107,32117,32119,32173,32175,32205,32207,32209,32211,32223,32225,32299,32301,32303,32307,32309,32323,32327],[15,28778,541],{"id":540},[20,28780,4089,28781,4093],{},[546,28782,4092],{},[20,28784,4096,28785,4100],{},[546,28786,4099],{},[20,28788,4103],{},[20,28790,4106,28791,4110],{},[546,28792,4109],{},[15,28794,4114],{"id":4113},[20,28796,4117],{},[561,28798,28799,28803,28807,28811,28815],{},[564,28800,28801,4125],{},[546,28802,4124],{},[564,28804,28805,4131],{},[546,28806,4130],{},[564,28808,28809,4137],{},[546,28810,4136],{},[564,28812,28813,4143],{},[546,28814,4142],{},[564,28816,28817,4149],{},[546,28818,4148],{},[24,28820,28821],{"type":631},[20,28822,4154],{},[72,28824],{},[15,28826,748],{"id":747},[31,28828,4162],{"id":4161},[20,28830,4165],{},[561,28832,28833,28835,28837],{},[564,28834,4170],{},[564,28836,4173],{},[564,28838,4176],{},[72,28840],{},[31,28842,4182],{"id":4181},[20,28844,4185],{},[47,28846,28847],{"className":758,"code":4188,"filename":760,"language":761,"meta":55,"style":55},[39,28848,28849,28853,28861,28867,28871,28875,28885],{"__ignoreMap":55},[250,28850,28851],{"class":252,"line":253},[250,28852,4195],{"class":768},[250,28854,28855,28857,28859],{"class":252,"line":113},[250,28856,4200],{"class":774},[250,28858,4203],{"class":782},[250,28860,4206],{"class":782},[250,28862,28863,28865],{"class":252,"line":110},[250,28864,874],{"class":778},[250,28866,4206],{"class":782},[250,28868,28869],{"class":252,"line":269},[250,28870,795],{"emptyLinePlaceholder":129},[250,28872,28873],{"class":252,"line":275},[250,28874,4221],{"class":768},[250,28876,28877,28879,28881,28883],{"class":252,"line":281},[250,28878,4226],{"class":774},[250,28880,808],{"class":782},[250,28882,4231],{"class":782},[250,28884,4234],{"class":782},[250,28886,28887,28889,28891,28893,28895],{"class":252,"line":287},[250,28888,4226],{"class":774},[250,28890,808],{"class":782},[250,28892,4243],{"class":778},[250,28894,4246],{"class":782},[250,28896,4249],{"class":782},[24,28898,28899],{"type":26},[20,28900,4254],{},[72,28902],{},[31,28904,4260],{"id":4259},[20,28906,4263],{},[20,28908,1092,28909,1007],{},[39,28910,4268],{},[47,28912,28913],{"className":1010,"code":4271,"filename":4268,"language":1012,"meta":55,"style":55},[39,28914,28915,28927,28931,28941,28949,28957,28965,28969,28977,28981],{"__ignoreMap":55},[250,28916,28917,28919,28921,28923,28925],{"class":252,"line":253},[250,28918,1763],{"class":786},[250,28920,4280],{"class":912},[250,28922,1769],{"class":786},[250,28924,4285],{"class":782},[250,28926,1379],{"class":912},[250,28928,28929],{"class":252,"line":113},[250,28930,795],{"emptyLinePlaceholder":129},[250,28932,28933,28935,28937,28939],{"class":252,"line":110},[250,28934,1019],{"class":786},[250,28936,1022],{"class":786},[250,28938,4300],{"class":774},[250,28940,1028],{"class":912},[250,28942,28943,28945,28947],{"class":252,"line":269},[250,28944,4307],{"class":912},[250,28946,4310],{"class":782},[250,28948,927],{"class":912},[250,28950,28951,28953,28955],{"class":252,"line":275},[250,28952,4317],{"class":912},[250,28954,4320],{"class":782},[250,28956,927],{"class":912},[250,28958,28959,28961,28963],{"class":252,"line":281},[250,28960,4327],{"class":912},[250,28962,4330],{"class":782},[250,28964,927],{"class":912},[250,28966,28967],{"class":252,"line":287},[250,28968,4337],{"class":912},[250,28970,28971,28973,28975],{"class":252,"line":293},[250,28972,4342],{"class":912},[250,28974,4345],{"class":782},[250,28976,927],{"class":912},[250,28978,28979],{"class":252,"line":299},[250,28980,1048],{"class":912},[250,28982,28983],{"class":252,"line":132},[250,28984,1077],{"class":912},[72,28986],{},[31,28988,4361],{"id":4360},[20,28990,4364],{},[561,28992,28993,28997,29001],{},[564,28994,28995,4372],{},[546,28996,4371],{},[564,28998,28999,4378],{},[546,29000,4377],{},[564,29002,29003,4384],{},[546,29004,4383],{},[20,29006,1092,29007,1007],{},[39,29008,4389],{},[47,29010,29011],{"className":1010,"code":4392,"filename":4389,"language":1012,"meta":55,"style":55},[39,29012,29013,29025,29037,29041,29045,29063,29079,29095,29107,29123,29141,29165,29181,29195,29199,29203,29207,29225,29241,29267,29279,29295,29311,29325,29341,29355,29359,29363,29367,29385,29401,29413,29421,29433,29445,29453,29465,29489,29505,29509,29513,29517,29531,29545,29559],{"__ignoreMap":55},[250,29014,29015,29017,29019,29021,29023],{"class":252,"line":253},[250,29016,1763],{"class":786},[250,29018,4401],{"class":912},[250,29020,1769],{"class":786},[250,29022,4406],{"class":782},[250,29024,1379],{"class":912},[250,29026,29027,29029,29031,29033,29035],{"class":252,"line":113},[250,29028,1763],{"class":786},[250,29030,4415],{"class":912},[250,29032,1769],{"class":786},[250,29034,4420],{"class":782},[250,29036,1379],{"class":912},[250,29038,29039],{"class":252,"line":110},[250,29040,795],{"emptyLinePlaceholder":129},[250,29042,29043],{"class":252,"line":269},[250,29044,4431],{"class":768},[250,29046,29047,29049,29051,29053,29055,29057,29059,29061],{"class":252,"line":275},[250,29048,1019],{"class":786},[250,29050,4438],{"class":786},[250,29052,4441],{"class":778},[250,29054,1187],{"class":786},[250,29056,4446],{"class":774},[250,29058,1434],{"class":912},[250,29060,4451],{"class":782},[250,29062,4454],{"class":912},[250,29064,29065,29067,29069,29071,29073,29075,29077],{"class":252,"line":281},[250,29066,4459],{"class":912},[250,29068,52],{"class":774},[250,29070,1434],{"class":912},[250,29072,4466],{"class":782},[250,29074,2380],{"class":912},[250,29076,4471],{"class":774},[250,29078,1156],{"class":912},[250,29080,29081,29083,29085,29087,29089,29091,29093],{"class":252,"line":287},[250,29082,4478],{"class":912},[250,29084,52],{"class":774},[250,29086,1434],{"class":912},[250,29088,4485],{"class":782},[250,29090,2380],{"class":912},[250,29092,4490],{"class":774},[250,29094,1156],{"class":912},[250,29096,29097,29099,29101,29103,29105],{"class":252,"line":293},[250,29098,4497],{"class":912},[250,29100,52],{"class":774},[250,29102,1434],{"class":912},[250,29104,4504],{"class":782},[250,29106,4507],{"class":912},[250,29108,29109,29111,29113,29115,29117,29119,29121],{"class":252,"line":299},[250,29110,4512],{"class":912},[250,29112,4515],{"class":774},[250,29114,1434],{"class":912},[250,29116,4520],{"class":782},[250,29118,2380],{"class":912},[250,29120,4490],{"class":774},[250,29122,1156],{"class":912},[250,29124,29125,29127,29129,29131,29133,29135,29137,29139],{"class":252,"line":132},[250,29126,4531],{"class":912},[250,29128,52],{"class":774},[250,29130,1434],{"class":912},[250,29132,4538],{"class":782},[250,29134,2380],{"class":912},[250,29136,4490],{"class":774},[250,29138,4545],{"class":912},[250,29140,4548],{"class":768},[250,29142,29143,29145,29147,29149,29151,29153,29155,29157,29159,29161,29163],{"class":252,"line":310},[250,29144,4553],{"class":912},[250,29146,4556],{"class":774},[250,29148,1434],{"class":912},[250,29150,4561],{"class":782},[250,29152,4564],{"class":912},[250,29154,4567],{"class":782},[250,29156,4570],{"class":912},[250,29158,4573],{"class":774},[250,29160,1434],{"class":912},[250,29162,1066],{"class":778},[250,29164,4507],{"class":912},[250,29166,29167,29169,29171,29173,29175,29177,29179],{"class":252,"line":316},[250,29168,4584],{"class":912},[250,29170,4556],{"class":774},[250,29172,1434],{"class":912},[250,29174,4591],{"class":782},[250,29176,4564],{"class":912},[250,29178,4596],{"class":782},[250,29180,4599],{"class":912},[250,29182,29183,29185,29187,29189,29191,29193],{"class":252,"line":322},[250,29184,4604],{"class":912},[250,29186,4573],{"class":774},[250,29188,1434],{"class":912},[250,29190,4611],{"class":774},[250,29192,4614],{"class":782},[250,29194,4507],{"class":912},[250,29196,29197],{"class":252,"line":328},[250,29198,1077],{"class":912},[250,29200,29201],{"class":252,"line":334},[250,29202,795],{"emptyLinePlaceholder":129},[250,29204,29205],{"class":252,"line":340},[250,29206,4629],{"class":768},[250,29208,29209,29211,29213,29215,29217,29219,29221,29223],{"class":252,"line":346},[250,29210,1019],{"class":786},[250,29212,4438],{"class":786},[250,29214,1405],{"class":778},[250,29216,1187],{"class":786},[250,29218,4446],{"class":774},[250,29220,1434],{"class":912},[250,29222,4646],{"class":782},[250,29224,4454],{"class":912},[250,29226,29227,29229,29231,29233,29235,29237,29239],{"class":252,"line":352},[250,29228,4459],{"class":912},[250,29230,52],{"class":774},[250,29232,1434],{"class":912},[250,29234,4466],{"class":782},[250,29236,2380],{"class":912},[250,29238,4471],{"class":774},[250,29240,1156],{"class":912},[250,29242,29243,29245,29247,29249,29251,29253,29255,29257,29259,29261,29263,29265],{"class":252,"line":358},[250,29244,4669],{"class":912},[250,29246,52],{"class":774},[250,29248,1434],{"class":912},[250,29250,4676],{"class":782},[250,29252,2380],{"class":912},[250,29254,4490],{"class":774},[250,29256,1647],{"class":912},[250,29258,4573],{"class":774},[250,29260,1434],{"class":912},[250,29262,1631],{"class":782},[250,29264,4691],{"class":912},[250,29266,4694],{"class":768},[250,29268,29269,29271,29273,29275,29277],{"class":252,"line":364},[250,29270,4699],{"class":912},[250,29272,52],{"class":774},[250,29274,1434],{"class":912},[250,29276,4706],{"class":782},[250,29278,4507],{"class":912},[250,29280,29281,29283,29285,29287,29289,29291,29293],{"class":252,"line":370},[250,29282,4713],{"class":912},[250,29284,4515],{"class":774},[250,29286,1434],{"class":912},[250,29288,4720],{"class":782},[250,29290,2380],{"class":912},[250,29292,4490],{"class":774},[250,29294,1156],{"class":912},[250,29296,29297,29299,29301,29303,29305,29307,29309],{"class":252,"line":376},[250,29298,4584],{"class":912},[250,29300,4556],{"class":774},[250,29302,1434],{"class":912},[250,29304,4591],{"class":782},[250,29306,4564],{"class":912},[250,29308,4596],{"class":782},[250,29310,4599],{"class":912},[250,29312,29313,29315,29317,29319,29321,29323],{"class":252,"line":382},[250,29314,4604],{"class":912},[250,29316,4573],{"class":774},[250,29318,1434],{"class":912},[250,29320,4611],{"class":774},[250,29322,4614],{"class":782},[250,29324,4507],{"class":912},[250,29326,29327,29329,29331,29333,29335,29337,29339],{"class":252,"line":388},[250,29328,4761],{"class":912},[250,29330,4556],{"class":774},[250,29332,1434],{"class":912},[250,29334,4768],{"class":782},[250,29336,4564],{"class":912},[250,29338,4596],{"class":782},[250,29340,4599],{"class":912},[250,29342,29343,29345,29347,29349,29351,29353],{"class":252,"line":393},[250,29344,4604],{"class":912},[250,29346,4573],{"class":774},[250,29348,1434],{"class":912},[250,29350,4611],{"class":774},[250,29352,4614],{"class":782},[250,29354,4507],{"class":912},[250,29356,29357],{"class":252,"line":399},[250,29358,1077],{"class":912},[250,29360,29361],{"class":252,"line":405},[250,29362,795],{"emptyLinePlaceholder":129},[250,29364,29365],{"class":252,"line":410},[250,29366,4801],{"class":768},[250,29368,29369,29371,29373,29375,29377,29379,29381,29383],{"class":252,"line":415},[250,29370,1019],{"class":786},[250,29372,4438],{"class":786},[250,29374,4810],{"class":778},[250,29376,1187],{"class":786},[250,29378,4446],{"class":774},[250,29380,1434],{"class":912},[250,29382,4819],{"class":782},[250,29384,4454],{"class":912},[250,29386,29387,29389,29391,29393,29395,29397,29399],{"class":252,"line":420},[250,29388,4459],{"class":912},[250,29390,52],{"class":774},[250,29392,1434],{"class":912},[250,29394,4466],{"class":782},[250,29396,2380],{"class":912},[250,29398,4471],{"class":774},[250,29400,1156],{"class":912},[250,29402,29403,29405,29407,29409,29411],{"class":252,"line":426},[250,29404,4842],{"class":912},[250,29406,52],{"class":774},[250,29408,1434],{"class":912},[250,29410,4849],{"class":782},[250,29412,4852],{"class":912},[250,29414,29415,29417,29419],{"class":252,"line":431},[250,29416,4604],{"class":912},[250,29418,4490],{"class":774},[250,29420,4861],{"class":912},[250,29422,29423,29425,29427,29429,29431],{"class":252,"line":436},[250,29424,4604],{"class":912},[250,29426,4868],{"class":774},[250,29428,1112],{"class":912},[250,29430,1115],{"class":786},[250,29432,4875],{"class":912},[250,29434,29435,29437,29439,29441,29443],{"class":252,"line":442},[250,29436,4880],{"class":912},[250,29438,52],{"class":774},[250,29440,1434],{"class":912},[250,29442,4887],{"class":782},[250,29444,4852],{"class":912},[250,29446,29447,29449,29451],{"class":252,"line":447},[250,29448,4604],{"class":912},[250,29450,4490],{"class":774},[250,29452,4861],{"class":912},[250,29454,29455,29457,29459,29461,29463],{"class":252,"line":453},[250,29456,4604],{"class":912},[250,29458,4868],{"class":774},[250,29460,1112],{"class":912},[250,29462,1115],{"class":786},[250,29464,4910],{"class":912},[250,29466,29467,29469,29471,29473,29475,29477,29479,29481,29483,29485,29487],{"class":252,"line":459},[250,29468,4915],{"class":912},[250,29470,4556],{"class":774},[250,29472,1434],{"class":912},[250,29474,4922],{"class":782},[250,29476,2380],{"class":912},[250,29478,4490],{"class":774},[250,29480,1647],{"class":912},[250,29482,4573],{"class":774},[250,29484,1434],{"class":912},[250,29486,1198],{"class":778},[250,29488,4507],{"class":912},[250,29490,29491,29493,29495,29497,29499,29501,29503],{"class":252,"line":465},[250,29492,4941],{"class":912},[250,29494,4515],{"class":774},[250,29496,1434],{"class":912},[250,29498,4948],{"class":782},[250,29500,2380],{"class":912},[250,29502,4490],{"class":774},[250,29504,1156],{"class":912},[250,29506,29507],{"class":252,"line":471},[250,29508,1077],{"class":912},[250,29510,29511],{"class":252,"line":2201},[250,29512,795],{"emptyLinePlaceholder":129},[250,29514,29515],{"class":252,"line":2207},[250,29516,4967],{"class":768},[250,29518,29519,29521,29523,29525,29527,29529],{"class":252,"line":2213},[250,29520,1019],{"class":786},[250,29522,4974],{"class":786},[250,29524,4977],{"class":774},[250,29526,1187],{"class":786},[250,29528,4982],{"class":786},[250,29530,4985],{"class":912},[250,29532,29533,29535,29537,29539,29541,29543],{"class":252,"line":2218},[250,29534,1019],{"class":786},[250,29536,4974],{"class":786},[250,29538,4994],{"class":774},[250,29540,1187],{"class":786},[250,29542,4982],{"class":786},[250,29544,5001],{"class":912},[250,29546,29547,29549,29551,29553,29555,29557],{"class":252,"line":2223},[250,29548,1019],{"class":786},[250,29550,4974],{"class":786},[250,29552,5010],{"class":774},[250,29554,1187],{"class":786},[250,29556,4982],{"class":786},[250,29558,5017],{"class":912},[250,29560,29561,29563,29565,29567,29569,29571],{"class":252,"line":2239},[250,29562,1019],{"class":786},[250,29564,4974],{"class":786},[250,29566,5026],{"class":774},[250,29568,1187],{"class":786},[250,29570,4982],{"class":786},[250,29572,5033],{"class":912},[161,29574,29575],{"icon":5036,"title":5037},[20,29576,5040],{},[72,29578],{},[31,29580,5046],{"id":5045},[20,29582,5049],{},[20,29584,1092,29585,1007],{},[39,29586,5054],{},[47,29588,29589],{"className":1010,"code":5057,"filename":5054,"language":1012,"meta":55,"style":55},[39,29590,29591,29603,29615,29631,29635,29653,29667,29671,29675,29685,29695,29699,29703,29707,29711,29715,29719,29723,29727,29731,29735,29739,29743,29747,29751,29755,29759,29763,29767,29771,29775,29779,29783,29787,29791,29795,29799,29803,29807,29813,29817,29829],{"__ignoreMap":55},[250,29592,29593,29595,29597,29599,29601],{"class":252,"line":253},[250,29594,1763],{"class":786},[250,29596,5066],{"class":912},[250,29598,1769],{"class":786},[250,29600,5071],{"class":782},[250,29602,1379],{"class":912},[250,29604,29605,29607,29609,29611,29613],{"class":252,"line":113},[250,29606,1763],{"class":786},[250,29608,5080],{"class":912},[250,29610,1769],{"class":786},[250,29612,5085],{"class":782},[250,29614,1379],{"class":912},[250,29616,29617,29619,29621,29623,29625,29627,29629],{"class":252,"line":110},[250,29618,1763],{"class":786},[250,29620,5094],{"class":778},[250,29622,5097],{"class":786},[250,29624,5100],{"class":912},[250,29626,1769],{"class":786},[250,29628,5105],{"class":782},[250,29630,1379],{"class":912},[250,29632,29633],{"class":252,"line":269},[250,29634,795],{"emptyLinePlaceholder":129},[250,29636,29637,29639,29641,29643,29645,29647,29649,29651],{"class":252,"line":275},[250,29638,1181],{"class":786},[250,29640,5118],{"class":778},[250,29642,1187],{"class":786},[250,29644,1568],{"class":786},[250,29646,5125],{"class":774},[250,29648,1434],{"class":912},[250,29650,5130],{"class":782},[250,29652,1885],{"class":912},[250,29654,29655,29657,29659,29661,29663,29665],{"class":252,"line":281},[250,29656,1019],{"class":786},[250,29658,4438],{"class":786},[250,29660,5141],{"class":778},[250,29662,1187],{"class":786},[250,29664,5146],{"class":774},[250,29666,5149],{"class":912},[250,29668,29669],{"class":252,"line":287},[250,29670,795],{"emptyLinePlaceholder":129},[250,29672,29673],{"class":252,"line":293},[250,29674,5158],{"class":768},[250,29676,29677,29679,29681,29683],{"class":252,"line":299},[250,29678,1019],{"class":786},[250,29680,1845],{"class":786},[250,29682,5167],{"class":774},[250,29684,1851],{"class":912},[250,29686,29687,29689,29691,29693],{"class":252,"line":132},[250,29688,5174],{"class":912},[250,29690,5177],{"class":774},[250,29692,1434],{"class":912},[250,29694,5182],{"class":782},[250,29696,29697],{"class":252,"line":310},[250,29698,5187],{"class":782},[250,29700,29701],{"class":252,"line":316},[250,29702,5192],{"class":782},[250,29704,29705],{"class":252,"line":322},[250,29706,5197],{"class":782},[250,29708,29709],{"class":252,"line":328},[250,29710,5202],{"class":782},[250,29712,29713],{"class":252,"line":334},[250,29714,5207],{"class":782},[250,29716,29717],{"class":252,"line":340},[250,29718,5212],{"class":782},[250,29720,29721],{"class":252,"line":346},[250,29722,5217],{"class":782},[250,29724,29725],{"class":252,"line":352},[250,29726,5222],{"class":782},[250,29728,29729],{"class":252,"line":358},[250,29730,2210],{"class":782},[250,29732,29733],{"class":252,"line":364},[250,29734,795],{"emptyLinePlaceholder":129},[250,29736,29737],{"class":252,"line":370},[250,29738,5235],{"class":782},[250,29740,29741],{"class":252,"line":376},[250,29742,5192],{"class":782},[250,29744,29745],{"class":252,"line":382},[250,29746,5244],{"class":782},[250,29748,29749],{"class":252,"line":388},[250,29750,5249],{"class":782},[250,29752,29753],{"class":252,"line":393},[250,29754,5254],{"class":782},[250,29756,29757],{"class":252,"line":399},[250,29758,5259],{"class":782},[250,29760,29761],{"class":252,"line":405},[250,29762,5264],{"class":782},[250,29764,29765],{"class":252,"line":410},[250,29766,2210],{"class":782},[250,29768,29769],{"class":252,"line":415},[250,29770,795],{"emptyLinePlaceholder":129},[250,29772,29773],{"class":252,"line":420},[250,29774,5277],{"class":782},[250,29776,29777],{"class":252,"line":426},[250,29778,5192],{"class":782},[250,29780,29781],{"class":252,"line":431},[250,29782,5286],{"class":782},[250,29784,29785],{"class":252,"line":436},[250,29786,5291],{"class":782},[250,29788,29789],{"class":252,"line":442},[250,29790,5296],{"class":782},[250,29792,29793],{"class":252,"line":447},[250,29794,5301],{"class":782},[250,29796,29797],{"class":252,"line":453},[250,29798,5306],{"class":782},[250,29800,29801],{"class":252,"line":459},[250,29802,5311],{"class":782},[250,29804,29805],{"class":252,"line":465},[250,29806,2210],{"class":782},[250,29808,29809,29811],{"class":252,"line":471},[250,29810,5320],{"class":782},[250,29812,1885],{"class":912},[250,29814,29815],{"class":252,"line":2201},[250,29816,1053],{"class":912},[250,29818,29819,29821,29823,29825,29827],{"class":252,"line":2207},[250,29820,1856],{"class":912},[250,29822,1859],{"class":774},[250,29824,1434],{"class":912},[250,29826,5337],{"class":782},[250,29828,1885],{"class":912},[250,29830,29831],{"class":252,"line":2213},[250,29832,991],{"class":912},[72,29834],{},[31,29836,5349],{"id":5348},[20,29838,5352],{},[20,29840,1092,29841,1007],{},[39,29842,5357],{},[47,29844,29845],{"className":1010,"code":5360,"filename":5357,"language":1012,"meta":55,"style":55},[39,29846,29847,29859,29871,29875,29885,29909,29933,29957,29981,30005,30029,30053,30077,30101,30105,30109,30127,30131,30145,30149,30153,30167,30181,30187,30195,30199,30203,30207,30221],{"__ignoreMap":55},[250,29848,29849,29851,29853,29855,29857],{"class":252,"line":253},[250,29850,1763],{"class":786},[250,29852,5369],{"class":912},[250,29854,1769],{"class":786},[250,29856,5374],{"class":782},[250,29858,1379],{"class":912},[250,29860,29861,29863,29865,29867,29869],{"class":252,"line":113},[250,29862,1763],{"class":786},[250,29864,5383],{"class":912},[250,29866,1769],{"class":786},[250,29868,5388],{"class":782},[250,29870,1379],{"class":912},[250,29872,29873],{"class":252,"line":110},[250,29874,795],{"emptyLinePlaceholder":129},[250,29876,29877,29879,29881,29883],{"class":252,"line":269},[250,29878,1181],{"class":786},[250,29880,5401],{"class":778},[250,29882,1187],{"class":786},[250,29884,1190],{"class":912},[250,29886,29887,29889,29891,29893,29895,29897,29899,29901,29903,29905,29907],{"class":252,"line":275},[250,29888,1195],{"class":912},[250,29890,5412],{"class":782},[250,29892,1201],{"class":912},[250,29894,1204],{"class":782},[250,29896,5419],{"class":912},[250,29898,5422],{"class":782},[250,29900,1207],{"class":912},[250,29902,1210],{"class":778},[250,29904,1213],{"class":912},[250,29906,1216],{"class":782},[250,29908,1219],{"class":912},[250,29910,29911,29913,29915,29917,29919,29921,29923,29925,29927,29929,29931],{"class":252,"line":281},[250,29912,1195],{"class":912},[250,29914,5439],{"class":782},[250,29916,1201],{"class":912},[250,29918,1231],{"class":782},[250,29920,5419],{"class":912},[250,29922,5448],{"class":782},[250,29924,1207],{"class":912},[250,29926,1236],{"class":778},[250,29928,1213],{"class":912},[250,29930,1216],{"class":782},[250,29932,1219],{"class":912},[250,29934,29935,29937,29939,29941,29943,29945,29947,29949,29951,29953,29955],{"class":252,"line":287},[250,29936,1195],{"class":912},[250,29938,5465],{"class":782},[250,29940,1201],{"class":912},[250,29942,5470],{"class":782},[250,29944,5419],{"class":912},[250,29946,5475],{"class":782},[250,29948,1207],{"class":912},[250,29950,1259],{"class":778},[250,29952,1213],{"class":912},[250,29954,1216],{"class":782},[250,29956,1219],{"class":912},[250,29958,29959,29961,29963,29965,29967,29969,29971,29973,29975,29977,29979],{"class":252,"line":293},[250,29960,1195],{"class":912},[250,29962,5492],{"class":782},[250,29964,1201],{"class":912},[250,29966,5497],{"class":782},[250,29968,5419],{"class":912},[250,29970,5502],{"class":782},[250,29972,1207],{"class":912},[250,29974,1210],{"class":778},[250,29976,1213],{"class":912},[250,29978,1216],{"class":782},[250,29980,1219],{"class":912},[250,29982,29983,29985,29987,29989,29991,29993,29995,29997,29999,30001,30003],{"class":252,"line":299},[250,29984,1195],{"class":912},[250,29986,5519],{"class":782},[250,29988,1201],{"class":912},[250,29990,1278],{"class":782},[250,29992,5419],{"class":912},[250,29994,5528],{"class":782},[250,29996,1207],{"class":912},[250,29998,1283],{"class":778},[250,30000,1213],{"class":912},[250,30002,1288],{"class":782},[250,30004,1219],{"class":912},[250,30006,30007,30009,30011,30013,30015,30017,30019,30021,30023,30025,30027],{"class":252,"line":132},[250,30008,1195],{"class":912},[250,30010,5545],{"class":782},[250,30012,1201],{"class":912},[250,30014,5550],{"class":782},[250,30016,5419],{"class":912},[250,30018,5555],{"class":782},[250,30020,1207],{"class":912},[250,30022,1259],{"class":778},[250,30024,1213],{"class":912},[250,30026,1288],{"class":782},[250,30028,1219],{"class":912},[250,30030,30031,30033,30035,30037,30039,30041,30043,30045,30047,30049,30051],{"class":252,"line":310},[250,30032,1195],{"class":912},[250,30034,5572],{"class":782},[250,30036,1201],{"class":912},[250,30038,1254],{"class":782},[250,30040,5419],{"class":912},[250,30042,5581],{"class":782},[250,30044,1207],{"class":912},[250,30046,1259],{"class":778},[250,30048,1213],{"class":912},[250,30050,1264],{"class":782},[250,30052,1219],{"class":912},[250,30054,30055,30057,30059,30061,30063,30065,30067,30069,30071,30073,30075],{"class":252,"line":316},[250,30056,1195],{"class":912},[250,30058,5598],{"class":782},[250,30060,1201],{"class":912},[250,30062,5603],{"class":782},[250,30064,5419],{"class":912},[250,30066,5608],{"class":782},[250,30068,1207],{"class":912},[250,30070,1236],{"class":778},[250,30072,1213],{"class":912},[250,30074,1264],{"class":782},[250,30076,1219],{"class":912},[250,30078,30079,30081,30083,30085,30087,30089,30091,30093,30095,30097,30099],{"class":252,"line":322},[250,30080,1195],{"class":912},[250,30082,5625],{"class":782},[250,30084,1201],{"class":912},[250,30086,5630],{"class":782},[250,30088,5419],{"class":912},[250,30090,5635],{"class":782},[250,30092,1207],{"class":912},[250,30094,1283],{"class":778},[250,30096,1213],{"class":912},[250,30098,1264],{"class":782},[250,30100,1219],{"class":912},[250,30102,30103],{"class":252,"line":328},[250,30104,1317],{"class":912},[250,30106,30107],{"class":252,"line":334},[250,30108,795],{"emptyLinePlaceholder":129},[250,30110,30111,30113,30115,30117,30119,30121,30123,30125],{"class":252,"line":340},[250,30112,1019],{"class":786},[250,30114,1022],{"class":786},[250,30116,1109],{"class":774},[250,30118,1434],{"class":912},[250,30120,1437],{"class":786},[250,30122,2015],{"class":912},[250,30124,1115],{"class":786},[250,30126,1118],{"class":912},[250,30128,30129],{"class":252,"line":346},[250,30130,5676],{"class":768},[250,30132,30133,30135,30137,30139,30141,30143],{"class":252,"line":352},[250,30134,1565],{"class":786},[250,30136,5683],{"class":912},[250,30138,5686],{"class":774},[250,30140,5689],{"class":912},[250,30142,5692],{"class":774},[250,30144,1906],{"class":912},[250,30146,30147],{"class":252,"line":358},[250,30148,1053],{"class":912},[250,30150,30151],{"class":252,"line":364},[250,30152,5703],{"class":768},[250,30154,30155,30157,30159,30161,30163,30165],{"class":252,"line":370},[250,30156,1944],{"class":786},[250,30158,1440],{"class":912},[250,30160,1181],{"class":786},[250,30162,5714],{"class":778},[250,30164,5717],{"class":786},[250,30166,5720],{"class":912},[250,30168,30169,30171,30173,30175,30177,30179],{"class":252,"line":376},[250,30170,5725],{"class":786},[250,30172,5683],{"class":912},[250,30174,5730],{"class":774},[250,30176,5689],{"class":912},[250,30178,5735],{"class":774},[250,30180,1028],{"class":912},[250,30182,30183,30185],{"class":252,"line":382},[250,30184,5742],{"class":786},[250,30186,5745],{"class":912},[250,30188,30189,30191,30193],{"class":252,"line":388},[250,30190,5750],{"class":912},[250,30192,1066],{"class":778},[250,30194,927],{"class":912},[250,30196,30197],{"class":252,"line":393},[250,30198,1547],{"class":912},[250,30200,30201],{"class":252,"line":399},[250,30202,986],{"class":912},[250,30204,30205],{"class":252,"line":405},[250,30206,1053],{"class":912},[250,30208,30209,30211,30213,30215,30217,30219],{"class":252,"line":410},[250,30210,1123],{"class":786},[250,30212,5773],{"class":912},[250,30214,5776],{"class":782},[250,30216,5779],{"class":912},[250,30218,1503],{"class":778},[250,30220,5784],{"class":912},[250,30222,30223],{"class":252,"line":415},[250,30224,1077],{"class":912},[72,30226],{},[31,30228,5794],{"id":5793},[2459,30230,5798],{"id":5797},[20,30232,1092,30233,1007],{},[39,30234,5803],{},[47,30236,30237],{"className":1010,"code":5806,"filename":5803,"language":1012,"meta":55,"style":55},[39,30238,30239,30251,30263,30267,30285,30309,30315],{"__ignoreMap":55},[250,30240,30241,30243,30245,30247,30249],{"class":252,"line":253},[250,30242,1763],{"class":786},[250,30244,5369],{"class":912},[250,30246,1769],{"class":786},[250,30248,5374],{"class":782},[250,30250,1379],{"class":912},[250,30252,30253,30255,30257,30259,30261],{"class":252,"line":113},[250,30254,1763],{"class":786},[250,30256,5383],{"class":912},[250,30258,1769],{"class":786},[250,30260,5388],{"class":782},[250,30262,1379],{"class":912},[250,30264,30265],{"class":252,"line":110},[250,30266,795],{"emptyLinePlaceholder":129},[250,30268,30269,30271,30273,30275,30277,30279,30281,30283],{"class":252,"line":269},[250,30270,1019],{"class":786},[250,30272,1022],{"class":786},[250,30274,1109],{"class":774},[250,30276,1434],{"class":912},[250,30278,1437],{"class":786},[250,30280,2015],{"class":912},[250,30282,1115],{"class":786},[250,30284,1118],{"class":912},[250,30286,30287,30289,30291,30293,30295,30297,30299,30301,30303,30305,30307],{"class":252,"line":275},[250,30288,1455],{"class":786},[250,30290,5861],{"class":778},[250,30292,1187],{"class":786},[250,30294,1463],{"class":786},[250,30296,5683],{"class":912},[250,30298,5870],{"class":774},[250,30300,1647],{"class":912},[250,30302,1769],{"class":774},[250,30304,5689],{"class":912},[250,30306,5879],{"class":774},[250,30308,5882],{"class":912},[250,30310,30311,30313],{"class":252,"line":281},[250,30312,1123],{"class":786},[250,30314,5889],{"class":912},[250,30316,30317],{"class":252,"line":287},[250,30318,1077],{"class":912},[2459,30320,5897],{"id":5896},[20,30322,1092,30323,1007],{},[39,30324,5902],{},[47,30326,30327],{"className":1010,"code":5905,"filename":5902,"language":1012,"meta":55,"style":55},[39,30328,30329,30341,30353,30357,30379,30395,30399,30409,30417,30425,30433,30437,30441,30445,30477,30481,30491,30499,30507,30515,30519,30523,30527,30533],{"__ignoreMap":55},[250,30330,30331,30333,30335,30337,30339],{"class":252,"line":253},[250,30332,1763],{"class":786},[250,30334,5369],{"class":912},[250,30336,1769],{"class":786},[250,30338,5374],{"class":782},[250,30340,1379],{"class":912},[250,30342,30343,30345,30347,30349,30351],{"class":252,"line":113},[250,30344,1763],{"class":786},[250,30346,5383],{"class":912},[250,30348,1769],{"class":786},[250,30350,5388],{"class":782},[250,30352,1379],{"class":912},[250,30354,30355],{"class":252,"line":110},[250,30356,795],{"emptyLinePlaceholder":129},[250,30358,30359,30361,30363,30365,30367,30369,30371,30373,30375,30377],{"class":252,"line":269},[250,30360,1019],{"class":786},[250,30362,1022],{"class":786},[250,30364,1109],{"class":774},[250,30366,1434],{"class":912},[250,30368,1437],{"class":786},[250,30370,1440],{"class":912},[250,30372,1443],{"class":1370},[250,30374,1446],{"class":912},[250,30376,1115],{"class":786},[250,30378,1118],{"class":912},[250,30380,30381,30383,30385,30387,30389,30391,30393],{"class":252,"line":275},[250,30382,1455],{"class":786},[250,30384,5964],{"class":778},[250,30386,1187],{"class":786},[250,30388,5969],{"class":774},[250,30390,5972],{"class":912},[250,30392,4466],{"class":782},[250,30394,1885],{"class":912},[250,30396,30397],{"class":252,"line":281},[250,30398,1053],{"class":912},[250,30400,30401,30403,30405,30407],{"class":252,"line":287},[250,30402,1486],{"class":786},[250,30404,1440],{"class":912},[250,30406,1491],{"class":786},[250,30408,5991],{"class":912},[250,30410,30411,30413,30415],{"class":252,"line":293},[250,30412,1517],{"class":786},[250,30414,1520],{"class":774},[250,30416,1028],{"class":912},[250,30418,30419,30421,30423],{"class":252,"line":299},[250,30420,1527],{"class":912},[250,30422,1530],{"class":778},[250,30424,927],{"class":912},[250,30426,30427,30429,30431],{"class":252,"line":132},[250,30428,1537],{"class":912},[250,30430,6014],{"class":782},[250,30432,927],{"class":912},[250,30434,30435],{"class":252,"line":310},[250,30436,1547],{"class":912},[250,30438,30439],{"class":252,"line":316},[250,30440,986],{"class":912},[250,30442,30443],{"class":252,"line":322},[250,30444,1053],{"class":912},[250,30446,30447,30449,30451,30453,30455,30457,30459,30461,30463,30465,30467,30469,30471,30473,30475],{"class":252,"line":328},[250,30448,1455],{"class":786},[250,30450,5714],{"class":778},[250,30452,1187],{"class":786},[250,30454,1463],{"class":786},[250,30456,5683],{"class":912},[250,30458,5870],{"class":774},[250,30460,1647],{"class":912},[250,30462,1769],{"class":774},[250,30464,5689],{"class":912},[250,30466,5879],{"class":774},[250,30468,6053],{"class":912},[250,30470,6056],{"class":774},[250,30472,6059],{"class":912},[250,30474,6062],{"class":774},[250,30476,1906],{"class":912},[250,30478,30479],{"class":252,"line":334},[250,30480,1053],{"class":912},[250,30482,30483,30485,30487,30489],{"class":252,"line":340},[250,30484,1486],{"class":786},[250,30486,1440],{"class":912},[250,30488,1491],{"class":786},[250,30490,6079],{"class":912},[250,30492,30493,30495,30497],{"class":252,"line":346},[250,30494,1517],{"class":786},[250,30496,1520],{"class":774},[250,30498,1028],{"class":912},[250,30500,30501,30503,30505],{"class":252,"line":352},[250,30502,1527],{"class":912},[250,30504,6094],{"class":778},[250,30506,927],{"class":912},[250,30508,30509,30511,30513],{"class":252,"line":358},[250,30510,1537],{"class":912},[250,30512,6103],{"class":782},[250,30514,927],{"class":912},[250,30516,30517],{"class":252,"line":364},[250,30518,1547],{"class":912},[250,30520,30521],{"class":252,"line":370},[250,30522,986],{"class":912},[250,30524,30525],{"class":252,"line":376},[250,30526,1053],{"class":912},[250,30528,30529,30531],{"class":252,"line":382},[250,30530,1123],{"class":786},[250,30532,6124],{"class":912},[250,30534,30535],{"class":252,"line":388},[250,30536,1077],{"class":912},[2459,30538,6132],{"id":6131},[20,30540,6135],{},[20,30542,1092,30543,1007],{},[39,30544,1353],{},[47,30546,30547],{"className":1010,"code":6142,"filename":1353,"language":1012,"meta":55,"style":55},[39,30548,30549,30561,30573,30585,30589,30597,30607,30617,30621,30625,30647,30661,30665,30669,30701,30709,30717,30725,30729,30733,30737,30741,30753,30769,30773,30787,30799,30807,30815,30827,30835,30839,30849,30857,30865,30881,30885,30889,30893,30903,30911,30919,30935,30939,30943,30947,30959,30967,30971,30975,30979,30983,30987,30991,31005,31019,31023,31037,31041,31051,31059,31063,31073,31083,31087,31091,31095,31109,31121,31129,31137,31149,31157,31161,31175,31183,31187,31191,31195,31203,31207,31211,31215,31219,31231,31239,31247,31259,31267,31271,31283,31291,31299,31311,31315,31321,31327,31331,31335],{"__ignoreMap":55},[250,30550,30551,30553,30555,30557,30559],{"class":252,"line":253},[250,30552,1763],{"class":786},[250,30554,5369],{"class":912},[250,30556,1769],{"class":786},[250,30558,5374],{"class":782},[250,30560,1379],{"class":912},[250,30562,30563,30565,30567,30569,30571],{"class":252,"line":113},[250,30564,1763],{"class":786},[250,30566,6163],{"class":912},[250,30568,1769],{"class":786},[250,30570,5388],{"class":782},[250,30572,1379],{"class":912},[250,30574,30575,30577,30579,30581,30583],{"class":252,"line":110},[250,30576,1763],{"class":786},[250,30578,6176],{"class":912},[250,30580,1769],{"class":786},[250,30582,4420],{"class":782},[250,30584,1379],{"class":912},[250,30586,30587],{"class":252,"line":269},[250,30588,795],{"emptyLinePlaceholder":129},[250,30590,30591,30593,30595],{"class":252,"line":275},[250,30592,1360],{"class":786},[250,30594,6193],{"class":774},[250,30596,1118],{"class":912},[250,30598,30599,30601,30603,30605],{"class":252,"line":281},[250,30600,6200],{"class":1370},[250,30602,1007],{"class":786},[250,30604,2506],{"class":778},[250,30606,1379],{"class":912},[250,30608,30609,30611,30613,30615],{"class":252,"line":287},[250,30610,1384],{"class":1370},[250,30612,1007],{"class":786},[250,30614,1376],{"class":778},[250,30616,1379],{"class":912},[250,30618,30619],{"class":252,"line":293},[250,30620,991],{"class":912},[250,30622,30623],{"class":252,"line":299},[250,30624,795],{"emptyLinePlaceholder":129},[250,30626,30627,30629,30631,30633,30635,30637,30639,30641,30643,30645],{"class":252,"line":132},[250,30628,1019],{"class":786},[250,30630,1022],{"class":786},[250,30632,1109],{"class":774},[250,30634,1434],{"class":912},[250,30636,1437],{"class":786},[250,30638,1440],{"class":912},[250,30640,1443],{"class":1370},[250,30642,1446],{"class":912},[250,30644,1115],{"class":786},[250,30646,1118],{"class":912},[250,30648,30649,30651,30653,30655,30657,30659],{"class":252,"line":310},[250,30650,1455],{"class":786},[250,30652,1458],{"class":778},[250,30654,1187],{"class":786},[250,30656,1463],{"class":786},[250,30658,1466],{"class":774},[250,30660,6261],{"class":912},[250,30662,30663],{"class":252,"line":316},[250,30664,1053],{"class":912},[250,30666,30667],{"class":252,"line":322},[250,30668,6270],{"class":768},[250,30670,30671,30673,30675,30677,30679,30681,30683,30685,30687,30689,30691,30693,30695,30697,30699],{"class":252,"line":328},[250,30672,1486],{"class":786},[250,30674,1440],{"class":912},[250,30676,1491],{"class":786},[250,30678,6281],{"class":912},[250,30680,1497],{"class":786},[250,30682,6286],{"class":786},[250,30684,6289],{"class":912},[250,30686,6292],{"class":774},[250,30688,6295],{"class":912},[250,30690,1497],{"class":786},[250,30692,6300],{"class":912},[250,30694,1503],{"class":778},[250,30696,1506],{"class":786},[250,30698,1509],{"class":778},[250,30700,1512],{"class":912},[250,30702,30703,30705,30707],{"class":252,"line":334},[250,30704,1517],{"class":786},[250,30706,1520],{"class":774},[250,30708,1028],{"class":912},[250,30710,30711,30713,30715],{"class":252,"line":340},[250,30712,1527],{"class":912},[250,30714,1530],{"class":778},[250,30716,927],{"class":912},[250,30718,30719,30721,30723],{"class":252,"line":346},[250,30720,1537],{"class":912},[250,30722,1540],{"class":782},[250,30724,927],{"class":912},[250,30726,30727],{"class":252,"line":352},[250,30728,1547],{"class":912},[250,30730,30731],{"class":252,"line":358},[250,30732,986],{"class":912},[250,30734,30735],{"class":252,"line":364},[250,30736,1053],{"class":912},[250,30738,30739],{"class":252,"line":370},[250,30740,6349],{"class":768},[250,30742,30743,30745,30747,30749,30751],{"class":252,"line":376},[250,30744,1911],{"class":786},[250,30746,6356],{"class":912},[250,30748,1416],{"class":786},[250,30750,1509],{"class":778},[250,30752,1379],{"class":912},[250,30754,30755,30757,30759,30761,30763,30765,30767],{"class":252,"line":382},[250,30756,1455],{"class":786},[250,30758,6369],{"class":778},[250,30760,1007],{"class":786},[250,30762,6193],{"class":774},[250,30764,1413],{"class":912},[250,30766,1416],{"class":786},[250,30768,1419],{"class":912},[250,30770,30771],{"class":252,"line":388},[250,30772,1053],{"class":912},[250,30774,30775,30777,30779,30781,30783,30785],{"class":252,"line":393},[250,30776,1944],{"class":786},[250,30778,1440],{"class":912},[250,30780,1181],{"class":786},[250,30782,5714],{"class":778},[250,30784,5717],{"class":786},[250,30786,6398],{"class":912},[250,30788,30789,30791,30793,30795,30797],{"class":252,"line":399},[250,30790,6403],{"class":786},[250,30792,6406],{"class":778},[250,30794,1187],{"class":786},[250,30796,1463],{"class":786},[250,30798,6413],{"class":912},[250,30800,30801,30803,30805],{"class":252,"line":405},[250,30802,6418],{"class":912},[250,30804,5870],{"class":774},[250,30806,4861],{"class":912},[250,30808,30809,30811,30813],{"class":252,"line":410},[250,30810,6418],{"class":912},[250,30812,1769],{"class":774},[250,30814,6431],{"class":912},[250,30816,30817,30819,30821,30823,30825],{"class":252,"line":415},[250,30818,6418],{"class":912},[250,30820,5879],{"class":774},[250,30822,1434],{"class":912},[250,30824,6442],{"class":774},[250,30826,6445],{"class":912},[250,30828,30829,30831,30833],{"class":252,"line":420},[250,30830,6418],{"class":912},[250,30832,6062],{"class":774},[250,30834,1906],{"class":912},[250,30836,30837],{"class":252,"line":426},[250,30838,6458],{"class":912},[250,30840,30841,30843,30845,30847],{"class":252,"line":431},[250,30842,6463],{"class":786},[250,30844,1440],{"class":912},[250,30846,1491],{"class":786},[250,30848,6470],{"class":912},[250,30850,30851,30853,30855],{"class":252,"line":436},[250,30852,6475],{"class":786},[250,30854,1520],{"class":774},[250,30856,1028],{"class":912},[250,30858,30859,30861,30863],{"class":252,"line":442},[250,30860,6484],{"class":912},[250,30862,1530],{"class":778},[250,30864,927],{"class":912},[250,30866,30867,30869,30871,30873,30875,30877,30879],{"class":252,"line":447},[250,30868,6493],{"class":912},[250,30870,6496],{"class":782},[250,30872,6499],{"class":912},[250,30874,2230],{"class":782},[250,30876,6504],{"class":912},[250,30878,6507],{"class":782},[250,30880,927],{"class":912},[250,30882,30883],{"class":252,"line":453},[250,30884,6514],{"class":912},[250,30886,30887],{"class":252,"line":459},[250,30888,3684],{"class":912},[250,30890,30891],{"class":252,"line":465},[250,30892,6458],{"class":912},[250,30894,30895,30897,30899,30901],{"class":252,"line":471},[250,30896,6463],{"class":786},[250,30898,1440],{"class":912},[250,30900,1491],{"class":786},[250,30902,6533],{"class":912},[250,30904,30905,30907,30909],{"class":252,"line":2201},[250,30906,6475],{"class":786},[250,30908,1520],{"class":774},[250,30910,1028],{"class":912},[250,30912,30913,30915,30917],{"class":252,"line":2207},[250,30914,6484],{"class":912},[250,30916,1530],{"class":778},[250,30918,927],{"class":912},[250,30920,30921,30923,30925,30927,30929,30931,30933],{"class":252,"line":2213},[250,30922,6493],{"class":912},[250,30924,6496],{"class":782},[250,30926,6558],{"class":912},[250,30928,2230],{"class":782},[250,30930,6563],{"class":912},[250,30932,6566],{"class":782},[250,30934,927],{"class":912},[250,30936,30937],{"class":252,"line":2218},[250,30938,6514],{"class":912},[250,30940,30941],{"class":252,"line":2223},[250,30942,3684],{"class":912},[250,30944,30945],{"class":252,"line":2239},[250,30946,6458],{"class":912},[250,30948,30949,30951,30953,30955,30957],{"class":252,"line":2244},[250,30950,6585],{"class":912},[250,30952,6588],{"class":786},[250,30954,6591],{"class":912},[250,30956,6594],{"class":786},[250,30958,6597],{"class":912},[250,30960,30961,30963,30965],{"class":252,"line":2267},[250,30962,6602],{"class":912},[250,30964,1668],{"class":774},[250,30966,1028],{"class":912},[250,30968,30969],{"class":252,"line":2301},[250,30970,6611],{"class":912},[250,30972,30973],{"class":252,"line":2306},[250,30974,6616],{"class":912},[250,30976,30977],{"class":252,"line":2320},[250,30978,1547],{"class":912},[250,30980,30981],{"class":252,"line":2340},[250,30982,986],{"class":912},[250,30984,30985],{"class":252,"line":2360},[250,30986,1053],{"class":912},[250,30988,30989],{"class":252,"line":2397},[250,30990,6633],{"class":768},[250,30992,30993,30995,30997,30999,31001,31003],{"class":252,"line":2402},[250,30994,1455],{"class":786},[250,30996,6640],{"class":778},[250,30998,1187],{"class":786},[250,31000,6645],{"class":912},[250,31002,1616],{"class":774},[250,31004,1906],{"class":912},[250,31006,31007,31009,31011,31013,31015,31017],{"class":252,"line":2407},[250,31008,1455],{"class":786},[250,31010,6656],{"class":778},[250,31012,1187],{"class":786},[250,31014,1901],{"class":912},[250,31016,1153],{"class":774},[250,31018,1906],{"class":912},[250,31020,31021],{"class":252,"line":6667},[250,31022,1053],{"class":912},[250,31024,31025,31027,31029,31031,31033,31035],{"class":252,"line":6672},[250,31026,1565],{"class":786},[250,31028,5683],{"class":912},[250,31030,5730],{"class":774},[250,31032,6681],{"class":912},[250,31034,5735],{"class":774},[250,31036,1028],{"class":912},[250,31038,31039],{"class":252,"line":6688},[250,31040,6691],{"class":912},[250,31042,31043,31045,31047,31049],{"class":252,"line":6694},[250,31044,6697],{"class":912},[250,31046,1497],{"class":786},[250,31048,6702],{"class":782},[250,31050,927],{"class":912},[250,31052,31053,31055,31057],{"class":252,"line":6707},[250,31054,1628],{"class":912},[250,31056,1631],{"class":782},[250,31058,927],{"class":912},[250,31060,31061],{"class":252,"line":6716},[250,31062,6719],{"class":912},[250,31064,31065,31067,31069,31071],{"class":252,"line":6722},[250,31066,1638],{"class":912},[250,31068,1641],{"class":786},[250,31070,1644],{"class":774},[250,31072,6731],{"class":912},[250,31074,31075,31077,31079,31081],{"class":252,"line":6734},[250,31076,6737],{"class":912},[250,31078,1641],{"class":786},[250,31080,1644],{"class":774},[250,31082,6731],{"class":912},[250,31084,31085],{"class":252,"line":6746},[250,31086,6749],{"class":912},[250,31088,31089],{"class":252,"line":6752},[250,31090,1053],{"class":912},[250,31092,31093],{"class":252,"line":6757},[250,31094,6760],{"class":768},[250,31096,31097,31099,31101,31103,31105,31107],{"class":252,"line":6763},[250,31098,1944],{"class":786},[250,31100,1440],{"class":912},[250,31102,1181],{"class":786},[250,31104,6772],{"class":778},[250,31106,5717],{"class":786},[250,31108,6777],{"class":912},[250,31110,31111,31113,31115,31117,31119],{"class":252,"line":6780},[250,31112,6403],{"class":786},[250,31114,6406],{"class":778},[250,31116,1187],{"class":786},[250,31118,1463],{"class":786},[250,31120,6413],{"class":912},[250,31122,31123,31125,31127],{"class":252,"line":6793},[250,31124,6418],{"class":912},[250,31126,5870],{"class":774},[250,31128,4861],{"class":912},[250,31130,31131,31133,31135],{"class":252,"line":6802},[250,31132,6418],{"class":912},[250,31134,1769],{"class":774},[250,31136,6431],{"class":912},[250,31138,31139,31141,31143,31145,31147],{"class":252,"line":6811},[250,31140,6418],{"class":912},[250,31142,5879],{"class":774},[250,31144,1434],{"class":912},[250,31146,6442],{"class":774},[250,31148,6822],{"class":912},[250,31150,31151,31153,31155],{"class":252,"line":6825},[250,31152,6418],{"class":912},[250,31154,6062],{"class":774},[250,31156,1906],{"class":912},[250,31158,31159],{"class":252,"line":6834},[250,31160,6458],{"class":912},[250,31162,31163,31165,31167,31169,31171,31173],{"class":252,"line":6839},[250,31164,5725],{"class":786},[250,31166,5683],{"class":912},[250,31168,5730],{"class":774},[250,31170,6848],{"class":912},[250,31172,5735],{"class":774},[250,31174,1028],{"class":912},[250,31176,31177,31179,31181],{"class":252,"line":6855},[250,31178,6858],{"class":912},[250,31180,1616],{"class":774},[250,31182,1156],{"class":912},[250,31184,31185],{"class":252,"line":6865},[250,31186,6868],{"class":912},[250,31188,31189],{"class":252,"line":6871},[250,31190,6874],{"class":912},[250,31192,31193],{"class":252,"line":6877},[250,31194,6880],{"class":912},[250,31196,31197,31199,31201],{"class":252,"line":6883},[250,31198,6886],{"class":912},[250,31200,1491],{"class":786},[250,31202,6891],{"class":912},[250,31204,31205],{"class":252,"line":6894},[250,31206,1547],{"class":912},[250,31208,31209],{"class":252,"line":6899},[250,31210,986],{"class":912},[250,31212,31213],{"class":252,"line":6904},[250,31214,1053],{"class":912},[250,31216,31217],{"class":252,"line":6909},[250,31218,6912],{"class":768},[250,31220,31221,31223,31225,31227,31229],{"class":252,"line":6915},[250,31222,1455],{"class":786},[250,31224,6920],{"class":778},[250,31226,1187],{"class":786},[250,31228,1463],{"class":786},[250,31230,6413],{"class":912},[250,31232,31233,31235,31237],{"class":252,"line":6929},[250,31234,4604],{"class":912},[250,31236,5870],{"class":774},[250,31238,4861],{"class":912},[250,31240,31241,31243,31245],{"class":252,"line":6938},[250,31242,4604],{"class":912},[250,31244,1769],{"class":774},[250,31246,6945],{"class":912},[250,31248,31249,31251,31253,31255,31257],{"class":252,"line":6948},[250,31250,4604],{"class":912},[250,31252,5879],{"class":774},[250,31254,1434],{"class":912},[250,31256,6442],{"class":774},[250,31258,6959],{"class":912},[250,31260,31261,31263,31265],{"class":252,"line":6962},[250,31262,4604],{"class":912},[250,31264,6062],{"class":774},[250,31266,1906],{"class":912},[250,31268,31269],{"class":252,"line":6971},[250,31270,1053],{"class":912},[250,31272,31273,31275,31277,31279,31281],{"class":252,"line":6976},[250,31274,1455],{"class":786},[250,31276,5861],{"class":778},[250,31278,1187],{"class":786},[250,31280,1463],{"class":786},[250,31282,6413],{"class":912},[250,31284,31285,31287,31289],{"class":252,"line":6989},[250,31286,4604],{"class":912},[250,31288,5870],{"class":774},[250,31290,4861],{"class":912},[250,31292,31293,31295,31297],{"class":252,"line":6998},[250,31294,4604],{"class":912},[250,31296,1769],{"class":774},[250,31298,7005],{"class":912},[250,31300,31301,31303,31305,31307,31309],{"class":252,"line":7008},[250,31302,4604],{"class":912},[250,31304,5879],{"class":774},[250,31306,1434],{"class":912},[250,31308,6442],{"class":774},[250,31310,7019],{"class":912},[250,31312,31313],{"class":252,"line":7022},[250,31314,1053],{"class":912},[250,31316,31317,31319],{"class":252,"line":7027},[250,31318,1123],{"class":786},[250,31320,1118],{"class":912},[250,31322,31323,31325],{"class":252,"line":7034},[250,31324,7037],{"class":786},[250,31326,7040],{"class":912},[250,31328,31329],{"class":252,"line":7043},[250,31330,7046],{"class":912},[250,31332,31333],{"class":252,"line":7049},[250,31334,1161],{"class":912},[250,31336,31337],{"class":252,"line":7054},[250,31338,1077],{"class":912},[2459,31340,7060],{"id":7059},[20,31342,1092,31343,1007],{},[39,31344,7065],{},[47,31346,31347],{"className":1010,"code":7068,"filename":7065,"language":1012,"meta":55,"style":55},[39,31348,31349,31361,31373,31385,31389,31419,31423,31445,31461,31475,31479,31489,31497,31505,31513,31517,31521,31525,31545,31553,31561,31583,31587,31591,31595,31607,31615,31623,31635,31643,31647,31657,31665,31673,31681,31685,31689,31693,31697,31703,31711,31719,31723,31733,31737,31749,31753,31765,31773,31781,31793,31801,31805,31811],{"__ignoreMap":55},[250,31350,31351,31353,31355,31357,31359],{"class":252,"line":253},[250,31352,1763],{"class":786},[250,31354,5369],{"class":912},[250,31356,1769],{"class":786},[250,31358,5374],{"class":782},[250,31360,1379],{"class":912},[250,31362,31363,31365,31367,31369,31371],{"class":252,"line":113},[250,31364,1763],{"class":786},[250,31366,7089],{"class":912},[250,31368,1769],{"class":786},[250,31370,5388],{"class":782},[250,31372,1379],{"class":912},[250,31374,31375,31377,31379,31381,31383],{"class":252,"line":110},[250,31376,1763],{"class":786},[250,31378,6176],{"class":912},[250,31380,1769],{"class":786},[250,31382,4420],{"class":782},[250,31384,1379],{"class":912},[250,31386,31387],{"class":252,"line":269},[250,31388,795],{"emptyLinePlaceholder":129},[250,31390,31391,31393,31395,31397,31399,31401,31403,31405,31407,31409,31411,31413,31415,31417],{"class":252,"line":275},[250,31392,1181],{"class":786},[250,31394,7118],{"class":778},[250,31396,1187],{"class":786},[250,31398,7123],{"class":912},[250,31400,1631],{"class":782},[250,31402,7128],{"class":912},[250,31404,7131],{"class":782},[250,31406,7128],{"class":912},[250,31408,7136],{"class":782},[250,31410,7128],{"class":912},[250,31412,7141],{"class":782},[250,31414,7128],{"class":912},[250,31416,7146],{"class":782},[250,31418,1317],{"class":912},[250,31420,31421],{"class":252,"line":281},[250,31422,795],{"emptyLinePlaceholder":129},[250,31424,31425,31427,31429,31431,31433,31435,31437,31439,31441,31443],{"class":252,"line":287},[250,31426,1019],{"class":786},[250,31428,1022],{"class":786},[250,31430,1109],{"class":774},[250,31432,1434],{"class":912},[250,31434,1437],{"class":786},[250,31436,1440],{"class":912},[250,31438,1443],{"class":1370},[250,31440,1446],{"class":912},[250,31442,1115],{"class":786},[250,31444,1118],{"class":912},[250,31446,31447,31449,31451,31453,31455,31457,31459],{"class":252,"line":293},[250,31448,1455],{"class":786},[250,31450,5964],{"class":778},[250,31452,1187],{"class":786},[250,31454,5969],{"class":774},[250,31456,5972],{"class":912},[250,31458,4466],{"class":782},[250,31460,1885],{"class":912},[250,31462,31463,31465,31467,31469,31471,31473],{"class":252,"line":299},[250,31464,1455],{"class":786},[250,31466,1458],{"class":778},[250,31468,1187],{"class":786},[250,31470,1463],{"class":786},[250,31472,1466],{"class":774},[250,31474,6261],{"class":912},[250,31476,31477],{"class":252,"line":132},[250,31478,1053],{"class":912},[250,31480,31481,31483,31485,31487],{"class":252,"line":310},[250,31482,1486],{"class":786},[250,31484,1440],{"class":912},[250,31486,1491],{"class":786},[250,31488,5991],{"class":912},[250,31490,31491,31493,31495],{"class":252,"line":316},[250,31492,1517],{"class":786},[250,31494,1520],{"class":774},[250,31496,1028],{"class":912},[250,31498,31499,31501,31503],{"class":252,"line":322},[250,31500,1527],{"class":912},[250,31502,1530],{"class":778},[250,31504,927],{"class":912},[250,31506,31507,31509,31511],{"class":252,"line":328},[250,31508,1537],{"class":912},[250,31510,7241],{"class":782},[250,31512,927],{"class":912},[250,31514,31515],{"class":252,"line":334},[250,31516,1547],{"class":912},[250,31518,31519],{"class":252,"line":340},[250,31520,986],{"class":912},[250,31522,31523],{"class":252,"line":346},[250,31524,1053],{"class":912},[250,31526,31527,31529,31531,31533,31535,31537,31539,31541,31543],{"class":252,"line":352},[250,31528,1486],{"class":786},[250,31530,1440],{"class":912},[250,31532,1491],{"class":786},[250,31534,7266],{"class":912},[250,31536,1497],{"class":786},[250,31538,6286],{"class":786},[250,31540,7273],{"class":912},[250,31542,7276],{"class":774},[250,31544,7279],{"class":912},[250,31546,31547,31549,31551],{"class":252,"line":358},[250,31548,1517],{"class":786},[250,31550,1520],{"class":774},[250,31552,1028],{"class":912},[250,31554,31555,31557,31559],{"class":252,"line":364},[250,31556,1527],{"class":912},[250,31558,1530],{"class":778},[250,31560,927],{"class":912},[250,31562,31563,31565,31567,31569,31571,31573,31575,31577,31579,31581],{"class":252,"line":370},[250,31564,1537],{"class":912},[250,31566,7302],{"class":782},[250,31568,7305],{"class":912},[250,31570,2230],{"class":782},[250,31572,7310],{"class":774},[250,31574,1434],{"class":782},[250,31576,7315],{"class":782},[250,31578,2390],{"class":782},[250,31580,2355],{"class":782},[250,31582,927],{"class":912},[250,31584,31585],{"class":252,"line":376},[250,31586,1547],{"class":912},[250,31588,31589],{"class":252,"line":382},[250,31590,986],{"class":912},[250,31592,31593],{"class":252,"line":388},[250,31594,1053],{"class":912},[250,31596,31597,31599,31601,31603,31605],{"class":252,"line":393},[250,31598,1455],{"class":786},[250,31600,7340],{"class":778},[250,31602,1187],{"class":786},[250,31604,1463],{"class":786},[250,31606,6413],{"class":912},[250,31608,31609,31611,31613],{"class":252,"line":399},[250,31610,4604],{"class":912},[250,31612,5870],{"class":774},[250,31614,4861],{"class":912},[250,31616,31617,31619,31621],{"class":252,"line":405},[250,31618,4604],{"class":912},[250,31620,1769],{"class":774},[250,31622,6945],{"class":912},[250,31624,31625,31627,31629,31631,31633],{"class":252,"line":410},[250,31626,4604],{"class":912},[250,31628,5879],{"class":774},[250,31630,1434],{"class":912},[250,31632,6442],{"class":774},[250,31634,7375],{"class":912},[250,31636,31637,31639,31641],{"class":252,"line":415},[250,31638,4604],{"class":912},[250,31640,6062],{"class":774},[250,31642,1906],{"class":912},[250,31644,31645],{"class":252,"line":420},[250,31646,1053],{"class":912},[250,31648,31649,31651,31653,31655],{"class":252,"line":426},[250,31650,1486],{"class":786},[250,31652,1440],{"class":912},[250,31654,1491],{"class":786},[250,31656,7398],{"class":912},[250,31658,31659,31661,31663],{"class":252,"line":431},[250,31660,1517],{"class":786},[250,31662,1520],{"class":774},[250,31664,1028],{"class":912},[250,31666,31667,31669,31671],{"class":252,"line":436},[250,31668,1527],{"class":912},[250,31670,6094],{"class":778},[250,31672,927],{"class":912},[250,31674,31675,31677,31679],{"class":252,"line":442},[250,31676,1537],{"class":912},[250,31678,7421],{"class":782},[250,31680,927],{"class":912},[250,31682,31683],{"class":252,"line":447},[250,31684,1547],{"class":912},[250,31686,31687],{"class":252,"line":453},[250,31688,986],{"class":912},[250,31690,31691],{"class":252,"line":459},[250,31692,1053],{"class":912},[250,31694,31695],{"class":252,"line":465},[250,31696,7440],{"class":768},[250,31698,31699,31701],{"class":252,"line":471},[250,31700,1565],{"class":786},[250,31702,6413],{"class":912},[250,31704,31705,31707,31709],{"class":252,"line":2201},[250,31706,4604],{"class":912},[250,31708,7453],{"class":774},[250,31710,6945],{"class":912},[250,31712,31713,31715,31717],{"class":252,"line":2207},[250,31714,4604],{"class":912},[250,31716,7462],{"class":774},[250,31718,1028],{"class":912},[250,31720,31721],{"class":252,"line":2213},[250,31722,7469],{"class":912},[250,31724,31725,31727,31729,31731],{"class":252,"line":2218},[250,31726,7474],{"class":912},[250,31728,1641],{"class":786},[250,31730,1644],{"class":774},[250,31732,1156],{"class":912},[250,31734,31735],{"class":252,"line":2223},[250,31736,7485],{"class":912},[250,31738,31739,31741,31743,31745,31747],{"class":252,"line":2239},[250,31740,4604],{"class":912},[250,31742,5879],{"class":774},[250,31744,1434],{"class":912},[250,31746,6442],{"class":774},[250,31748,7498],{"class":912},[250,31750,31751],{"class":252,"line":2244},[250,31752,1053],{"class":912},[250,31754,31755,31757,31759,31761,31763],{"class":252,"line":2267},[250,31756,1455],{"class":786},[250,31758,7509],{"class":778},[250,31760,1187],{"class":786},[250,31762,1463],{"class":786},[250,31764,6413],{"class":912},[250,31766,31767,31769,31771],{"class":252,"line":2301},[250,31768,4604],{"class":912},[250,31770,5870],{"class":774},[250,31772,4861],{"class":912},[250,31774,31775,31777,31779],{"class":252,"line":2306},[250,31776,4604],{"class":912},[250,31778,1769],{"class":774},[250,31780,6945],{"class":912},[250,31782,31783,31785,31787,31789,31791],{"class":252,"line":2320},[250,31784,4604],{"class":912},[250,31786,5879],{"class":774},[250,31788,1434],{"class":912},[250,31790,6442],{"class":774},[250,31792,7375],{"class":912},[250,31794,31795,31797,31799],{"class":252,"line":2340},[250,31796,4604],{"class":912},[250,31798,6062],{"class":774},[250,31800,1906],{"class":912},[250,31802,31803],{"class":252,"line":2360},[250,31804,1053],{"class":912},[250,31806,31807,31809],{"class":252,"line":2397},[250,31808,1123],{"class":786},[250,31810,7562],{"class":912},[250,31812,31813],{"class":252,"line":2402},[250,31814,1077],{"class":912},[2459,31816,7570],{"id":7569},[20,31818,1092,31819,1007],{},[39,31820,7575],{},[47,31822,31823],{"className":1010,"code":7578,"filename":7575,"language":1012,"meta":55,"style":55},[39,31824,31825,31837,31849,31853,31871,31883,31891,31899,31907,31911,31915,31933,31953,31965,31973,31981,31993,32003,32007,32011,32015,32021],{"__ignoreMap":55},[250,31826,31827,31829,31831,31833,31835],{"class":252,"line":253},[250,31828,1763],{"class":786},[250,31830,5369],{"class":912},[250,31832,1769],{"class":786},[250,31834,5374],{"class":782},[250,31836,1379],{"class":912},[250,31838,31839,31841,31843,31845,31847],{"class":252,"line":113},[250,31840,1763],{"class":786},[250,31842,7599],{"class":912},[250,31844,1769],{"class":786},[250,31846,5388],{"class":782},[250,31848,1379],{"class":912},[250,31850,31851],{"class":252,"line":110},[250,31852,795],{"emptyLinePlaceholder":129},[250,31854,31855,31857,31859,31861,31863,31865,31867,31869],{"class":252,"line":269},[250,31856,1019],{"class":786},[250,31858,1022],{"class":786},[250,31860,1109],{"class":774},[250,31862,1434],{"class":912},[250,31864,1437],{"class":786},[250,31866,2015],{"class":912},[250,31868,1115],{"class":786},[250,31870,1118],{"class":912},[250,31872,31873,31875,31877,31879,31881],{"class":252,"line":275},[250,31874,1455],{"class":786},[250,31876,7634],{"class":778},[250,31878,1187],{"class":786},[250,31880,1463],{"class":786},[250,31882,6413],{"class":912},[250,31884,31885,31887,31889],{"class":252,"line":281},[250,31886,4604],{"class":912},[250,31888,5870],{"class":774},[250,31890,4861],{"class":912},[250,31892,31893,31895,31897],{"class":252,"line":287},[250,31894,4604],{"class":912},[250,31896,1769],{"class":774},[250,31898,6945],{"class":912},[250,31900,31901,31903,31905],{"class":252,"line":293},[250,31902,4604],{"class":912},[250,31904,7663],{"class":774},[250,31906,7666],{"class":912},[250,31908,31909],{"class":252,"line":299},[250,31910,1053],{"class":912},[250,31912,31913],{"class":252,"line":132},[250,31914,7675],{"class":768},[250,31916,31917,31919,31921,31923,31925,31927,31929,31931],{"class":252,"line":310},[250,31918,1455],{"class":786},[250,31920,7682],{"class":778},[250,31922,1187],{"class":786},[250,31924,1463],{"class":786},[250,31926,1571],{"class":778},[250,31928,2230],{"class":912},[250,31930,2233],{"class":774},[250,31932,1982],{"class":912},[250,31934,31935,31937,31939,31941,31943,31945,31947,31949,31951],{"class":252,"line":316},[250,31936,7699],{"class":912},[250,31938,2820],{"class":774},[250,31940,1434],{"class":912},[250,31942,1437],{"class":786},[250,31944,1440],{"class":912},[250,31946,7710],{"class":1370},[250,31948,1446],{"class":912},[250,31950,1115],{"class":786},[250,31952,1118],{"class":912},[250,31954,31955,31957,31959,31961,31963],{"class":252,"line":322},[250,31956,7721],{"class":786},[250,31958,5861],{"class":778},[250,31960,1187],{"class":786},[250,31962,1463],{"class":786},[250,31964,6413],{"class":912},[250,31966,31967,31969,31971],{"class":252,"line":328},[250,31968,7734],{"class":912},[250,31970,5870],{"class":774},[250,31972,4861],{"class":912},[250,31974,31975,31977,31979],{"class":252,"line":334},[250,31976,7734],{"class":912},[250,31978,1769],{"class":774},[250,31980,7005],{"class":912},[250,31982,31983,31985,31987,31989,31991],{"class":252,"line":340},[250,31984,7734],{"class":912},[250,31986,5879],{"class":774},[250,31988,7755],{"class":912},[250,31990,6056],{"class":774},[250,31992,7760],{"class":912},[250,31994,31995,31997,31999,32001],{"class":252,"line":346},[250,31996,7765],{"class":786},[250,31998,7768],{"class":912},[250,32000,7771],{"class":786},[250,32002,7774],{"class":912},[250,32004,32005],{"class":252,"line":352},[250,32006,7485],{"class":912},[250,32008,32009],{"class":252,"line":358},[250,32010,2859],{"class":912},[250,32012,32013],{"class":252,"line":364},[250,32014,1053],{"class":912},[250,32016,32017,32019],{"class":252,"line":370},[250,32018,1123],{"class":786},[250,32020,7793],{"class":912},[250,32022,32023],{"class":252,"line":376},[250,32024,1077],{"class":912},[72,32026],{},[31,32028,7803],{"id":7802},[20,32030,7806],{},[47,32032,32033],{"className":758,"code":7809,"filename":760,"language":761,"meta":55,"style":55},[39,32034,32035,32039,32047,32051,32055],{"__ignoreMap":55},[250,32036,32037],{"class":252,"line":253},[250,32038,7816],{"class":768},[250,32040,32041,32043,32045],{"class":252,"line":113},[250,32042,4200],{"class":774},[250,32044,4246],{"class":782},[250,32046,7825],{"class":782},[250,32048,32049],{"class":252,"line":110},[250,32050,795],{"emptyLinePlaceholder":129},[250,32052,32053],{"class":252,"line":269},[250,32054,7834],{"class":768},[250,32056,32057,32059,32061],{"class":252,"line":275},[250,32058,4200],{"class":774},[250,32060,4246],{"class":782},[250,32062,7843],{"class":782},[161,32064,32065],{"icon":7846,"title":7847},[20,32066,7850,32067,7854,32069,7858],{},[39,32068,7853],{},[39,32070,7857],{},[72,32072],{},[31,32074,7864],{"id":7863},[20,32076,7867],{},[47,32078,32079],{"className":758,"code":196,"filename":760,"language":761,"meta":55,"style":55},[39,32080,32081],{"__ignoreMap":55},[250,32082,32083,32085,32087],{"class":252,"line":253},[250,32084,4226],{"class":774},[250,32086,1707],{"class":782},[250,32088,1710],{"class":782},[2459,32090,7883],{"id":7882},[47,32092,32093],{"className":758,"code":7886,"language":761,"meta":55,"style":55},[39,32094,32095],{"__ignoreMap":55},[250,32096,32097,32099,32101,32103],{"class":252,"line":253},[250,32098,775],{"class":774},[250,32100,7895],{"class":778},[250,32102,7898],{"class":782},[250,32104,7901],{"class":782},[2459,32106,7905],{"id":7904},[47,32108,32109],{"className":758,"code":7908,"language":761,"meta":55,"style":55},[39,32110,32111],{"__ignoreMap":55},[250,32112,32113,32115],{"class":252,"line":253},[250,32114,775],{"class":774},[250,32116,7917],{"class":782},[2459,32118,7921],{"id":7920},[47,32120,32121],{"className":758,"code":7924,"language":761,"meta":55,"style":55},[39,32122,32123,32135,32143,32149,32153,32157,32161,32165,32169],{"__ignoreMap":55},[250,32124,32125,32127,32129,32131,32133],{"class":252,"line":253},[250,32126,775],{"class":774},[250,32128,7895],{"class":778},[250,32130,7898],{"class":782},[250,32132,7937],{"class":782},[250,32134,7940],{"class":778},[250,32136,32137,32139,32141],{"class":252,"line":113},[250,32138,7945],{"class":778},[250,32140,7948],{"class":782},[250,32142,7940],{"class":778},[250,32144,32145,32147],{"class":252,"line":110},[250,32146,7955],{"class":778},[250,32148,7958],{"class":782},[250,32150,32151],{"class":252,"line":269},[250,32152,7963],{"class":782},[250,32154,32155],{"class":252,"line":275},[250,32156,7968],{"class":782},[250,32158,32159],{"class":252,"line":281},[250,32160,7973],{"class":782},[250,32162,32163],{"class":252,"line":287},[250,32164,7978],{"class":782},[250,32166,32167],{"class":252,"line":293},[250,32168,7983],{"class":782},[250,32170,32171],{"class":252,"line":299},[250,32172,7988],{"class":782},[2459,32174,7992],{"id":7991},[47,32176,32177],{"className":758,"code":7995,"language":761,"meta":55,"style":55},[39,32178,32179,32191,32199],{"__ignoreMap":55},[250,32180,32181,32183,32185,32187,32189],{"class":252,"line":253},[250,32182,775],{"class":774},[250,32184,7895],{"class":778},[250,32186,8006],{"class":782},[250,32188,8009],{"class":782},[250,32190,7940],{"class":778},[250,32192,32193,32195,32197],{"class":252,"line":113},[250,32194,7945],{"class":778},[250,32196,7948],{"class":782},[250,32198,7940],{"class":778},[250,32200,32201,32203],{"class":252,"line":110},[250,32202,7955],{"class":778},[250,32204,8026],{"class":782},[72,32206],{},[31,32208,3256],{"id":3255},[20,32210,3259],{},[561,32212,32213,32215,32217,32219,32221],{},[564,32214,8037],{},[564,32216,8040],{},[564,32218,8043],{},[564,32220,8046],{},[564,32222,8049],{},[2459,32224,3280],{"id":3279},[645,32226,32227,32237],{},[648,32228,32229],{},[651,32230,32231,32233,32235],{},[654,32232,8060],{},[654,32234,3289],{},[654,32236,3292],{},[666,32238,32239,32249,32259,32269,32279,32289],{},[651,32240,32241,32243,32247],{},[671,32242,8071],{},[671,32244,32245],{},[39,32246,8076],{},[671,32248,8079],{},[651,32250,32251,32253,32257],{},[671,32252,8071],{},[671,32254,32255],{},[39,32256,8088],{},[671,32258,8091],{},[651,32260,32261,32263,32267],{},[671,32262,8096],{},[671,32264,32265],{},[39,32266,3343],{},[671,32268,8103],{},[651,32270,32271,32273,32277],{},[671,32272,8071],{},[671,32274,32275],{},[39,32276,3343],{},[671,32278,8114],{},[651,32280,32281,32283,32287],{},[671,32282,8119],{},[671,32284,32285],{},[39,32286,8124],{},[671,32288,8127],{},[651,32290,32291,32293,32297],{},[671,32292,8096],{},[671,32294,32295],{},[39,32296,8136],{},[671,32298,8139],{},[72,32300],{},[15,32302,3352],{"id":3351},[20,32304,8146,32305,8150],{},[546,32306,8149],{},[20,32308,8153],{},[561,32310,32311,32315,32319],{},[564,32312,32313,8161],{},[546,32314,8160],{},[564,32316,32317,8167],{},[546,32318,8166],{},[564,32320,32321,8173],{},[546,32322,8172],{},[20,32324,8176,32325,8180],{},[546,32326,8179],{},[500,32328,8183],{},{"title":55,"searchDepth":110,"depth":110,"links":32330},[32331,32332,32333,32334,32335,32336,32337,32344,32345,32351],{"id":4161,"depth":113,"text":4162},{"id":4181,"depth":113,"text":4182},{"id":4259,"depth":113,"text":4260},{"id":4360,"depth":113,"text":4361},{"id":5045,"depth":113,"text":5046},{"id":5348,"depth":113,"text":5349},{"id":5793,"depth":113,"text":5794,"children":32338},[32339,32340,32341,32342,32343],{"id":5797,"depth":110,"text":5798},{"id":5896,"depth":110,"text":5897},{"id":6131,"depth":110,"text":6132},{"id":7059,"depth":110,"text":7060},{"id":7569,"depth":110,"text":7570},{"id":7802,"depth":113,"text":7803},{"id":7863,"depth":113,"text":7864,"children":32346},[32347,32348,32349,32350],{"id":7882,"depth":110,"text":7883},{"id":7904,"depth":110,"text":7905},{"id":7920,"depth":110,"text":7921},{"id":7991,"depth":110,"text":7992},{"id":3255,"depth":113,"text":3256,"children":32352},[32353],{"id":3279,"depth":110,"text":3280},{"type":12,"value":32355},[32356,32358,32362,32366,32368],[15,32357,541],{"id":540},[20,32359,4089,32360,4093],{},[546,32361,4092],{},[20,32363,4096,32364,4100],{},[546,32365,4099],{},[20,32367,4103],{},[20,32369,4106,32370,4110],{},[546,32371,4109],{},[8229,8230,3504,8231,8232,8233,8234],{},{"title":4081,"description":8209},[32376,32377],{"title":3519,"path":4075,"stem":4077,"children":-1},{"title":8242,"path":8297,"stem":8299,"children":-1},[32379,32908,33139],{"id":12036,"title":12037,"author":32380,"body":32381,"canonical":115,"categories":115,"date":12640,"description":12641,"excerpt":32884,"extension":118,"img":12662,"keywords":32904,"language":3510,"meta":32905,"navigation":129,"ogImage":115,"path":12666,"rating":275,"readTime":293,"seo":32906,"stem":12668,"tag":3515,"__hash__":12669,"score":275,"slug":32907},{"name":8,"img":10,"website":535},{"type":12,"value":32382,"toc":32871},[32383,32385,32391,32393,32401,32403,32405,32411,32413,32419,32421,32463,32469,32471,32477,32479,32561,32563,32641,32643,32645,32649,32651,32659,32661,32663,32667,32669,32773,32775,32777,32781,32783,32785,32787,32795,32797,32801,32803,32805,32839,32841,32845,32847,32849,32851,32853,32857,32859,32861,32863,32865,32869],[15,32384,541],{"id":540},[20,32386,12045,32387,12049,32389],{},[546,32388,12048],{},[250,32390,3570],{"index":1198},[20,32392,12054],{},[561,32394,32395,32397,32399],{},[564,32396,12059],{},[564,32398,12062],{},[564,32400,12065],{},[15,32402,748],{"id":747},[31,32404,12071],{"id":12070},[20,32406,12074,32407,12077,32409],{},[39,32408,11907],{},[250,32410,3582],{"index":1226},[31,32412,12083],{"id":12082},[20,32414,12086,32415,12090,32417,12093],{},[39,32416,12089],{},[39,32418,10277],{},[20,32420,12096],{},[47,32422,32423],{"className":1010,"code":12099,"language":1012,"meta":55,"style":55},[39,32424,32425,32429,32447,32459],{"__ignoreMap":55},[250,32426,32427],{"class":252,"line":253},[250,32428,12106],{"class":768},[250,32430,32431,32433,32435,32437,32439,32441,32443,32445],{"class":252,"line":113},[250,32432,1019],{"class":786},[250,32434,1022],{"class":786},[250,32436,10272],{"class":774},[250,32438,1574],{"class":912},[250,32440,10277],{"class":1370},[250,32442,1446],{"class":912},[250,32444,1115],{"class":786},[250,32446,1118],{"class":912},[250,32448,32449,32451,32453,32455,32457],{"class":252,"line":110},[250,32450,1856],{"class":912},[250,32452,1859],{"class":774},[250,32454,1434],{"class":912},[250,32456,12135],{"class":782},[250,32458,4852],{"class":912},[250,32460,32461],{"class":252,"line":269},[250,32462,474],{"class":912},[20,32464,12144,32465,12147,32467,2390],{},[39,32466,8892],{},[250,32468,1226],{},[31,32470,12153],{"id":12152},[20,32472,12156,32473,12160,32475,2390],{},[546,32474,12159],{},[250,32476,1226],{},[20,32478,12165],{},[47,32480,32481],{"className":1010,"code":12168,"language":1012,"meta":55,"style":55},[39,32482,32483,32487,32505,32525,32553,32557],{"__ignoreMap":55},[250,32484,32485],{"class":252,"line":253},[250,32486,12175],{"class":768},[250,32488,32489,32491,32493,32495,32497,32499,32501,32503],{"class":252,"line":113},[250,32490,1019],{"class":786},[250,32492,1022],{"class":786},[250,32494,10272],{"class":774},[250,32496,1574],{"class":912},[250,32498,10277],{"class":1370},[250,32500,1446],{"class":912},[250,32502,1115],{"class":786},[250,32504,1118],{"class":912},[250,32506,32507,32509,32511,32513,32515,32517,32519,32521,32523],{"class":252,"line":110},[250,32508,10288],{"class":912},[250,32510,10291],{"class":774},[250,32512,1434],{"class":912},[250,32514,10296],{"class":782},[250,32516,10299],{"class":912},[250,32518,1443],{"class":1370},[250,32520,1446],{"class":912},[250,32522,1115],{"class":786},[250,32524,1118],{"class":912},[250,32526,32527,32529,32531,32533,32535,32537,32539,32541,32543,32545,32547,32549,32551],{"class":252,"line":269},[250,32528,10312],{"class":912},[250,32530,1859],{"class":774},[250,32532,1434],{"class":912},[250,32534,12224],{"class":782},[250,32536,1443],{"class":912},[250,32538,2230],{"class":782},[250,32540,10342],{"class":912},[250,32542,10345],{"class":782},[250,32544,1443],{"class":912},[250,32546,2230],{"class":782},[250,32548,10352],{"class":912},[250,32550,2355],{"class":782},[250,32552,4852],{"class":912},[250,32554,32555],{"class":252,"line":275},[250,32556,10365],{"class":912},[250,32558,32559],{"class":252,"line":281},[250,32560,474],{"class":912},[20,32562,12253],{},[47,32564,32565],{"className":1010,"code":12256,"language":1012,"meta":55,"style":55},[39,32566,32567,32571,32589,32613,32633,32637],{"__ignoreMap":55},[250,32568,32569],{"class":252,"line":253},[250,32570,12263],{"class":768},[250,32572,32573,32575,32577,32579,32581,32583,32585,32587],{"class":252,"line":113},[250,32574,1019],{"class":786},[250,32576,1022],{"class":786},[250,32578,10272],{"class":774},[250,32580,1574],{"class":912},[250,32582,10277],{"class":1370},[250,32584,1446],{"class":912},[250,32586,1115],{"class":786},[250,32588,1118],{"class":912},[250,32590,32591,32593,32595,32597,32599,32601,32603,32605,32607,32609,32611],{"class":252,"line":110},[250,32592,10288],{"class":912},[250,32594,10291],{"class":774},[250,32596,1434],{"class":912},[250,32598,12292],{"class":782},[250,32600,10299],{"class":912},[250,32602,12297],{"class":1370},[250,32604,12300],{"class":912},[250,32606,1443],{"class":1370},[250,32608,12305],{"class":912},[250,32610,1115],{"class":786},[250,32612,1118],{"class":912},[250,32614,32615,32617,32619,32621,32623,32625,32627,32629,32631],{"class":252,"line":269},[250,32616,10312],{"class":912},[250,32618,12297],{"class":774},[250,32620,1434],{"class":912},[250,32622,12320],{"class":782},[250,32624,1443],{"class":912},[250,32626,2230],{"class":782},[250,32628,10352],{"class":912},[250,32630,12329],{"class":782},[250,32632,12332],{"class":912},[250,32634,32635],{"class":252,"line":275},[250,32636,10365],{"class":912},[250,32638,32639],{"class":252,"line":281},[250,32640,474],{"class":912},[31,32642,12344],{"id":12343},[20,32644,12347],{},[2459,32646,12351,32647],{"id":12350},[546,32648,12354],{},[20,32650,12357],{},[561,32652,32653,32655,32657],{},[564,32654,12362],{},[564,32656,12365],{},[564,32658,12368],{},[20,32660,12371],{},[72,32662],{},[2459,32664,12377,32665],{"id":12376},[546,32666,12380],{},[20,32668,12383],{},[47,32670,32671],{"className":1010,"code":12386,"language":1012,"meta":55,"style":55},[39,32672,32673,32677,32695,32715,32733,32745,32761,32765,32769],{"__ignoreMap":55},[250,32674,32675],{"class":252,"line":253},[250,32676,12393],{"class":768},[250,32678,32679,32681,32683,32685,32687,32689,32691,32693],{"class":252,"line":113},[250,32680,1019],{"class":786},[250,32682,1022],{"class":786},[250,32684,10272],{"class":774},[250,32686,1574],{"class":912},[250,32688,10277],{"class":1370},[250,32690,1446],{"class":912},[250,32692,1115],{"class":786},[250,32694,1118],{"class":912},[250,32696,32697,32699,32701,32703,32705,32707,32709,32711,32713],{"class":252,"line":110},[250,32698,10288],{"class":912},[250,32700,10291],{"class":774},[250,32702,1434],{"class":912},[250,32704,10296],{"class":782},[250,32706,10299],{"class":912},[250,32708,1443],{"class":1370},[250,32710,1446],{"class":912},[250,32712,1115],{"class":786},[250,32714,1118],{"class":912},[250,32716,32717,32719,32721,32723,32725,32727,32729,32731],{"class":252,"line":269},[250,32718,6403],{"class":786},[250,32720,10497],{"class":778},[250,32722,1187],{"class":786},[250,32724,10502],{"class":912},[250,32726,6062],{"class":774},[250,32728,1434],{"class":912},[250,32730,10509],{"class":782},[250,32732,4852],{"class":912},[250,32734,32735,32737,32739,32741,32743],{"class":252,"line":275},[250,32736,6463],{"class":786},[250,32738,1440],{"class":912},[250,32740,1491],{"class":786},[250,32742,12460],{"class":774},[250,32744,12463],{"class":912},[250,32746,32747,32749,32751,32753,32755,32757,32759],{"class":252,"line":281},[250,32748,6475],{"class":786},[250,32750,1520],{"class":774},[250,32752,10172],{"class":912},[250,32754,10538],{"class":778},[250,32756,10177],{"class":912},[250,32758,10543],{"class":782},[250,32760,4599],{"class":912},[250,32762,32763],{"class":252,"line":287},[250,32764,3684],{"class":912},[250,32766,32767],{"class":252,"line":293},[250,32768,10365],{"class":912},[250,32770,32771],{"class":252,"line":299},[250,32772,474],{"class":912},[20,32774,12494],{},[72,32776],{},[2459,32778,12500,32779],{"id":12499},[546,32780,12503],{},[20,32782,12506],{},[20,32784,12509],{},[20,32786,12512],{},[561,32788,32789,32791,32793],{},[564,32790,12517],{},[564,32792,12520],{},[564,32794,12523],{},[72,32796],{},[2459,32798,12529,32799],{"id":12528},[546,32800,12532],{},[20,32802,12535],{},[20,32804,12538],{},[47,32806,32807],{"className":1010,"code":12541,"language":1012,"meta":55,"style":55},[39,32808,32809,32829,32835],{"__ignoreMap":55},[250,32810,32811,32813,32815,32817,32819,32821,32823,32825,32827],{"class":252,"line":253},[250,32812,12548],{"class":912},[250,32814,10291],{"class":774},[250,32816,1434],{"class":912},[250,32818,10296],{"class":782},[250,32820,10299],{"class":912},[250,32822,1443],{"class":1370},[250,32824,1446],{"class":912},[250,32826,1115],{"class":786},[250,32828,1118],{"class":912},[250,32830,32831,32833],{"class":252,"line":113},[250,32832,12569],{"class":774},[250,32834,12572],{"class":912},[250,32836,32837],{"class":252,"line":110},[250,32838,474],{"class":912},[72,32840],{},[2459,32842,12582,32843],{"id":12581},[546,32844,12585],{},[20,32846,12588],{},[20,32848,12591],{},[72,32850],{},[31,32852,12597],{"id":12596},[20,32854,12600,32855,2390],{},[250,32856,1198],{},[72,32858],{},[15,32860,3352],{"id":3351},[20,32862,12609],{},[20,32864,12612],{},[20,32866,12615,32867,1491],{},[546,32868,12618],{},[500,32870,12621],{},{"title":55,"searchDepth":110,"depth":110,"links":32872},[32873,32874,32875,32876,32883],{"id":12070,"depth":113,"text":12071},{"id":12082,"depth":113,"text":12083},{"id":12152,"depth":113,"text":12153},{"id":12343,"depth":113,"text":12344,"children":32877},[32878,32879,32880,32881,32882],{"id":12350,"depth":110,"text":12630},{"id":12376,"depth":110,"text":12632},{"id":12499,"depth":110,"text":12634},{"id":12528,"depth":110,"text":12636},{"id":12581,"depth":110,"text":12638},{"id":12596,"depth":113,"text":12597},{"type":12,"value":32885},[32886,32888,32894,32896],[15,32887,541],{"id":540},[20,32889,12045,32890,12049,32892],{},[546,32891,12048],{},[250,32893,3570],{"index":1198},[20,32895,12054],{},[561,32897,32898,32900,32902],{},[564,32899,12059],{},[564,32901,12062],{},[564,32903,12065],{},[3504,12664,3507,3509,8234],{},{"title":12037,"description":12641},"nitro-plugins",{"id":12671,"title":12672,"author":32909,"body":32910,"canonical":115,"categories":115,"date":12959,"description":12960,"excerpt":33107,"extension":118,"img":12662,"keywords":33135,"language":3510,"meta":33136,"navigation":129,"ogImage":115,"path":12991,"rating":275,"readTime":316,"seo":33137,"stem":12993,"tag":3515,"__hash__":12994,"score":275,"slug":33138},{"name":8,"img":10,"website":535},{"type":12,"value":32911,"toc":33096},[32912,32914,32920,32922,32932,32938,32940,32942,32974,32976,32978,32980,32985,32987,32989,32991,32993,32995,32997,32999,33001,33003,33005,33009,33011,33016,33018,33020,33022,33024,33026,33028,33030,33032,33037,33039,33041,33046,33048,33050,33052,33054,33056,33058,33060,33062,33064,33066,33068,33070,33072,33074,33076,33078,33080,33082,33084,33086,33088,33090,33092,33094],[15,32913,541],{"id":540},[20,32915,12680,32916,12684,32918,12688],{},[546,32917,12683],{},[546,32919,12687],{},[20,32921,12691],{},[561,32923,32924,32926,32928,32930],{},[564,32925,12696],{},[564,32927,12699],{},[564,32929,12702],{},[564,32931,12705],{},[20,32933,12708,32934,12711,32936,12715],{},[546,32935,3510],{},[546,32937,12714],{},[15,32939,12719],{"id":12718},[20,32941,12722],{},[47,32943,32944],{"className":12725,"code":12726,"language":12727,"meta":55,"style":55},[39,32945,32946,32950,32954,32958,32962,32966,32970],{"__ignoreMap":55},[250,32947,32948],{"class":252,"line":253},[250,32949,12734],{},[250,32951,32952],{"class":252,"line":113},[250,32953,12739],{},[250,32955,32956],{"class":252,"line":110},[250,32957,12744],{},[250,32959,32960],{"class":252,"line":269},[250,32961,12749],{},[250,32963,32964],{"class":252,"line":275},[250,32965,12754],{},[250,32967,32968],{"class":252,"line":281},[250,32969,12759],{},[250,32971,32972],{"class":252,"line":287},[250,32973,12764],{},[15,32975,12768],{"id":12767},[20,32977,12771],{},[20,32979,12774],{},[47,32981,32983],{"className":32982,"code":12778,"language":52},[50],[39,32984,12778],{"__ignoreMap":55},[20,32986,12783],{},[31,32988,12787],{"id":12786},[20,32990,12790],{},[20,32992,12793],{},[20,32994,12796],{},[20,32996,12799],{},[20,32998,12802],{},[20,33000,12805],{},[31,33002,12809],{"id":12808},[20,33004,12812],{},[20,33006,12815,33007,2390],{},[250,33008,12818],{},[20,33010,12821],{},[47,33012,33014],{"className":33013,"code":12825,"language":52},[50],[39,33015,12825],{"__ignoreMap":55},[20,33017,12783],{},[31,33019,12833],{"id":12832},[20,33021,12836],{},[20,33023,12839],{},[20,33025,12842],{},[31,33027,12846],{"id":12845},[20,33029,12849],{},[20,33031,12852],{},[47,33033,33035],{"className":33034,"code":12856,"language":52},[50],[39,33036,12856],{"__ignoreMap":55},[20,33038,12861],{},[20,33040,12864],{},[47,33042,33044],{"className":33043,"code":12868,"language":52},[50],[39,33045,12868],{"__ignoreMap":55},[20,33047,12783],{},[31,33049,12876],{"id":12875},[20,33051,12879],{},[20,33053,12882],{},[20,33055,12885],{},[31,33057,12889],{"id":12888},[20,33059,12892],{},[20,33061,12895],{},[20,33063,12898],{},[31,33065,12902],{"id":12901},[20,33067,12905],{},[20,33069,12908],{},[20,33071,12911],{},[31,33073,12915],{"id":12914},[20,33075,12918],{},[20,33077,12921],{},[31,33079,12925],{"id":12924},[20,33081,12928],{},[20,33083,12931],{},[20,33085,12934],{},[20,33087,12937],{},[15,33089,3352],{"id":3351},[20,33091,12942],{},[20,33093,12945],{},[500,33095,502],{},{"title":55,"searchDepth":110,"depth":110,"links":33097},[33098,33099,33100,33101,33102,33103,33104,33105,33106],{"id":12786,"depth":113,"text":12787},{"id":12808,"depth":113,"text":12809},{"id":12832,"depth":113,"text":12833},{"id":12845,"depth":113,"text":12846},{"id":12875,"depth":113,"text":12876},{"id":12888,"depth":113,"text":12889},{"id":12901,"depth":113,"text":12902},{"id":12914,"depth":113,"text":12915},{"id":12924,"depth":113,"text":12925},{"type":12,"value":33108},[33109,33111,33117,33119,33129],[15,33110,541],{"id":540},[20,33112,12680,33113,12684,33115,12688],{},[546,33114,12683],{},[546,33116,12687],{},[20,33118,12691],{},[561,33120,33121,33123,33125,33127],{},[564,33122,12696],{},[564,33124,12699],{},[564,33126,12702],{},[564,33128,12705],{},[20,33130,12708,33131,12711,33133,12715],{},[546,33132,3510],{},[546,33134,12714],{},[3504,11903,3507,3508,8234],{},{"title":12672,"description":12960},"nitro-tutorial",{"id":532,"title":533,"author":33140,"body":33141,"canonical":115,"categories":115,"date":3470,"description":3471,"excerpt":35480,"extension":118,"img":3502,"keywords":35510,"language":3510,"meta":35511,"navigation":129,"ogImage":115,"path":3512,"rating":275,"readTime":132,"seo":35512,"stem":3514,"tag":3515,"__hash__":3516,"score":269,"slug":35513},{"name":8,"img":10,"website":535},{"type":12,"value":33142,"toc":35448},[33143,33145,33149,33153,33155,33167,33171,33173,33175,33177,33199,33203,33205,33207,33209,33273,33275,33279,33281,33283,33285,33287,33323,33325,33339,33341,33343,33345,33373,33377,33379,33389,33391,33461,33463,33465,33467,33471,33525,33527,33529,33531,33533,33537,33593,33597,33743,33745,34015,34017,34019,34021,34033,34037,34039,34055,34057,34059,34061,34065,34605,34607,34639,34641,34643,34645,34647,34797,34799,34801,34875,34877,34879,35045,35047,35049,35051,35145,35147,35164,35166,35168,35170,35172,35186,35188,35236,35238,35286,35288,35290,35310,35314,35316,35318,35320,35332,35334,35386,35388,35390,35394,35416,35418,35420,35432,35434,35442,35444,35446],[15,33144,541],{"id":540},[20,33146,544,33147,549],{},[546,33148,548],{},[20,33150,552,33151,556],{},[546,33152,555],{},[20,33154,559],{},[561,33156,33157,33159,33161,33163,33165],{},[564,33158,566],{},[564,33160,569],{},[564,33162,572],{},[564,33164,575],{},[564,33166,578],{},[20,33168,581,33169,585],{},[546,33170,584],{},[15,33172,589],{"id":588},[20,33174,592],{},[31,33176,596],{"id":595},[561,33178,33179,33183,33187,33191,33195],{},[564,33180,33181,604],{},[546,33182,603],{},[564,33184,33185,610],{},[546,33186,609],{},[564,33188,33189,616],{},[546,33190,615],{},[564,33192,33193,622],{},[546,33194,621],{},[564,33196,33197,628],{},[546,33198,627],{},[24,33200,33201],{"type":631},[20,33202,634],{},[72,33204],{},[31,33206,640],{"id":639},[20,33208,643],{},[645,33210,33211,33223],{},[648,33212,33213],{},[651,33214,33215,33217,33219,33221],{},[654,33216,656],{},[654,33218,659],{},[654,33220,548],{},[654,33222,664],{},[666,33224,33225,33237,33249,33261],{},[651,33226,33227,33229,33231,33233],{},[671,33228,673],{},[671,33230,676],{},[671,33232,679],{},[671,33234,33235],{},[546,33236,684],{},[651,33238,33239,33241,33243,33245],{},[671,33240,689],{},[671,33242,692],{},[671,33244,695],{},[671,33246,33247],{},[546,33248,700],{},[651,33250,33251,33253,33255,33257],{},[671,33252,705],{},[671,33254,708],{},[671,33256,711],{},[671,33258,33259],{},[546,33260,716],{},[651,33262,33263,33265,33267,33269],{},[671,33264,721],{},[671,33266,724],{},[671,33268,727],{},[671,33270,33271],{},[546,33272,732],{},[20,33274,735],{},[161,33276,33277],{"icon":738,"title":739},[20,33278,742],{},[72,33280],{},[15,33282,748],{"id":747},[31,33284,752],{"id":751},[20,33286,755],{},[47,33288,33289],{"className":758,"code":759,"filename":760,"language":761,"meta":55,"style":55},[39,33290,33291,33295,33307,33311,33315],{"__ignoreMap":55},[250,33292,33293],{"class":252,"line":253},[250,33294,769],{"class":768},[250,33296,33297,33299,33301,33303,33305],{"class":252,"line":113},[250,33298,775],{"class":774},[250,33300,779],{"class":778},[250,33302,783],{"class":782},[250,33304,787],{"class":786},[250,33306,790],{"class":774},[250,33308,33309],{"class":252,"line":110},[250,33310,795],{"emptyLinePlaceholder":129},[250,33312,33313],{"class":252,"line":269},[250,33314,800],{"class":768},[250,33316,33317,33319,33321],{"class":252,"line":275},[250,33318,805],{"class":774},[250,33320,808],{"class":782},[250,33322,811],{"class":782},[20,33324,814],{},[47,33326,33327],{"className":758,"code":817,"filename":760,"language":761,"meta":55,"style":55},[39,33328,33329,33335],{"__ignoreMap":55},[250,33330,33331,33333],{"class":252,"line":253},[250,33332,824],{"class":774},[250,33334,827],{"class":778},[250,33336,33337],{"class":252,"line":113},[250,33338,832],{"class":768},[72,33340],{},[31,33342,838],{"id":837},[20,33344,841],{},[47,33346,33347],{"className":758,"code":844,"filename":760,"language":761,"meta":55,"style":55},[39,33348,33349,33353,33363,33367],{"__ignoreMap":55},[250,33350,33351],{"class":252,"line":253},[250,33352,851],{"class":768},[250,33354,33355,33357,33359,33361],{"class":252,"line":113},[250,33356,856],{"class":774},[250,33358,859],{"class":782},[250,33360,862],{"class":782},[250,33362,865],{"class":782},[250,33364,33365],{"class":252,"line":110},[250,33366,795],{"emptyLinePlaceholder":129},[250,33368,33369,33371],{"class":252,"line":269},[250,33370,874],{"class":778},[250,33372,865],{"class":782},[24,33374,33375],{"type":26},[20,33376,881],{},[20,33378,884],{},[47,33380,33381],{"className":758,"code":887,"filename":760,"language":761,"meta":55,"style":55},[39,33382,33383],{"__ignoreMap":55},[250,33384,33385,33387],{"class":252,"line":253},[250,33386,824],{"class":774},[250,33388,896],{"class":782},[20,33390,899],{},[47,33392,33393],{"className":902,"code":903,"filename":904,"language":905,"meta":55,"style":55},[39,33394,33395,33399,33409,33415,33425,33435,33445,33453,33457],{"__ignoreMap":55},[250,33396,33397],{"class":252,"line":253},[250,33398,913],{"class":912},[250,33400,33401,33403,33405,33407],{"class":252,"line":113},[250,33402,918],{"class":778},[250,33404,921],{"class":912},[250,33406,924],{"class":782},[250,33408,927],{"class":912},[250,33410,33411,33413],{"class":252,"line":110},[250,33412,932],{"class":778},[250,33414,935],{"class":912},[250,33416,33417,33419,33421,33423],{"class":252,"line":269},[250,33418,940],{"class":778},[250,33420,921],{"class":912},[250,33422,945],{"class":782},[250,33424,927],{"class":912},[250,33426,33427,33429,33431,33433],{"class":252,"line":275},[250,33428,952],{"class":778},[250,33430,921],{"class":912},[250,33432,957],{"class":782},[250,33434,927],{"class":912},[250,33436,33437,33439,33441,33443],{"class":252,"line":281},[250,33438,964],{"class":778},[250,33440,921],{"class":912},[250,33442,969],{"class":782},[250,33444,927],{"class":912},[250,33446,33447,33449,33451],{"class":252,"line":287},[250,33448,976],{"class":778},[250,33450,921],{"class":912},[250,33452,981],{"class":782},[250,33454,33455],{"class":252,"line":293},[250,33456,986],{"class":912},[250,33458,33459],{"class":252,"line":299},[250,33460,991],{"class":912},[72,33462],{},[31,33464,997],{"id":996},[20,33466,1000],{},[20,33468,1003,33469,1007],{},[39,33470,1006],{},[47,33472,33473],{"className":1010,"code":1011,"filename":1006,"language":1012,"meta":55,"style":55},[39,33474,33475,33485,33489,33497,33501,33505,33509,33517,33521],{"__ignoreMap":55},[250,33476,33477,33479,33481,33483],{"class":252,"line":253},[250,33478,1019],{"class":786},[250,33480,1022],{"class":786},[250,33482,1025],{"class":774},[250,33484,1028],{"class":912},[250,33486,33487],{"class":252,"line":113},[250,33488,1033],{"class":912},[250,33490,33491,33493,33495],{"class":252,"line":110},[250,33492,1038],{"class":912},[250,33494,1041],{"class":782},[250,33496,927],{"class":912},[250,33498,33499],{"class":252,"line":269},[250,33500,1048],{"class":912},[250,33502,33503],{"class":252,"line":275},[250,33504,1053],{"class":912},[250,33506,33507],{"class":252,"line":281},[250,33508,1058],{"class":912},[250,33510,33511,33513,33515],{"class":252,"line":287},[250,33512,1063],{"class":912},[250,33514,1066],{"class":778},[250,33516,927],{"class":912},[250,33518,33519],{"class":252,"line":293},[250,33520,1048],{"class":912},[250,33522,33523],{"class":252,"line":299},[250,33524,1077],{"class":912},[20,33526,1080],{},[72,33528],{},[31,33530,1086],{"id":1085},[20,33532,1089],{},[20,33534,1092,33535,1007],{},[39,33536,1095],{},[47,33538,33539],{"className":1010,"code":1098,"filename":1095,"language":1012,"meta":55,"style":55},[39,33540,33541,33555,33561,33569,33577,33585,33589],{"__ignoreMap":55},[250,33542,33543,33545,33547,33549,33551,33553],{"class":252,"line":253},[250,33544,1019],{"class":786},[250,33546,1022],{"class":786},[250,33548,1109],{"class":774},[250,33550,1112],{"class":912},[250,33552,1115],{"class":786},[250,33554,1118],{"class":912},[250,33556,33557,33559],{"class":252,"line":113},[250,33558,1123],{"class":786},[250,33560,1118],{"class":912},[250,33562,33563,33565,33567],{"class":252,"line":110},[250,33564,1130],{"class":912},[250,33566,1133],{"class":782},[250,33568,927],{"class":912},[250,33570,33571,33573,33575],{"class":252,"line":269},[250,33572,1140],{"class":912},[250,33574,1143],{"class":782},[250,33576,927],{"class":912},[250,33578,33579,33581,33583],{"class":252,"line":275},[250,33580,1150],{"class":912},[250,33582,1153],{"class":774},[250,33584,1156],{"class":912},[250,33586,33587],{"class":252,"line":281},[250,33588,1161],{"class":912},[250,33590,33591],{"class":252,"line":287},[250,33592,1077],{"class":912},[20,33594,1092,33595,1171],{},[39,33596,1170],{},[47,33598,33599],{"className":1010,"code":1174,"filename":1170,"language":1012,"meta":55,"style":55},[39,33600,33601,33611,33631,33651,33671,33691,33711,33715,33719,33733,33739],{"__ignoreMap":55},[250,33602,33603,33605,33607,33609],{"class":252,"line":253},[250,33604,1181],{"class":786},[250,33606,1184],{"class":778},[250,33608,1187],{"class":786},[250,33610,1190],{"class":912},[250,33612,33613,33615,33617,33619,33621,33623,33625,33627,33629],{"class":252,"line":113},[250,33614,1195],{"class":912},[250,33616,1198],{"class":778},[250,33618,1201],{"class":912},[250,33620,1204],{"class":782},[250,33622,1207],{"class":912},[250,33624,1210],{"class":778},[250,33626,1213],{"class":912},[250,33628,1216],{"class":782},[250,33630,1219],{"class":912},[250,33632,33633,33635,33637,33639,33641,33643,33645,33647,33649],{"class":252,"line":110},[250,33634,1195],{"class":912},[250,33636,1226],{"class":778},[250,33638,1201],{"class":912},[250,33640,1231],{"class":782},[250,33642,1207],{"class":912},[250,33644,1236],{"class":778},[250,33646,1213],{"class":912},[250,33648,1216],{"class":782},[250,33650,1219],{"class":912},[250,33652,33653,33655,33657,33659,33661,33663,33665,33667,33669],{"class":252,"line":269},[250,33654,1195],{"class":912},[250,33656,1249],{"class":778},[250,33658,1201],{"class":912},[250,33660,1254],{"class":782},[250,33662,1207],{"class":912},[250,33664,1259],{"class":778},[250,33666,1213],{"class":912},[250,33668,1264],{"class":782},[250,33670,1219],{"class":912},[250,33672,33673,33675,33677,33679,33681,33683,33685,33687,33689],{"class":252,"line":275},[250,33674,1195],{"class":912},[250,33676,1273],{"class":778},[250,33678,1201],{"class":912},[250,33680,1278],{"class":782},[250,33682,1207],{"class":912},[250,33684,1283],{"class":778},[250,33686,1213],{"class":912},[250,33688,1288],{"class":782},[250,33690,1219],{"class":912},[250,33692,33693,33695,33697,33699,33701,33703,33705,33707,33709],{"class":252,"line":281},[250,33694,1195],{"class":912},[250,33696,1297],{"class":778},[250,33698,1201],{"class":912},[250,33700,1302],{"class":782},[250,33702,1207],{"class":912},[250,33704,1236],{"class":778},[250,33706,1213],{"class":912},[250,33708,1264],{"class":782},[250,33710,1219],{"class":912},[250,33712,33713],{"class":252,"line":287},[250,33714,1317],{"class":912},[250,33716,33717],{"class":252,"line":293},[250,33718,795],{"emptyLinePlaceholder":129},[250,33720,33721,33723,33725,33727,33729,33731],{"class":252,"line":299},[250,33722,1019],{"class":786},[250,33724,1022],{"class":786},[250,33726,1109],{"class":774},[250,33728,1112],{"class":912},[250,33730,1115],{"class":786},[250,33732,1118],{"class":912},[250,33734,33735,33737],{"class":252,"line":132},[250,33736,1123],{"class":786},[250,33738,1342],{"class":912},[250,33740,33741],{"class":252,"line":310},[250,33742,1077],{"class":912},[20,33744,1349],{},[47,33746,33747],{"className":1010,"code":1352,"filename":1353,"language":1012,"meta":55,"style":55},[39,33748,33749,33757,33767,33777,33781,33785,33801,33805,33827,33847,33851,33873,33881,33889,33897,33901,33905,33909,33913,33937,33941,33951,33959,33963,33971,33985,33989,33993,34001,34005,34011],{"__ignoreMap":55},[250,33750,33751,33753,33755],{"class":252,"line":253},[250,33752,1360],{"class":786},[250,33754,1363],{"class":774},[250,33756,1118],{"class":912},[250,33758,33759,33761,33763,33765],{"class":252,"line":113},[250,33760,1371],{"class":1370},[250,33762,1007],{"class":786},[250,33764,1376],{"class":778},[250,33766,1379],{"class":912},[250,33768,33769,33771,33773,33775],{"class":252,"line":110},[250,33770,1384],{"class":1370},[250,33772,1007],{"class":786},[250,33774,1376],{"class":778},[250,33776,1379],{"class":912},[250,33778,33779],{"class":252,"line":269},[250,33780,991],{"class":912},[250,33782,33783],{"class":252,"line":275},[250,33784,795],{"emptyLinePlaceholder":129},[250,33786,33787,33789,33791,33793,33795,33797,33799],{"class":252,"line":281},[250,33788,1181],{"class":786},[250,33790,1405],{"class":778},[250,33792,1007],{"class":786},[250,33794,1410],{"class":778},[250,33796,1413],{"class":912},[250,33798,1416],{"class":786},[250,33800,1419],{"class":912},[250,33802,33803],{"class":252,"line":287},[250,33804,795],{"emptyLinePlaceholder":129},[250,33806,33807,33809,33811,33813,33815,33817,33819,33821,33823,33825],{"class":252,"line":293},[250,33808,1019],{"class":786},[250,33810,1022],{"class":786},[250,33812,1109],{"class":774},[250,33814,1434],{"class":912},[250,33816,1437],{"class":786},[250,33818,1440],{"class":912},[250,33820,1443],{"class":1370},[250,33822,1446],{"class":912},[250,33824,1115],{"class":786},[250,33826,1118],{"class":912},[250,33828,33829,33831,33833,33835,33837,33839,33841,33843,33845],{"class":252,"line":299},[250,33830,1455],{"class":786},[250,33832,1458],{"class":778},[250,33834,1187],{"class":786},[250,33836,1463],{"class":786},[250,33838,1466],{"class":774},[250,33840,1469],{"class":912},[250,33842,1472],{"class":786},[250,33844,1363],{"class":774},[250,33846,1477],{"class":912},[250,33848,33849],{"class":252,"line":132},[250,33850,1053],{"class":912},[250,33852,33853,33855,33857,33859,33861,33863,33865,33867,33869,33871],{"class":252,"line":310},[250,33854,1486],{"class":786},[250,33856,1440],{"class":912},[250,33858,1491],{"class":786},[250,33860,1494],{"class":912},[250,33862,1497],{"class":786},[250,33864,1500],{"class":912},[250,33866,1503],{"class":778},[250,33868,1506],{"class":786},[250,33870,1509],{"class":778},[250,33872,1512],{"class":912},[250,33874,33875,33877,33879],{"class":252,"line":316},[250,33876,1517],{"class":786},[250,33878,1520],{"class":774},[250,33880,1028],{"class":912},[250,33882,33883,33885,33887],{"class":252,"line":322},[250,33884,1527],{"class":912},[250,33886,1530],{"class":778},[250,33888,927],{"class":912},[250,33890,33891,33893,33895],{"class":252,"line":328},[250,33892,1537],{"class":912},[250,33894,1540],{"class":782},[250,33896,927],{"class":912},[250,33898,33899],{"class":252,"line":334},[250,33900,1547],{"class":912},[250,33902,33903],{"class":252,"line":340},[250,33904,986],{"class":912},[250,33906,33907],{"class":252,"line":346},[250,33908,1053],{"class":912},[250,33910,33911],{"class":252,"line":352},[250,33912,1560],{"class":768},[250,33914,33915,33917,33919,33921,33923,33925,33927,33929,33931,33933,33935],{"class":252,"line":358},[250,33916,1565],{"class":786},[250,33918,1568],{"class":786},[250,33920,1571],{"class":778},[250,33922,1574],{"class":912},[250,33924,1577],{"class":1370},[250,33926,1446],{"class":912},[250,33928,1115],{"class":786},[250,33930,1584],{"class":774},[250,33932,1587],{"class":912},[250,33934,1590],{"class":778},[250,33936,1593],{"class":912},[250,33938,33939],{"class":252,"line":364},[250,33940,1053],{"class":912},[250,33942,33943,33945,33947,33949],{"class":252,"line":370},[250,33944,1455],{"class":786},[250,33946,1604],{"class":778},[250,33948,1187],{"class":786},[250,33950,1118],{"class":912},[250,33952,33953,33955,33957],{"class":252,"line":376},[250,33954,1613],{"class":912},[250,33956,1616],{"class":774},[250,33958,1156],{"class":912},[250,33960,33961],{"class":252,"line":382},[250,33962,1623],{"class":912},[250,33964,33965,33967,33969],{"class":252,"line":388},[250,33966,1628],{"class":912},[250,33968,1631],{"class":782},[250,33970,927],{"class":912},[250,33972,33973,33975,33977,33979,33981,33983],{"class":252,"line":393},[250,33974,1638],{"class":912},[250,33976,1641],{"class":786},[250,33978,1644],{"class":774},[250,33980,1647],{"class":912},[250,33982,1650],{"class":774},[250,33984,1156],{"class":912},[250,33986,33987],{"class":252,"line":399},[250,33988,1161],{"class":912},[250,33990,33991],{"class":252,"line":405},[250,33992,1053],{"class":912},[250,33994,33995,33997,33999],{"class":252,"line":410},[250,33996,1665],{"class":912},[250,33998,1668],{"class":774},[250,34000,1671],{"class":912},[250,34002,34003],{"class":252,"line":415},[250,34004,1053],{"class":912},[250,34006,34007,34009],{"class":252,"line":420},[250,34008,1123],{"class":786},[250,34010,1682],{"class":912},[250,34012,34013],{"class":252,"line":426},[250,34014,1077],{"class":912},[72,34016],{},[31,34018,1692],{"id":1691},[20,34020,1695],{},[47,34022,34023],{"className":758,"code":1698,"filename":760,"language":761,"meta":55,"style":55},[39,34024,34025],{"__ignoreMap":55},[250,34026,34027,34029,34031],{"class":252,"line":253},[250,34028,824],{"class":774},[250,34030,1707],{"class":782},[250,34032,1710],{"class":782},[161,34034,34035],{"icon":1713,"title":1714},[20,34036,1717],{},[20,34038,1720],{},[47,34040,34041],{"className":758,"code":1723,"filename":760,"language":761,"meta":55,"style":55},[39,34042,34043,34049],{"__ignoreMap":55},[250,34044,34045,34047],{"class":252,"line":253},[250,34046,775],{"class":774},[250,34048,1732],{"class":782},[250,34050,34051,34053],{"class":252,"line":113},[250,34052,775],{"class":774},[250,34054,1739],{"class":782},[72,34056],{},[31,34058,1745],{"id":1744},[20,34060,1748],{},[20,34062,1092,34063,1007],{},[39,34064,1753],{},[47,34066,34067],{"className":1010,"code":1756,"filename":1753,"language":1012,"meta":55,"style":55},[39,34068,34069,34081,34085,34097,34109,34121,34133,34137,34147,34171,34175,34189,34201,34205,34215,34219,34245,34253,34269,34285,34297,34307,34313,34317,34321,34327,34347,34355,34359,34371,34377,34385,34395,34399,34407,34417,34421,34425,34429,34435,34439,34443,34447,34451,34463,34467,34485,34511,34515,34527,34543,34559,34591,34595,34599],{"__ignoreMap":55},[250,34070,34071,34073,34075,34077,34079],{"class":252,"line":253},[250,34072,1763],{"class":786},[250,34074,1766],{"class":912},[250,34076,1769],{"class":786},[250,34078,1772],{"class":782},[250,34080,1379],{"class":912},[250,34082,34083],{"class":252,"line":113},[250,34084,795],{"emptyLinePlaceholder":129},[250,34086,34087,34089,34091,34093,34095],{"class":252,"line":110},[250,34088,1181],{"class":786},[250,34090,1785],{"class":778},[250,34092,1187],{"class":786},[250,34094,1790],{"class":782},[250,34096,1379],{"class":912},[250,34098,34099,34101,34103,34105,34107],{"class":252,"line":269},[250,34100,1181],{"class":786},[250,34102,1799],{"class":778},[250,34104,1187],{"class":786},[250,34106,1804],{"class":778},[250,34108,1379],{"class":912},[250,34110,34111,34113,34115,34117,34119],{"class":252,"line":275},[250,34112,1181],{"class":786},[250,34114,1813],{"class":778},[250,34116,1187],{"class":786},[250,34118,1818],{"class":778},[250,34120,1379],{"class":912},[250,34122,34123,34125,34127,34129,34131],{"class":252,"line":281},[250,34124,1181],{"class":786},[250,34126,1827],{"class":778},[250,34128,1187],{"class":786},[250,34130,1832],{"class":778},[250,34132,1379],{"class":912},[250,34134,34135],{"class":252,"line":287},[250,34136,795],{"emptyLinePlaceholder":129},[250,34138,34139,34141,34143,34145],{"class":252,"line":293},[250,34140,1437],{"class":786},[250,34142,1845],{"class":786},[250,34144,1848],{"class":774},[250,34146,1851],{"class":912},[250,34148,34149,34151,34153,34155,34157,34159,34161,34163,34165,34167,34169],{"class":252,"line":299},[250,34150,1856],{"class":912},[250,34152,1859],{"class":774},[250,34154,1434],{"class":912},[250,34156,1864],{"class":782},[250,34158,1867],{"class":778},[250,34160,1870],{"class":782},[250,34162,1873],{"class":778},[250,34164,1876],{"class":782},[250,34166,1879],{"class":778},[250,34168,1882],{"class":782},[250,34170,1885],{"class":912},[250,34172,34173],{"class":252,"line":132},[250,34174,1053],{"class":912},[250,34176,34177,34179,34181,34183,34185,34187],{"class":252,"line":310},[250,34178,1455],{"class":786},[250,34180,1896],{"class":778},[250,34182,1187],{"class":786},[250,34184,1901],{"class":912},[250,34186,1153],{"class":774},[250,34188,1906],{"class":912},[250,34190,34191,34193,34195,34197,34199],{"class":252,"line":316},[250,34192,1911],{"class":786},[250,34194,1914],{"class":912},[250,34196,1416],{"class":786},[250,34198,1509],{"class":778},[250,34200,1379],{"class":912},[250,34202,34203],{"class":252,"line":322},[250,34204,1053],{"class":912},[250,34206,34207,34209,34211,34213],{"class":252,"line":328},[250,34208,1455],{"class":786},[250,34210,1931],{"class":778},[250,34212,1187],{"class":786},[250,34214,1419],{"class":912},[250,34216,34217],{"class":252,"line":334},[250,34218,1053],{"class":912},[250,34220,34221,34223,34225,34227,34229,34231,34233,34235,34237,34239,34241,34243],{"class":252,"line":340},[250,34222,1944],{"class":786},[250,34224,1440],{"class":912},[250,34226,1949],{"class":786},[250,34228,1952],{"class":912},[250,34230,1416],{"class":786},[250,34232,1509],{"class":778},[250,34234,1959],{"class":912},[250,34236,1962],{"class":786},[250,34238,1827],{"class":778},[250,34240,1967],{"class":912},[250,34242,1970],{"class":786},[250,34244,1512],{"class":912},[250,34246,34247,34249,34251],{"class":252,"line":346},[250,34248,1977],{"class":912},[250,34250,1668],{"class":774},[250,34252,1982],{"class":912},[250,34254,34255,34257,34259,34261,34263,34265,34267],{"class":252,"line":352},[250,34256,1987],{"class":786},[250,34258,1571],{"class":778},[250,34260,1574],{"class":912},[250,34262,1577],{"class":1370},[250,34264,1446],{"class":912},[250,34266,1115],{"class":786},[250,34268,1118],{"class":912},[250,34270,34271,34273,34275,34277,34279,34281,34283],{"class":252,"line":358},[250,34272,2004],{"class":786},[250,34274,2007],{"class":774},[250,34276,1187],{"class":786},[250,34278,2012],{"class":786},[250,34280,2015],{"class":912},[250,34282,1115],{"class":786},[250,34284,1118],{"class":912},[250,34286,34287,34289,34291,34293,34295],{"class":252,"line":364},[250,34288,2024],{"class":786},[250,34290,2027],{"class":912},[250,34292,2030],{"class":786},[250,34294,1813],{"class":778},[250,34296,1512],{"class":912},[250,34298,34299,34301,34303,34305],{"class":252,"line":370},[250,34300,2039],{"class":774},[250,34302,1434],{"class":912},[250,34304,1066],{"class":778},[250,34306,1885],{"class":912},[250,34308,34309,34311],{"class":252,"line":376},[250,34310,2050],{"class":786},[250,34312,1379],{"class":912},[250,34314,34315],{"class":252,"line":382},[250,34316,2057],{"class":912},[250,34318,34319],{"class":252,"line":388},[250,34320,2062],{"class":912},[250,34322,34323,34325],{"class":252,"line":393},[250,34324,2067],{"class":786},[250,34326,1118],{"class":912},[250,34328,34329,34331,34333,34335,34337,34339,34341,34343,34345],{"class":252,"line":399},[250,34330,2074],{"class":786},[250,34332,2077],{"class":774},[250,34334,1434],{"class":912},[250,34336,2082],{"class":782},[250,34338,2085],{"class":778},[250,34340,2088],{"class":782},[250,34342,2091],{"class":778},[250,34344,2094],{"class":782},[250,34346,1885],{"class":912},[250,34348,34349,34351,34353],{"class":252,"line":405},[250,34350,2101],{"class":912},[250,34352,1970],{"class":786},[250,34354,1379],{"class":912},[250,34356,34357],{"class":252,"line":410},[250,34358,2110],{"class":912},[250,34360,34361,34363,34365,34367,34369],{"class":252,"line":415},[250,34362,2115],{"class":786},[250,34364,2027],{"class":912},[250,34366,1962],{"class":786},[250,34368,1813],{"class":778},[250,34370,1512],{"class":912},[250,34372,34373,34375],{"class":252,"line":420},[250,34374,2128],{"class":774},[250,34376,1906],{"class":912},[250,34378,34379,34381,34383],{"class":252,"line":426},[250,34380,2135],{"class":912},[250,34382,2138],{"class":786},[250,34384,1118],{"class":912},[250,34386,34387,34389,34391,34393],{"class":252,"line":431},[250,34388,2145],{"class":774},[250,34390,1434],{"class":912},[250,34392,1066],{"class":778},[250,34394,1885],{"class":912},[250,34396,34397],{"class":252,"line":436},[250,34398,2156],{"class":912},[250,34400,34401,34403,34405],{"class":252,"line":442},[250,34402,2161],{"class":912},[250,34404,2164],{"class":786},[250,34406,2167],{"class":912},[250,34408,34409,34411,34413,34415],{"class":252,"line":447},[250,34410,2039],{"class":774},[250,34412,1434],{"class":912},[250,34414,1066],{"class":778},[250,34416,1885],{"class":912},[250,34418,34419],{"class":252,"line":453},[250,34420,2057],{"class":912},[250,34422,34423],{"class":252,"line":459},[250,34424,2186],{"class":912},[250,34426,34427],{"class":252,"line":465},[250,34428,2191],{"class":912},[250,34430,34431,34433],{"class":252,"line":471},[250,34432,2196],{"class":774},[250,34434,1906],{"class":912},[250,34436,34437],{"class":252,"line":2201},[250,34438,2204],{"class":912},[250,34440,34441],{"class":252,"line":2207},[250,34442,2210],{"class":912},[250,34444,34445],{"class":252,"line":2213},[250,34446,986],{"class":912},[250,34448,34449],{"class":252,"line":2218},[250,34450,1053],{"class":912},[250,34452,34453,34455,34457,34459,34461],{"class":252,"line":2223},[250,34454,1565],{"class":786},[250,34456,1571],{"class":778},[250,34458,2230],{"class":912},[250,34460,2233],{"class":774},[250,34462,2236],{"class":912},[250,34464,34465],{"class":252,"line":2239},[250,34466,1053],{"class":912},[250,34468,34469,34471,34473,34475,34477,34479,34481,34483],{"class":252,"line":2244},[250,34470,1455],{"class":786},[250,34472,2249],{"class":778},[250,34474,1187],{"class":786},[250,34476,1901],{"class":912},[250,34478,1153],{"class":774},[250,34480,2258],{"class":912},[250,34482,2261],{"class":786},[250,34484,2264],{"class":912},[250,34486,34487,34489,34491,34493,34495,34497,34499,34501,34503,34505,34507,34509],{"class":252,"line":2267},[250,34488,1455],{"class":786},[250,34490,2272],{"class":778},[250,34492,1187],{"class":786},[250,34494,2277],{"class":912},[250,34496,2280],{"class":774},[250,34498,1434],{"class":912},[250,34500,1867],{"class":778},[250,34502,2287],{"class":786},[250,34504,2290],{"class":912},[250,34506,2293],{"class":786},[250,34508,2296],{"class":778},[250,34510,1593],{"class":912},[250,34512,34513],{"class":252,"line":2301},[250,34514,1053],{"class":912},[250,34516,34517,34519,34521,34523,34525],{"class":252,"line":2306},[250,34518,1856],{"class":912},[250,34520,1859],{"class":774},[250,34522,1434],{"class":912},[250,34524,2315],{"class":782},[250,34526,1885],{"class":912},[250,34528,34529,34531,34533,34535,34537,34539,34541],{"class":252,"line":2320},[250,34530,1856],{"class":912},[250,34532,1859],{"class":774},[250,34534,1434],{"class":912},[250,34536,2329],{"class":782},[250,34538,2332],{"class":912},[250,34540,2335],{"class":782},[250,34542,1885],{"class":912},[250,34544,34545,34547,34549,34551,34553,34555,34557],{"class":252,"line":2340},[250,34546,1856],{"class":912},[250,34548,1859],{"class":774},[250,34550,1434],{"class":912},[250,34552,2349],{"class":782},[250,34554,2352],{"class":912},[250,34556,2355],{"class":782},[250,34558,1885],{"class":912},[250,34560,34561,34563,34565,34567,34569,34571,34573,34575,34577,34579,34581,34583,34585,34587,34589],{"class":252,"line":2360},[250,34562,1856],{"class":912},[250,34564,1859],{"class":774},[250,34566,1434],{"class":912},[250,34568,2369],{"class":782},[250,34570,1434],{"class":782},[250,34572,2332],{"class":912},[250,34574,2287],{"class":786},[250,34576,1813],{"class":778},[250,34578,2380],{"class":782},[250,34580,2383],{"class":774},[250,34582,1434],{"class":782},[250,34584,1226],{"class":778},[250,34586,2390],{"class":782},[250,34588,2335],{"class":782},[250,34590,1885],{"class":912},[250,34592,34593],{"class":252,"line":2397},[250,34594,991],{"class":912},[250,34596,34597],{"class":252,"line":2402},[250,34598,795],{"emptyLinePlaceholder":129},[250,34600,34601,34603],{"class":252,"line":2407},[250,34602,2410],{"class":774},[250,34604,1906],{"class":912},[20,34606,2415],{},[47,34608,34609],{"className":758,"code":2418,"filename":760,"language":761,"meta":55,"style":55},[39,34610,34611,34615,34623,34627,34631],{"__ignoreMap":55},[250,34612,34613],{"class":252,"line":253},[250,34614,2425],{"class":768},[250,34616,34617,34619,34621],{"class":252,"line":113},[250,34618,824],{"class":774},[250,34620,1707],{"class":782},[250,34622,1710],{"class":782},[250,34624,34625],{"class":252,"line":110},[250,34626,795],{"emptyLinePlaceholder":129},[250,34628,34629],{"class":252,"line":269},[250,34630,2442],{"class":768},[250,34632,34633,34635,34637],{"class":252,"line":275},[250,34634,824],{"class":774},[250,34636,1707],{"class":782},[250,34638,2451],{"class":782},[72,34640],{},[31,34642,2457],{"id":2456},[2459,34644,2462],{"id":2461},[20,34646,2465],{},[47,34648,34649],{"className":1010,"code":2468,"filename":2469,"language":1012,"meta":55,"style":55},[39,34650,34651,34655,34663,34673,34683,34693,34697,34701,34717,34733,34749,34753,34757,34771,34777,34781,34785,34789,34793],{"__ignoreMap":55},[250,34652,34653],{"class":252,"line":253},[250,34654,2476],{"class":768},[250,34656,34657,34659,34661],{"class":252,"line":113},[250,34658,1360],{"class":786},[250,34660,2483],{"class":774},[250,34662,1118],{"class":912},[250,34664,34665,34667,34669,34671],{"class":252,"line":110},[250,34666,2490],{"class":1370},[250,34668,1007],{"class":786},[250,34670,1376],{"class":778},[250,34672,1379],{"class":912},[250,34674,34675,34677,34679,34681],{"class":252,"line":269},[250,34676,2501],{"class":1370},[250,34678,1007],{"class":786},[250,34680,2506],{"class":778},[250,34682,1379],{"class":912},[250,34684,34685,34687,34689,34691],{"class":252,"line":275},[250,34686,2513],{"class":1370},[250,34688,1007],{"class":786},[250,34690,1376],{"class":778},[250,34692,1379],{"class":912},[250,34694,34695],{"class":252,"line":281},[250,34696,991],{"class":912},[250,34698,34699],{"class":252,"line":287},[250,34700,795],{"emptyLinePlaceholder":129},[250,34702,34703,34705,34707,34709,34711,34713,34715],{"class":252,"line":293},[250,34704,1181],{"class":786},[250,34706,1184],{"class":778},[250,34708,1007],{"class":786},[250,34710,2483],{"class":774},[250,34712,1413],{"class":912},[250,34714,1416],{"class":786},[250,34716,1190],{"class":912},[250,34718,34719,34721,34723,34725,34727,34729,34731],{"class":252,"line":299},[250,34720,1195],{"class":912},[250,34722,1198],{"class":778},[250,34724,1201],{"class":912},[250,34726,1204],{"class":782},[250,34728,1207],{"class":912},[250,34730,1210],{"class":778},[250,34732,1219],{"class":912},[250,34734,34735,34737,34739,34741,34743,34745,34747],{"class":252,"line":132},[250,34736,1195],{"class":912},[250,34738,1226],{"class":778},[250,34740,1201],{"class":912},[250,34742,1231],{"class":782},[250,34744,1207],{"class":912},[250,34746,1236],{"class":778},[250,34748,1219],{"class":912},[250,34750,34751],{"class":252,"line":310},[250,34752,1317],{"class":912},[250,34754,34755],{"class":252,"line":316},[250,34756,795],{"emptyLinePlaceholder":129},[250,34758,34759,34761,34763,34765,34767,34769],{"class":252,"line":322},[250,34760,1019],{"class":786},[250,34762,1022],{"class":786},[250,34764,1109],{"class":774},[250,34766,1112],{"class":912},[250,34768,1115],{"class":786},[250,34770,1118],{"class":912},[250,34772,34773,34775],{"class":252,"line":328},[250,34774,1123],{"class":786},[250,34776,1118],{"class":912},[250,34778,34779],{"class":252,"line":334},[250,34780,2608],{"class":912},[250,34782,34783],{"class":252,"line":340},[250,34784,2613],{"class":912},[250,34786,34787],{"class":252,"line":346},[250,34788,2618],{"class":912},[250,34790,34791],{"class":252,"line":352},[250,34792,1161],{"class":912},[250,34794,34795],{"class":252,"line":358},[250,34796,1077],{"class":912},[2459,34798,2630],{"id":2629},[20,34800,2633],{},[47,34802,34803],{"className":1010,"code":2636,"filename":2637,"language":1012,"meta":55,"style":55},[39,34804,34805,34827,34845,34861,34865,34871],{"__ignoreMap":55},[250,34806,34807,34809,34811,34813,34815,34817,34819,34821,34823,34825],{"class":252,"line":253},[250,34808,1019],{"class":786},[250,34810,1022],{"class":786},[250,34812,1109],{"class":774},[250,34814,1434],{"class":912},[250,34816,1437],{"class":786},[250,34818,1440],{"class":912},[250,34820,1443],{"class":1370},[250,34822,1446],{"class":912},[250,34824,1115],{"class":786},[250,34826,1118],{"class":912},[250,34828,34829,34831,34833,34835,34837,34839,34841,34843],{"class":252,"line":113},[250,34830,1455],{"class":786},[250,34832,2668],{"class":778},[250,34834,1187],{"class":786},[250,34836,2673],{"class":912},[250,34838,2676],{"class":774},[250,34840,1434],{"class":912},[250,34842,2681],{"class":782},[250,34844,1885],{"class":912},[250,34846,34847,34849,34851,34853,34855,34857,34859],{"class":252,"line":110},[250,34848,1455],{"class":786},[250,34850,2690],{"class":778},[250,34852,1187],{"class":786},[250,34854,1463],{"class":786},[250,34856,2697],{"class":912},[250,34858,905],{"class":774},[250,34860,1906],{"class":912},[250,34862,34863],{"class":252,"line":269},[250,34864,1053],{"class":912},[250,34866,34867,34869],{"class":252,"line":275},[250,34868,1123],{"class":786},[250,34870,2712],{"class":912},[250,34872,34873],{"class":252,"line":281},[250,34874,1077],{"class":912},[2459,34876,2720],{"id":2719},[20,34878,2723],{},[47,34880,34881],{"className":1010,"code":2726,"filename":2727,"language":1012,"meta":55,"style":55},[39,34882,34883,34901,34911,34917,34923,34929,34933,34937,34941,34959,34993,34997,35001,35007,35023,35037,35041],{"__ignoreMap":55},[250,34884,34885,34887,34889,34891,34893,34895,34897,34899],{"class":252,"line":253},[250,34886,1019],{"class":786},[250,34888,1022],{"class":786},[250,34890,1109],{"class":774},[250,34892,1434],{"class":912},[250,34894,1437],{"class":786},[250,34896,2015],{"class":912},[250,34898,1115],{"class":786},[250,34900,1118],{"class":912},[250,34902,34903,34905,34907,34909],{"class":252,"line":113},[250,34904,1455],{"class":786},[250,34906,2754],{"class":778},[250,34908,1187],{"class":786},[250,34910,1190],{"class":912},[250,34912,34913,34915],{"class":252,"line":110},[250,34914,2763],{"class":782},[250,34916,927],{"class":912},[250,34918,34919,34921],{"class":252,"line":269},[250,34920,2770],{"class":782},[250,34922,927],{"class":912},[250,34924,34925,34927],{"class":252,"line":275},[250,34926,2777],{"class":782},[250,34928,927],{"class":912},[250,34930,34931],{"class":252,"line":281},[250,34932,2784],{"class":912},[250,34934,34935],{"class":252,"line":287},[250,34936,1053],{"class":912},[250,34938,34939],{"class":252,"line":293},[250,34940,2793],{"class":768},[250,34942,34943,34945,34947,34949,34951,34953,34955,34957],{"class":252,"line":299},[250,34944,1455],{"class":786},[250,34946,2800],{"class":778},[250,34948,1187],{"class":786},[250,34950,1463],{"class":786},[250,34952,1571],{"class":778},[250,34954,2230],{"class":912},[250,34956,2233],{"class":774},[250,34958,1982],{"class":912},[250,34960,34961,34963,34965,34967,34969,34971,34973,34975,34977,34979,34981,34983,34985,34987,34989,34991],{"class":252,"line":132},[250,34962,2817],{"class":912},[250,34964,2820],{"class":774},[250,34966,1574],{"class":912},[250,34968,2825],{"class":1370},[250,34970,1446],{"class":912},[250,34972,1115],{"class":786},[250,34974,2077],{"class":774},[250,34976,2834],{"class":912},[250,34978,2837],{"class":774},[250,34980,1574],{"class":912},[250,34982,2842],{"class":1370},[250,34984,1446],{"class":912},[250,34986,1115],{"class":786},[250,34988,2849],{"class":912},[250,34990,905],{"class":774},[250,34992,2854],{"class":912},[250,34994,34995],{"class":252,"line":310},[250,34996,2859],{"class":912},[250,34998,34999],{"class":252,"line":316},[250,35000,1053],{"class":912},[250,35002,35003,35005],{"class":252,"line":322},[250,35004,1123],{"class":786},[250,35006,1118],{"class":912},[250,35008,35009,35011,35013,35015,35017,35019,35021],{"class":252,"line":328},[250,35010,2874],{"class":912},[250,35012,2820],{"class":774},[250,35014,1574],{"class":912},[250,35016,2842],{"class":1370},[250,35018,1446],{"class":912},[250,35020,1115],{"class":786},[250,35022,2887],{"class":912},[250,35024,35025,35027,35029,35031,35033,35035],{"class":252,"line":334},[250,35026,2892],{"class":912},[250,35028,1641],{"class":786},[250,35030,1644],{"class":774},[250,35032,1647],{"class":912},[250,35034,1650],{"class":774},[250,35036,1156],{"class":912},[250,35038,35039],{"class":252,"line":340},[250,35040,1161],{"class":912},[250,35042,35043],{"class":252,"line":346},[250,35044,1077],{"class":912},[72,35046],{},[31,35048,2916],{"id":2915},[2459,35050,2920],{"id":2919},[2922,35052,35053,35071,35125],{},[564,35054,35055,35057,35069,2947],{},[546,35056,2928],{},[47,35058,35059],{"className":758,"code":2931,"language":761,"meta":55,"style":55},[39,35060,35061],{"__ignoreMap":55},[250,35062,35063,35065,35067],{"class":252,"line":253},[250,35064,824],{"class":774},[250,35066,2940],{"class":782},[250,35068,2943],{"class":782},[2945,35070],{},[564,35072,35073,35075],{},[546,35074,2952],{},[47,35076,35077],{"className":902,"code":2955,"language":905,"meta":55,"style":55},[39,35078,35079,35083,35089,35099,35109,35117,35121],{"__ignoreMap":55},[250,35080,35081],{"class":252,"line":253},[250,35082,913],{"class":912},[250,35084,35085,35087],{"class":252,"line":113},[250,35086,932],{"class":778},[250,35088,935],{"class":912},[250,35090,35091,35093,35095,35097],{"class":252,"line":110},[250,35092,940],{"class":778},[250,35094,921],{"class":912},[250,35096,945],{"class":782},[250,35098,927],{"class":912},[250,35100,35101,35103,35105,35107],{"class":252,"line":269},[250,35102,952],{"class":778},[250,35104,921],{"class":912},[250,35106,957],{"class":782},[250,35108,927],{"class":912},[250,35110,35111,35113,35115],{"class":252,"line":275},[250,35112,976],{"class":778},[250,35114,921],{"class":912},[250,35116,981],{"class":782},[250,35118,35119],{"class":252,"line":281},[250,35120,986],{"class":912},[250,35122,35123],{"class":252,"line":287},[250,35124,991],{"class":912},[564,35126,35127,35129],{},[546,35128,3008],{},[47,35130,35131],{"className":758,"code":3011,"language":761,"meta":55,"style":55},[39,35132,35133,35137],{"__ignoreMap":55},[250,35134,35135],{"class":252,"line":253},[250,35136,3018],{"class":768},[250,35138,35139,35141,35143],{"class":252,"line":113},[250,35140,824],{"class":774},[250,35142,3025],{"class":778},[250,35144,3028],{"class":782},[2459,35146,3032],{"id":3031},[24,35148,35149,35159],{"type":26},[561,35150,35151,35155,35157],{},[564,35152,3039,35153],{},[39,35154,3042],{},[564,35156,3045],{},[564,35158,3048],{},[20,35160,3051,35161,3056],{},[203,35162,3054],{"href":3054,"rel":35163},[207],[72,35165],{},[31,35167,3062],{"id":3061},[2459,35169,3066],{"id":3065},[3068,35171,3071],{"id":3070},[47,35173,35174],{"className":758,"code":3074,"filename":760,"language":761,"meta":55,"style":55},[39,35175,35176,35180],{"__ignoreMap":55},[250,35177,35178],{"class":252,"line":253},[250,35179,3081],{"class":768},[250,35181,35182,35184],{"class":252,"line":113},[250,35183,3070],{"class":774},[250,35185,3088],{"class":782},[3068,35187,3092],{"id":3091},[47,35189,35190],{"className":902,"code":3095,"filename":3096,"language":905,"meta":55,"style":55},[39,35191,35192,35196,35202,35210,35214,35220,35228,35232],{"__ignoreMap":55},[250,35193,35194],{"class":252,"line":253},[250,35195,913],{"class":912},[250,35197,35198,35200],{"class":252,"line":113},[250,35199,3107],{"class":778},[250,35201,935],{"class":912},[250,35203,35204,35206,35208],{"class":252,"line":110},[250,35205,3114],{"class":778},[250,35207,921],{"class":912},[250,35209,3119],{"class":782},[250,35211,35212],{"class":252,"line":269},[250,35213,1048],{"class":912},[250,35215,35216,35218],{"class":252,"line":275},[250,35217,3128],{"class":778},[250,35219,935],{"class":912},[250,35221,35222,35224,35226],{"class":252,"line":281},[250,35223,3135],{"class":778},[250,35225,921],{"class":912},[250,35227,3140],{"class":782},[250,35229,35230],{"class":252,"line":287},[250,35231,986],{"class":912},[250,35233,35234],{"class":252,"line":293},[250,35235,991],{"class":912},[3068,35237,3152],{"id":3151},[47,35239,35240],{"className":3155,"code":3156,"filename":3157,"language":3158,"meta":55,"style":55},[39,35241,35242,35246,35250,35254,35258,35262,35266,35270,35274,35278,35282],{"__ignoreMap":55},[250,35243,35244],{"class":252,"line":253},[250,35245,3165],{},[250,35247,35248],{"class":252,"line":113},[250,35249,3170],{},[250,35251,35252],{"class":252,"line":110},[250,35253,795],{"emptyLinePlaceholder":129},[250,35255,35256],{"class":252,"line":269},[250,35257,3179],{},[250,35259,35260],{"class":252,"line":275},[250,35261,3184],{},[250,35263,35264],{"class":252,"line":281},[250,35265,795],{"emptyLinePlaceholder":129},[250,35267,35268],{"class":252,"line":287},[250,35269,3193],{},[250,35271,35272],{"class":252,"line":293},[250,35273,3198],{},[250,35275,35276],{"class":252,"line":299},[250,35277,795],{"emptyLinePlaceholder":129},[250,35279,35280],{"class":252,"line":132},[250,35281,3207],{},[250,35283,35284],{"class":252,"line":310},[250,35285,3212],{},[3068,35287,3216],{"id":3215},[20,35289,3219],{},[47,35291,35292],{"className":758,"code":3222,"filename":760,"language":761,"meta":55,"style":55},[39,35293,35294,35302],{"__ignoreMap":55},[250,35295,35296,35298,35300],{"class":252,"line":253},[250,35297,856],{"class":774},[250,35299,3231],{"class":782},[250,35301,3234],{"class":782},[250,35303,35304,35306,35308],{"class":252,"line":113},[250,35305,824],{"class":774},[250,35307,1707],{"class":782},[250,35309,3243],{"class":782},[161,35311,35312],{"icon":3246,"title":3247},[20,35313,3250],{},[72,35315],{},[31,35317,3256],{"id":3255},[20,35319,3259],{},[561,35321,35322,35324,35326,35328,35330],{},[564,35323,3264],{},[564,35325,3267],{},[564,35327,3270],{},[564,35329,3273],{},[564,35331,3276],{},[2459,35333,3280],{"id":3279},[645,35335,35336,35344],{},[648,35337,35338],{},[651,35339,35340,35342],{},[654,35341,3289],{},[654,35343,3292],{},[666,35345,35346,35354,35362,35370,35378],{},[651,35347,35348,35352],{},[671,35349,3299,35350],{},[39,35351,3302],{},[671,35353,3305],{},[651,35355,35356,35360],{},[671,35357,3299,35358],{},[39,35359,3312],{},[671,35361,3315],{},[651,35363,35364,35368],{},[671,35365,3299,35366],{},[39,35367,3322],{},[671,35369,3325],{},[651,35371,35372,35376],{},[671,35373,3299,35374],{},[39,35375,3332],{},[671,35377,3335],{},[651,35379,35380,35384],{},[671,35381,3340,35382],{},[39,35383,3343],{},[671,35385,3346],{},[72,35387],{},[15,35389,3352],{"id":3351},[20,35391,35392,3358],{},[546,35393,3357],{},[561,35395,35396,35400,35404,35408,35412],{},[564,35397,35398,3366],{},[546,35399,3365],{},[564,35401,35402,3371],{},[546,35403,603],{},[564,35405,35406,3377],{},[546,35407,3376],{},[564,35409,35410,3383],{},[546,35411,3382],{},[564,35413,35414,3389],{},[546,35415,3388],{},[20,35417,3392],{},[2459,35419,3396],{"id":3395},[561,35421,35422,35424,35426,35428,35430],{},[564,35423,3401],{},[564,35425,3404],{},[564,35427,3407],{},[564,35429,3410],{},[564,35431,3413],{},[2459,35433,3417],{"id":3416},[561,35435,35436,35438,35440],{},[564,35437,3422],{},[564,35439,3425],{},[564,35441,3428],{},[20,35443,3431],{},[20,35445,3434],{},[500,35447,3437],{},{"title":55,"searchDepth":110,"depth":110,"links":35449},[35450,35451,35452,35453,35454,35455,35456,35457,35458,35463,35467,35475],{"id":595,"depth":113,"text":596},{"id":639,"depth":113,"text":640},{"id":751,"depth":113,"text":752},{"id":837,"depth":113,"text":838},{"id":996,"depth":113,"text":997},{"id":1085,"depth":113,"text":1086},{"id":1691,"depth":113,"text":1692},{"id":1744,"depth":113,"text":1745},{"id":2456,"depth":113,"text":2457,"children":35459},[35460,35461,35462],{"id":2461,"depth":110,"text":2462},{"id":2629,"depth":110,"text":2630},{"id":2719,"depth":110,"text":2720},{"id":2915,"depth":113,"text":2916,"children":35464},[35465,35466],{"id":2919,"depth":110,"text":2920},{"id":3031,"depth":110,"text":3032},{"id":3061,"depth":113,"text":3062,"children":35468},[35469],{"id":3065,"depth":110,"text":3066,"children":35470},[35471,35472,35473,35474],{"id":3070,"depth":269,"text":3071},{"id":3091,"depth":269,"text":3092},{"id":3151,"depth":269,"text":3152},{"id":3215,"depth":269,"text":3216},{"id":3255,"depth":113,"text":3256,"children":35476},[35477,35478,35479],{"id":3279,"depth":110,"text":3280},{"id":3395,"depth":110,"text":3396},{"id":3416,"depth":110,"text":3417},{"type":12,"value":35481},[35482,35484,35488,35492,35494,35506],[15,35483,541],{"id":540},[20,35485,544,35486,549],{},[546,35487,548],{},[20,35489,552,35490,556],{},[546,35491,555],{},[20,35493,559],{},[561,35495,35496,35498,35500,35502,35504],{},[564,35497,566],{},[564,35499,569],{},[564,35501,572],{},[564,35503,575],{},[564,35505,578],{},[20,35507,581,35508,585],{},[546,35509,584],{},[824,3504,3505,3506,3507,3508,3509],{},{"title":533,"description":3471},"bun-nitro-stack",1775877437461]