[{"data":1,"prerenderedAt":1164},["ShallowReactive",2],{"blog-nuxt-vs-vue":3},{"id":4,"title":5,"articleType":6,"author":7,"authorSlug":8,"body":9,"date":1135,"description":1136,"extension":1137,"faq":1138,"featured":1152,"image":1153,"meta":1154,"navigation":370,"path":1155,"readTime":1156,"seo":1157,"seoTitle":1158,"stem":1159,"tags":1160,"__hash__":1163},"blog\u002Fblog\u002Fnuxt-vs-vue.md","Nuxt vs Vue: How They Work Together and When to Add Nuxt","TechArticle","Pavel Mironov","pavel-mironov",{"type":10,"value":11,"toc":1107},"minimark",[12,16,21,24,27,38,41,44,48,61,64,103,110,113,120,124,132,137,167,181,185,197,200,204,221,225,237,241,244,481,495,502,653,656,663,666,670,799,802,812,815,818,822,825,829,846,849,855,859,884,887,891,894,897,970,977,985,989,992,995,1003,1007,1011,1014,1018,1024,1028,1031,1035,1050,1054,1067,1071,1079,1083,1091,1095,1098,1103],[13,14,15],"p",{},"Nuxt vs Vue sounds like a framework face-off, but it isn't one. Nuxt is built on Vue, and every Nuxt app is a Vue app with extra structure around it. The real question is when that structure is worth adding. This guide explains what each one does, where Vite fits in, how the same component runs in both, and when a Vue project should move to Nuxt.",[17,18,20],"h2",{"id":19},"nuxt-vs-vue-the-short-answer","Nuxt vs Vue: The Short Answer",[13,22,23],{},"Nuxt and Vue are not competitors. Vue is the UI framework that renders components and keeps them reactive. Nuxt is a framework that runs on Vue and adds the application layer around it: routing from files, server-side rendering and static generation, data fetching, API routes and deployment.",[13,25,26],{},"The stack looks like this:",[28,29,35],"pre",{"className":30,"code":32,"language":33,"meta":34},[31],"language-text","┌───────────────────────────────────────────────┐\n│ Nuxt   routing · SSR\u002FSSG · data · server\u002FAPI  │\n│ ┌───────────────────────────────────────────┐ │\n│ │ Vue    components · reactivity · templates│ │\n│ └───────────────────────────────────────────┘ │\n│ Vite   dev server · hot reload · bundling     │\n└───────────────────────────────────────────────┘\n","text","",[36,37,32],"code",{"__ignoreMap":34},[13,39,40],{},"Vite sits underneath both. A plain Vue project is usually created with Vite, and Nuxt uses Vite as its default builder. So Nuxt vs Vite isn't a contest either. Vite builds and serves your code; Nuxt decides how the app is structured and rendered. Flip it to Vite vs Nuxt and nothing changes: one is a build tool, the other an app framework. (Nuxt can bundle with webpack or Rspack instead, but Vite is the default.)",[13,42,43],{},"You never pick Nuxt instead of Vue. You pick Vue alone, or Vue plus Nuxt.",[17,45,47],{"id":46},"what-vue-does-on-its-own","What Vue Does on Its Own",[13,49,50,51,56,57,60],{},"If you need a refresher on ",[52,53,55],"a",{"href":54},"\u002Fblog\u002Fwhat-is-vue-js","what Vue.js is",", our guide covers it in depth. The short version: Vue is a JavaScript framework for building user interfaces. You write components as single-file ",[36,58,59],{},".vue"," components with a template, a script and styles, and Vue keeps the DOM in sync with your data through its reactivity system.",[13,62,63],{},"Vue calls itself a progressive framework, and it means it. You can drop it into one part of an existing page, or build a full single-page app. Out of the box, the core package gives you:",[65,66,67,71,88,91],"ul",{},[68,69,70],"li",{},"Components, props, events and slots",[68,72,73,74,77,78,77,81,84,85],{},"Reactivity with ",[36,75,76],{},"ref",", ",[36,79,80],{},"reactive",[36,82,83],{},"computed"," and ",[36,86,87],{},"watch",[68,89,90],{},"The Composition API and the Options API",[68,92,93,94,77,97,84,100],{},"Transitions, ",[36,95,96],{},"\u003CKeepAlive>",[36,98,99],{},"\u003CTeleport>",[36,101,102],{},"\u003CSuspense>",[13,104,105,106,109],{},"Everything else is a separate choice. Routing comes from Vue Router, state management from Pinia, and the build setup from Vite. The official scaffolding tool, ",[36,107,108],{},"npm create vue@latest",", asks which of these you want and generates a Vite project with them wired in.",[13,111,112],{},"What you get is a client-side app. The browser downloads JavaScript, runs it, and only then renders the page. That works well for dashboards and tools behind a login. It's weaker for pages that need to be indexed or that must show content the moment they load.",[13,114,115,116,119],{},"Vue can render on the server too. The ",[36,117,118],{},"vue\u002Fserver-renderer"," package turns components into HTML strings. But you have to build the rest yourself: the Node.js server, the routing on both sides, data loading before render and hydration in the browser. The Vue docs call a complete implementation \"quite complex\" and recommend a Vue framework with built-in SSR support, such as Nuxt, instead.",[17,121,123],{"id":122},"what-nuxt-adds-on-top-of-vue","What Nuxt Adds on Top of Vue",[13,125,126,127,131],{},"Nuxt takes the pieces Vue leaves open and makes the decisions for you. Your components stay Vue components. What changes is everything around them. (For a full overview, see our explainer on ",[52,128,130],{"href":129},"\u002Fblog\u002Fwhat-is-nuxt","what Nuxt is",".)",[133,134,136],"h3",{"id":135},"file-based-routing-and-auto-imports","File-Based Routing and Auto-Imports",[13,138,139,140,142,143,146,147,150,151,154,155,158,159,162,163,166],{},"In a Vue app you write a router config by hand. In Nuxt, every ",[36,141,59],{}," file in ",[36,144,145],{},"app\u002Fpages\u002F"," is a route: ",[36,148,149],{},"pages\u002Fabout.vue"," becomes ",[36,152,153],{},"\u002Fabout",", and ",[36,156,157],{},"pages\u002Fproducts\u002F[id].vue"," matches any product URL. Nested folders become nested routes, and layouts wrap pages without extra router code. Route middleware, such as an auth check, goes in ",[36,160,161],{},"app\u002Fmiddleware\u002F"," and is attached to a page with ",[36,164,165],{},"definePageMeta",". Under the hood this is still Vue Router; Nuxt just writes the config for you.",[13,168,169,170,77,172,77,174,84,177,180],{},"Nuxt also auto-imports Vue APIs, your components and your composables. ",[36,171,76],{},[36,173,83],{},[36,175,176],{},"\u003CProductCard>",[36,178,179],{},"useCart()"," are available in any file without import lines, and Nuxt generates types for all of them.",[133,182,184],{"id":183},"server-side-rendering-and-static-generation","Server-Side Rendering and Static Generation",[13,186,187,188,191,192,196],{},"This is the big one. Nuxt renders pages on the server by default, sends full HTML, then hydrates it in the browser. You can also prerender the whole site at build time with ",[36,189,190],{},"nuxt generate",", turn SSR off for an SPA, or mix modes per route with route rules. If these terms are new, our post on ",[52,193,195],{"href":194},"\u002Fblog\u002Fvue-js-seo-rendering","SSR, SSG and CSR in Vue"," explains each one.",[13,198,199],{},"Route rules are where this gets practical. One config line can prerender the homepage, another can cache product pages for an hour, and a third can render the admin area in the browser only. In plain Vue, each of those would be a separate setup.",[133,201,203],{"id":202},"data-fetching-and-server-routes","Data Fetching and Server Routes",[13,205,206,84,209,212,213,216,217,220],{},[36,207,208],{},"useFetch",[36,210,211],{},"useAsyncData"," load data during server rendering and pass it to the browser with the page, so the request isn't repeated. Files in ",[36,214,215],{},"server\u002Fapi\u002F"," become API endpoints that run on Nitro, Nuxt's server engine. A small app can read from a database or call third-party services without a separate backend. Because pages and endpoints live in one project, ",[36,218,219],{},"useFetch('\u002Fapi\u002Fproducts')"," knows the response type from the server route.",[133,222,224],{"id":223},"modules-and-layers","Modules and Layers",[13,226,227,228,231,232,236],{},"Nuxt modules add whole features with one line in ",[36,229,230],{},"nuxt.config.ts",": images, content, i18n, SEO, UI libraries. ",[52,233,235],{"href":234},"\u002Fblog\u002Fnuxt-layers","Nuxt layers"," let one Nuxt project extend another, which teams use to share a design system or a base app across products. Plain Vue has plugins too, but nothing that hooks into routing, the server and the build at once.",[17,238,240],{"id":239},"how-vue-and-nuxt-work-together-in-one-project","How Vue and Nuxt Work Together in One Project",[13,242,243],{},"The easiest way to see the relationship is to take one component and use it in both. Here is a product card:",[28,245,249],{"className":246,"code":247,"language":248,"meta":34,"style":34},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- ProductCard.vue -->\n\u003Cscript setup lang=\"ts\">\ndefineProps\u003C{ name: string; price: number }>()\nconst added = ref(false)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Carticle>\n    \u003Ch3>{{ name }}\u003C\u002Fh3>\n    \u003Cp>{{ price }} €\u003C\u002Fp>\n    \u003Cbutton @click=\"added = true\">{{ added ? 'Added' : 'Add to cart' }}\u003C\u002Fbutton>\n  \u003C\u002Farticle>\n\u003C\u002Ftemplate>\n","vue",[36,250,251,260,293,331,355,365,372,382,393,413,431,462,472],{"__ignoreMap":34},[252,253,256],"span",{"class":254,"line":255},"line",1,[252,257,259],{"class":258},"sHwdD","\u003C!-- ProductCard.vue -->\n",[252,261,263,267,271,275,278,281,284,288,290],{"class":254,"line":262},2,[252,264,266],{"class":265},"sMK4o","\u003C",[252,268,270],{"class":269},"swJcz","script",[252,272,274],{"class":273},"spNyl"," setup",[252,276,277],{"class":273}," lang",[252,279,280],{"class":265},"=",[252,282,283],{"class":265},"\"",[252,285,287],{"class":286},"sfazB","ts",[252,289,283],{"class":265},[252,291,292],{"class":265},">\n",[252,294,296,300,303,306,309,313,316,319,321,324,327],{"class":254,"line":295},3,[252,297,299],{"class":298},"s2Zo4","defineProps",[252,301,302],{"class":265},"\u003C{",[252,304,305],{"class":269}," name",[252,307,308],{"class":265},":",[252,310,312],{"class":311},"sBMFI"," string",[252,314,315],{"class":265},";",[252,317,318],{"class":269}," price",[252,320,308],{"class":265},[252,322,323],{"class":311}," number",[252,325,326],{"class":265}," }>",[252,328,330],{"class":329},"sTEyZ","()\n",[252,332,334,337,340,342,345,348,352],{"class":254,"line":333},4,[252,335,336],{"class":273},"const",[252,338,339],{"class":329}," added ",[252,341,280],{"class":265},[252,343,344],{"class":298}," ref",[252,346,347],{"class":329},"(",[252,349,351],{"class":350},"sfNiH","false",[252,353,354],{"class":329},")\n",[252,356,358,361,363],{"class":254,"line":357},5,[252,359,360],{"class":265},"\u003C\u002F",[252,362,270],{"class":269},[252,364,292],{"class":265},[252,366,368],{"class":254,"line":367},6,[252,369,371],{"emptyLinePlaceholder":370},true,"\n",[252,373,375,377,380],{"class":254,"line":374},7,[252,376,266],{"class":265},[252,378,379],{"class":269},"template",[252,381,292],{"class":265},[252,383,385,388,391],{"class":254,"line":384},8,[252,386,387],{"class":265},"  \u003C",[252,389,390],{"class":269},"article",[252,392,292],{"class":265},[252,394,396,399,401,404,407,409,411],{"class":254,"line":395},9,[252,397,398],{"class":265},"    \u003C",[252,400,133],{"class":269},[252,402,403],{"class":265},">",[252,405,406],{"class":329},"{{ name }}",[252,408,360],{"class":265},[252,410,133],{"class":269},[252,412,292],{"class":265},[252,414,416,418,420,422,425,427,429],{"class":254,"line":415},10,[252,417,398],{"class":265},[252,419,13],{"class":269},[252,421,403],{"class":265},[252,423,424],{"class":329},"{{ price }} €",[252,426,360],{"class":265},[252,428,13],{"class":269},[252,430,292],{"class":265},[252,432,434,436,439,442,444,446,449,451,453,456,458,460],{"class":254,"line":433},11,[252,435,398],{"class":265},[252,437,438],{"class":269},"button",[252,440,441],{"class":273}," @click",[252,443,280],{"class":265},[252,445,283],{"class":265},[252,447,448],{"class":286},"added = true",[252,450,283],{"class":265},[252,452,403],{"class":265},[252,454,455],{"class":329},"{{ added ? 'Added' : 'Add to cart' }}",[252,457,360],{"class":265},[252,459,438],{"class":269},[252,461,292],{"class":265},[252,463,465,468,470],{"class":254,"line":464},12,[252,466,467],{"class":265},"  \u003C\u002F",[252,469,390],{"class":269},[252,471,292],{"class":265},[252,473,475,477,479],{"class":254,"line":474},13,[252,476,360],{"class":265},[252,478,379],{"class":269},[252,480,292],{"class":265},[13,482,483,484,487,488,491,492,494],{},"In a plain Vue project, the only change is an explicit import, ",[36,485,486],{},"import { ref } from 'vue'",", and the parent imports the component too. In Nuxt, the file goes into ",[36,489,490],{},"app\u002Fcomponents\u002F"," and works as written, because ",[36,493,76],{}," and the component are auto-imported. The template, the props, the reactivity and the click handler are identical.",[13,496,497,498,501],{},"The difference shows up in the page that uses it. In Vue, a view fetches products in ",[36,499,500],{},"onMounted",", and the cards appear after the browser has run the JavaScript. In Nuxt, the page does this:",[28,503,505],{"className":246,"code":504,"language":248,"meta":34,"style":34},"\u003Cscript setup lang=\"ts\">\nconst { data: products } = await useFetch('\u002Fapi\u002Fproducts')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CProductCard v-for=\"p in products\" :key=\"p.id\" :name=\"p.name\" :price=\"p.price\" \u002F>\n\u003C\u002Ftemplate>\n",[36,506,507,527,567,575,579,587,645],{"__ignoreMap":34},[252,508,509,511,513,515,517,519,521,523,525],{"class":254,"line":255},[252,510,266],{"class":265},[252,512,270],{"class":269},[252,514,274],{"class":273},[252,516,277],{"class":273},[252,518,280],{"class":265},[252,520,283],{"class":265},[252,522,287],{"class":286},[252,524,283],{"class":265},[252,526,292],{"class":265},[252,528,529,531,534,537,539,542,545,548,552,555,557,560,563,565],{"class":254,"line":262},[252,530,336],{"class":273},[252,532,533],{"class":265}," {",[252,535,536],{"class":269}," data",[252,538,308],{"class":265},[252,540,541],{"class":329}," products ",[252,543,544],{"class":265},"}",[252,546,547],{"class":265}," =",[252,549,551],{"class":550},"s7zQu"," await",[252,553,554],{"class":298}," useFetch",[252,556,347],{"class":329},[252,558,559],{"class":265},"'",[252,561,562],{"class":286},"\u002Fapi\u002Fproducts",[252,564,559],{"class":265},[252,566,354],{"class":329},[252,568,569,571,573],{"class":254,"line":295},[252,570,360],{"class":265},[252,572,270],{"class":269},[252,574,292],{"class":265},[252,576,577],{"class":254,"line":333},[252,578,371],{"emptyLinePlaceholder":370},[252,580,581,583,585],{"class":254,"line":357},[252,582,266],{"class":265},[252,584,379],{"class":269},[252,586,292],{"class":265},[252,588,589,591,594,597,599,601,604,606,609,611,613,616,618,621,623,625,628,630,633,635,637,640,642],{"class":254,"line":367},[252,590,387],{"class":265},[252,592,593],{"class":269},"ProductCard",[252,595,596],{"class":273}," v-for",[252,598,280],{"class":265},[252,600,283],{"class":265},[252,602,603],{"class":286},"p in products",[252,605,283],{"class":265},[252,607,608],{"class":273}," :key",[252,610,280],{"class":265},[252,612,283],{"class":265},[252,614,615],{"class":286},"p.id",[252,617,283],{"class":265},[252,619,620],{"class":273}," :name",[252,622,280],{"class":265},[252,624,283],{"class":265},[252,626,627],{"class":286},"p.name",[252,629,283],{"class":265},[252,631,632],{"class":273}," :price",[252,634,280],{"class":265},[252,636,283],{"class":265},[252,638,639],{"class":286},"p.price",[252,641,283],{"class":265},[252,643,644],{"class":265}," \u002F>\n",[252,646,647,649,651],{"class":254,"line":374},[252,648,360],{"class":265},[252,650,379],{"class":269},[252,652,292],{"class":265},[13,654,655],{},"The cards are rendered to HTML on the server, so they're in the page source before any JavaScript runs. After hydration, the button works exactly as it does in the Vue app.",[13,657,658,659,662],{},"The same page can set its title and description with ",[36,660,661],{},"useSeoMeta({ title: 'Products' })",", and Nuxt writes those tags into the server-rendered HTML. In the Vue version, you'd add a head library and still ship an empty page to crawlers that don't run JavaScript.",[13,664,665],{},"Vue owns the component. Nuxt owns when and where it renders, where its data comes from and which URL it lives at.",[17,667,669],{"id":668},"the-difference-between-vue-and-nuxt-in-practice","The Difference Between Vue and Nuxt in Practice",[671,672,673,688],"table",{},[674,675,676],"thead",{},[677,678,679,682,685],"tr",{},[680,681],"th",{},[680,683,684],{},"Vue alone (with Vite)",[680,686,687],{},"Vue with Nuxt",[689,690,691,703,716,727,745,760,777,788],"tbody",{},[677,692,693,697,700],{},[694,695,696],"td",{},"Rendering",[694,698,699],{},"Client-side by default",[694,701,702],{},"SSR by default; SSG, SPA or hybrid per route",[677,704,705,708,711],{},[694,706,707],{},"Routing",[694,709,710],{},"Vue Router, configured by hand",[694,712,713,714],{},"Generated from ",[36,715,145],{},[677,717,718,721,724],{},[694,719,720],{},"Imports",[694,722,723],{},"Explicit",[694,725,726],{},"Auto-imported and typed",[677,728,729,732,737],{},[694,730,731],{},"Data loading",[694,733,734,735],{},"Your choice, usually in ",[36,736,500],{},[694,738,739,741,742,744],{},[36,740,208],{}," \u002F ",[36,743,211],{},", server-aware",[677,746,747,750,753],{},[694,748,749],{},"Backend",[694,751,752],{},"Separate service",[694,754,755,756,759],{},"API routes in ",[36,757,758],{},"server\u002F",", running on Nitro",[677,761,762,765,768],{},[694,763,764],{},"SEO tags",[694,766,767],{},"Add a head library yourself",[694,769,770,84,773,776],{},[36,771,772],{},"useSeoMeta",[36,774,775],{},"useHead",", rendered on the server",[677,778,779,782,785],{},[694,780,781],{},"Hosting",[694,783,784],{},"Any static host",[694,786,787],{},"Static host, Node.js, serverless or edge",[677,789,790,793,796],{},[694,791,792],{},"Project structure",[694,794,795],{},"Up to you",[694,797,798],{},"Conventions",[13,800,801],{},"The main difference between Vue and Nuxt is how much of the app is decided for you. With Vue, you pick a router, a data pattern, a folder structure and a hosting model, and you own every one of those decisions. With Nuxt, those choices are made, documented and shared by every Nuxt project, so a developer joining your team already knows where things live.",[13,803,804,805,84,808,811],{},"That has costs. Server rendering means some code runs in Node.js, where ",[36,806,807],{},"window",[36,809,810],{},"localStorage"," don't exist, and a mismatch between server and browser HTML produces hydration warnings. Conventions also limit how you organize files. For a team that wants full control of a small client-side app, Vue alone is simply less to think about.",[13,813,814],{},"The gain is mostly at the edges of the app: the first page load, SEO, the API, deployment. Inside a component, the two are the same.",[13,816,817],{},"That's where a lot of Nuxt.js vs Vue.js scorecards go wrong. They rate the two side by side on speed, learning curve and ecosystem, as if you had to drop one. Every cell in the right-hand column of the table above still runs on Vue.",[17,819,821],{"id":820},"vue-vs-nuxt-when-to-add-nuxt-to-a-vue-project","Vue vs Nuxt: When to Add Nuxt to a Vue Project",[13,823,824],{},"The Vue vs Nuxt decision usually comes down to two questions. Does the app need to show content before JavaScript runs? And do you want the server, routing and data loading handled by convention? If both answers are no, Vue on its own is the simpler tool.",[133,826,828],{"id":827},"when-vue-on-its-own-is-enough","When Vue on Its Own Is Enough",[65,830,831,834,837,840,843],{},[68,832,833],{},"Internal tools and admin panels behind a login, where search engines never see the pages",[68,835,836],{},"Dashboards that load data after sign-in and live for hours in one tab",[68,838,839],{},"Widgets embedded into an existing site or a server-rendered backend like Laravel or Django",[68,841,842],{},"Apps that ship inside Electron, Capacitor or a browser extension",[68,844,845],{},"Prototypes where speed of setup beats long-term structure",[13,847,848],{},"In these cases, Nuxt's server, routing conventions and SSR concerns add work without paying it back. A Vite + Vue Router + Pinia setup is small, fast to build and easy to deploy to any static host.",[13,850,851,852,854],{},"Starting with Vue alone doesn't lock you out of Nuxt later. Keep components small, keep browser-only code in ",[36,853,500],{},", and avoid depending on a custom router setup. Those habits make a future move much cheaper.",[133,856,858],{"id":857},"when-to-add-nuxt","When to Add Nuxt",[65,860,861,869,872,875,878,881],{},[68,862,863,864,868],{},"Public pages that need to rank in search or show rich previews when shared. Server-rendered HTML is the dependable way to get there, and our guide to ",[52,865,867],{"href":866},"\u002Fblog\u002Fvue-and-seo","Vue and SEO"," explains why client-only Vue apps struggle.",[68,870,871],{},"Marketing sites, blogs and docs that should be prerendered to static HTML",[68,873,874],{},"E-commerce, where product pages must be indexed and fast, but the cart behaves like an app",[68,876,877],{},"SaaS products with a public site and a logged-in app in one codebase, using route rules to render each part differently",[68,879,880],{},"Apps that need a light API layer (auth callbacks, webhooks, proxies to other services) without running a separate backend",[68,882,883],{},"Teams that want a standard structure, so new developers can find their way around on day one",[13,885,886],{},"Here's a tell: if you find yourself adding a head manager, a prerender plugin and a small Node.js server to a Vue app, you're rebuilding Nuxt by hand.",[17,888,890],{"id":889},"moving-a-vue-app-to-nuxt","Moving a Vue App to Nuxt",[13,892,893],{},"Nuxt isn't a plugin you add to an existing Vue app. It's the outer framework, so the move is a migration: you create a Nuxt project and bring your code into it. Most of the code moves without changes.",[13,895,896],{},"Here's the usual order:",[898,899,900,906,920,935,946,964],"ol",{},[68,901,902,903,905],{},"Create a Nuxt project and copy your components into ",[36,904,490],{},". Single-file components work as they are.",[68,907,908,909,911,912,915,916,919],{},"Turn each route in your Vue Router config into a file in ",[36,910,145],{},", then delete the router setup. Replace ",[36,913,914],{},"\u003Crouter-link>"," with ",[36,917,918],{},"\u003CNuxtLink>",".",[68,921,922,923,926,927,930,931,934],{},"Move Pinia stores and add the ",[36,924,925],{},"@pinia\u002Fnuxt"," module. Turn ",[36,928,929],{},"app.use()"," calls from ",[36,932,933],{},"main.ts"," into Nuxt plugins.",[68,936,937,938,915,940,942,943,945],{},"Replace data loading in ",[36,939,500],{},[36,941,208],{}," or ",[36,944,211],{}," where the data should be in the server-rendered HTML.",[68,947,948,949,77,951,942,954,956,957,959,960,963],{},"Wrap browser-only code (anything touching ",[36,950,807],{},[36,952,953],{},"document",[36,955,810],{},") in ",[36,958,500],{}," or a ",[36,961,962],{},"\u003CClientOnly>"," component.",[68,965,966,967,919],{},"Move environment variables into ",[36,968,969],{},"runtimeConfig",[13,971,972,973,976],{},"A lower-risk path is to start with ",[36,974,975],{},"ssr: false",". The app then runs as an SPA inside Nuxt, and you can switch on server rendering route by route with route rules once the browser-only code is cleaned up.",[13,978,979,980,984],{},"The work depends on the size of the app and how much code assumes a browser. If you want an experienced team to plan or run it, our ",[52,981,983],{"href":982},"\u002Fservices\u002Fnuxt-migration","Nuxt migration services"," cover moves from plain Vue as well as older Nuxt versions.",[17,986,988],{"id":987},"conclusion","Conclusion",[13,990,991],{},"Nuxt vs Vue isn't a choice between two frameworks. Vue renders your components. Nuxt runs those same components and adds routing, server rendering, data fetching, API routes and deployment around them. Vite builds the code in both cases.",[13,993,994],{},"Choose Vue on its own when the app lives behind a login, runs inside another product, or is small enough that you want full control. Add Nuxt when pages need to be indexed, load fast on first visit, or share a codebase with a public site and an API. Moving later works. It's just cheaper when the code was written with that move in mind.",[13,996,997,998,1002],{},"At Epicmax, we have built client projects with Nuxt since 2017, and this site is a Nuxt 4 app. If you're deciding between plain Vue and Nuxt for a new product, or planning to move an existing app, our ",[52,999,1001],{"href":1000},"\u002Fservices\u002Fnuxt-development","Nuxt development services"," can help.",[17,1004,1006],{"id":1005},"faqs","FAQs",[133,1008,1010],{"id":1009},"is-nuxt-better-than-vue","Is Nuxt better than Vue?",[13,1012,1013],{},"Neither is better, because they do different jobs. Vue renders components, and Nuxt is a framework that uses Vue for rendering and adds routing, server rendering, data fetching and an API layer. Nuxt is the better choice when you need those things, and plain Vue is simpler when you don't.",[133,1015,1017],{"id":1016},"nuxtjs-vs-vuejs-is-nuxt-harder-to-learn","Nuxt.js vs Vue.js: is Nuxt harder to learn?",[13,1019,1020,1021,1023],{},"A little. Everything you learn in Vue carries over, and on top of it Nuxt adds its conventions: the pages directory, auto-imports, ",[36,1022,208],{}," and the difference between code that runs on the server and in the browser. The conventions are quick to pick up; server rendering bugs like hydration mismatches take longer to get used to.",[133,1025,1027],{"id":1026},"can-i-use-nuxt-without-learning-vue-first","Can I use Nuxt without learning Vue first?",[13,1029,1030],{},"You can start, but you will be learning Vue anyway. Every page, layout and component in Nuxt is a Vue single-file component, so templates, props, reactivity and the Composition API are the bulk of the work. Learn the Vue basics first and Nuxt will make sense much faster.",[133,1032,1034],{"id":1033},"nuxt-vs-vite-do-i-need-both","Nuxt vs Vite: do I need both?",[13,1036,1037,1038,1041,1042,1044,1045,1049],{},"If you use Nuxt, you already have Vite. Vite is the default builder in Nuxt, which configures it for you, so you don't install or set it up separately. You only touch Vite directly through the ",[36,1039,1040],{},"vite"," key in ",[36,1043,230],{}," when you need a plugin or a custom option. Our ",[52,1046,1048],{"href":1047},"\u002Fblog\u002Fvite-vs-webpack","Vite vs Webpack"," post explains why Vite became the default.",[133,1051,1053],{"id":1052},"vite-vs-nuxt-which-should-i-start-a-new-vue-project-with","Vite vs Nuxt: which should I start a new Vue project with?",[13,1055,1056,1057,1059,1060,1063,1064,1066],{},"Start with Vite (",[36,1058,108],{},") for a single-page app behind a login, a widget or an internal tool. Start with Nuxt (",[36,1061,1062],{},"npm create nuxt@latest",") for anything public that needs SEO, fast first loads or its own API routes. If you are not sure yet, Nuxt with ",[36,1065,975],{}," behaves like an SPA and leaves the door open.",[133,1068,1070],{"id":1069},"is-nuxt-the-vue-version-of-nextjs","Is Nuxt the Vue version of Next.js?",[13,1072,1073,1074,1078],{},"Roughly, yes. The first Nuxt README called it a minimalistic framework for server-rendered Vue applications inspired by Next.js, and both now cover routing, server rendering and full-stack features. The difference is the component layer: Next.js uses React, Nuxt uses Vue. Our ",[52,1075,1077],{"href":1076},"\u002Fblog\u002Fvue-js-vs-next-js","Nuxt vs Next.js comparison"," goes into the details.",[133,1080,1082],{"id":1081},"does-nuxt-make-a-vue-app-faster","Does Nuxt make a Vue app faster?",[13,1084,1085,1086,1090],{},"It usually makes the first load faster, because server rendering or prerendering sends finished HTML instead of an empty page that waits for JavaScript. Once the page is interactive it runs the same Vue code, so runtime speed depends on your components. Hydration has its own cost, so large pages still need the usual ",[52,1087,1089],{"href":1088},"\u002Fblog\u002Fvue-js-performance","Vue.js performance optimization"," work.",[133,1092,1094],{"id":1093},"can-i-add-nuxt-to-an-existing-vue-project","Can I add Nuxt to an existing Vue project?",[13,1096,1097],{},"Not as a plugin you drop in. Nuxt is the app's outer framework, so you create a Nuxt project and move your components, routes, stores and plugins into it. Components usually move unchanged; the router setup, entry file and browser-only code need the most changes.",[1099,1100],"blog-button",{"label":1101,"to":1102},"Talk to a Nuxt expert","https:\u002F\u002Fcalendar.app.google\u002FXwRzASZitZRSVLxq6",[1104,1105,1106],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":34,"searchDepth":295,"depth":295,"links":1108},[1109,1110,1111,1117,1118,1119,1123,1124,1125],{"id":19,"depth":262,"text":20},{"id":46,"depth":262,"text":47},{"id":122,"depth":262,"text":123,"children":1112},[1113,1114,1115,1116],{"id":135,"depth":295,"text":136},{"id":183,"depth":295,"text":184},{"id":202,"depth":295,"text":203},{"id":223,"depth":295,"text":224},{"id":239,"depth":262,"text":240},{"id":668,"depth":262,"text":669},{"id":820,"depth":262,"text":821,"children":1120},[1121,1122],{"id":827,"depth":295,"text":828},{"id":857,"depth":295,"text":858},{"id":889,"depth":262,"text":890},{"id":987,"depth":262,"text":988},{"id":1005,"depth":262,"text":1006,"children":1126},[1127,1128,1129,1130,1131,1132,1133,1134],{"id":1009,"depth":295,"text":1010},{"id":1016,"depth":295,"text":1017},{"id":1026,"depth":295,"text":1027},{"id":1033,"depth":295,"text":1034},{"id":1052,"depth":295,"text":1053},{"id":1069,"depth":295,"text":1070},{"id":1081,"depth":295,"text":1082},{"id":1093,"depth":295,"text":1094},"2026-11-04","Vue vs Nuxt isn't a choice between rivals. Learn the difference between Vue and Nuxt, how Nuxt vs Vite fits in, and when a Vue app needs Nuxt.","md",[1139,1140,1142,1143,1145,1147,1149,1151],{"question":1010,"answer":1013},{"question":1017,"answer":1141},"A little. Everything you learn in Vue carries over, and on top of it Nuxt adds its conventions: the pages directory, auto-imports, useFetch and the difference between code that runs on the server and in the browser. The conventions are quick to pick up; server rendering bugs like hydration mismatches take longer to get used to.",{"question":1027,"answer":1030},{"question":1034,"answer":1144},"If you use Nuxt, you already have Vite. Vite is the default builder in Nuxt, which configures it for you, so you don't install or set it up separately. You only touch Vite directly through the vite key in nuxt.config.ts when you need a plugin or a custom option.",{"question":1053,"answer":1146},"Start with Vite (npm create vue@latest) for a single-page app behind a login, a widget or an internal tool. Start with Nuxt (npm create nuxt@latest) for anything public that needs SEO, fast first loads or its own API routes. If you are not sure yet, Nuxt with ssr: false behaves like an SPA and leaves the door open.",{"question":1070,"answer":1148},"Roughly, yes. The first Nuxt README called it a minimalistic framework for server-rendered Vue applications inspired by Next.js, and both now cover routing, server rendering and full-stack features. The difference is the component layer: Next.js uses React, Nuxt uses Vue.",{"question":1082,"answer":1150},"It usually makes the first load faster, because server rendering or prerendering sends finished HTML instead of an empty page that waits for JavaScript. Once the page is interactive it runs the same Vue code, so runtime speed depends on your components. Hydration has its own cost, so large pages still need the usual optimization work.",{"question":1094,"answer":1097},false,"\u002Fimages\u002Fblog\u002Fnuxt-vs-vue\u002Fcard.png",{},"\u002Fblog\u002Fnuxt-vs-vue","11 min read",{"title":5,"description":1136},null,"blog\u002Fnuxt-vs-vue",[1161,1162],"Nuxt","Vue.js","7BDGPbRjy16nPJVK2Opd1ccSxO2Z2VWLXzUCCyx3ONg",1793793094643]