Vue has quietly become one of the most widely used component frameworks on the web, and Nuxt is a [full-stack Vue framework](https://vercel.com/i/full-stack-framework) that turns that foundation into production applications. It packages server rendering, file-based routing, data fetching, and an HTTP server into one project, so Vue teams spend their time on the product instead of wiring infrastructure together.

This guide covers how Nuxt works under the hood, the rendering modes you can mix inside a single project, what changed in Nuxt 4, and how to [deploy on Vercel](https://vercel.com/docs/frameworks/full-stack/nuxt).

## [Copy link to heading](#what-is-nuxt)What is Nuxt?

Nuxt is a [full-stack Vue framework](https://vercel.com/i/full-stack-framework) that adds server-side rendering, file-based routing, a server engine, and auto-imports on top of Vue 3. It pairs Vue for components with Vite for the build pipeline and Nitro for the server, producing a single project that renders, routes, and responds to API calls.

The difference from plain Vue is where rendering happens. A standalone Vue single-page application ships an empty HTML shell and waits for JavaScript to load before content appears. Nuxt defaults to universal rendering, sending fully rendered HTML that the browser hydrates into an interactive app. On the React side, the closest architectural equivalent is [Next.js](https://vercel.com/i/astro-vs-next-js), which pairs file-based routing and SSR with React instead of Vue.

## [Copy link to heading](#how-nuxt-works)How Nuxt works

Nuxt layers three technologies into one build: Vue for components, Vite for the build pipeline, and Nitro for the server. Each layer handles a different problem, and the conventions connecting them make Nuxt feel like one framework rather than a toolkit.

### [Copy link to heading](#built-on-vue,-vite,-and-nitro)Built on Vue, Vite, and Nitro

Vue 3 handles component rendering and reactivity. The Vue compiler separates static and dynamic markup at build time, so static fragments are generated once, cached, and reused on every render. During SSR, Vue disables its reactivity system, since there is nothing interactive to track on the server.

Vite is the dev server and bundler. It pre-bundles dependencies, serves source over native ES modules, and updates only the changed module on Hot Module Replacement. The [Nitro engine](https://nitro.build/) is the HTTP server and build toolkit, built on `h3` for runtime portability. It compiles to multiple targets, including [Vercel Functions](https://vercel.com/docs/functions), Node, and static hosting, with no changes to application code.

### [Copy link to heading](#file-based-routing-and-auto-imports)File-based routing and auto-imports

Every `.vue` file inside `app/pages/` maps to a URL. `pages/index.vue` renders at `/`, `pages/about.vue` at `/about`, and `pages/users/[id].vue` creates a dynamic route at `/users/:id`. Server routes follow the same filesystem convention, and files in `server/api/` map to `/api/*` endpoints, with the HTTP method encoded in the filename. For example, `server/api/users.get.ts` handles `GET /api/users`, `server/api/users.post.ts` handles `POST /api/users`, and a method-less `server/api/users.ts` responds to any HTTP method.

Auto-imports pull Vue APIs like `ref()` and `computed()`, every component under `components/`, and every composable under `composables/` into scope without explicit `import` statements. The engine behind this is `unimport`, and Nuxt generates [TypeScript](https://vercel.com/i/javascript-vs-typescript) declarations for each auto-imported symbol so IDEs still resolve types correctly.

### [Copy link to heading](#the-ssr-request-flow)The SSR request flow

Nitro receives an incoming request and matches it against a compile-time routing table. Nuxt then runs data-fetching composables on the server. Inside SSR, `$fetch('/api/...')` calls short-circuit to the matching handler directly, skipping an extra HTTP round-trip, while the same code path makes a real network request when it runs in the browser.

Vue renders the component tree to an HTML string, and Nitro streams that HTML back to the browser along with the fetched data in the payload. The browser downloads the JavaScript bundle and hydrates the existing DOM by attaching event listeners, which avoids a full re-render on the client.

## [Copy link to heading](#nuxt-rendering-modes)Nuxt rendering modes

Nuxt supports four rendering strategies and lets you mix them at the route level through `routeRules`. The tradeoff between modes comes down to when HTML is generated and how much work happens at request time versus build time.

### [Copy link to heading](#server-side-rendering)Server-side rendering

Universal rendering is the default. For each request, Nitro renders the page on the server, returns HTML, and the browser hydrates it into a full Vue app. SSR keeps the first paint [content-rich for SEO](https://vercel.com/i/how-ai-is-changing-seo) and slower devices, at the cost of a running function per request.

### [Copy link to heading](#static-site-generation)Static site generation

SSG pre-renders pages at build time into static HTML files. The output serves directly from a [global CDN](https://vercel.com/docs/cdn) with no server at runtime. Content changes require a rebuild, so SSG fits pages where data is stable between deployments, such as marketing content and versioned documentation.

### [Copy link to heading](#hybrid-rendering-with-route-rules)Hybrid rendering with route rules

`routeRules` in `nuxt.config.ts` assigns a rendering and caching strategy to each route pattern. A blog path can be pre-rendered, a pricing page can be cached and revalidated in the background, and a dashboard route can render on demand. Most production Nuxt apps end up here, since different routes have different freshness and interactivity needs.

## [Copy link to heading](#key-features-of-nuxt)Key features of Nuxt

Nuxt's feature set includes primitives on both the Vue frontend and the Nitro backend. That coverage is what makes it a full-stack framework rather than only a rendering layer, and a few primitives carry most of the day-to-day work.

### [Copy link to heading](#nitro-server-engine-and-server-routes)Nitro server engine and server routes

Nitro is an open-source TypeScript server from the unified JavaScript ecosystem, built on the `h3` HTTP framework for portability across runtimes. Server routes in `server/api/` become HTTP endpoints, `server/routes/` handles non-API routes, and `server/middleware/` runs before any handler. Nitro also provides storage, caching, and scheduled-task APIs that behave the same across deployment targets.

### [Copy link to heading](#data-fetching-with-usefetch-and-useasyncdata)Data fetching with useFetch and useAsyncData

`useFetch` and `useAsyncData` are the two primitives for fetching data inside a page or component. Data fetched during SSR is forwarded to the browser in the rendered payload, so hydration does not trigger a second network request for the same data.

`useFetch` wraps `useAsyncData` around a `$fetch` call with a sensible default key. `useAsyncData` gives you explicit control over the key, which Nuxt uses for deduplication, sharing data across components, and cache invalidation.

### [Copy link to heading](#modules,-layers,-and-the-ecosystem)Modules, layers, and the ecosystem

The Nuxt module registry covers most integration work you'd otherwise write by hand. `@nuxt/content` adds a [headless CMS](https://vercel.com/i/headless-cms), `@nuxt/image` handles responsive [image optimization](https://vercel.com/docs/image-optimization/quickstart), and `@nuxt/ui` ships a component library powered by Reka UI and Tailwind CSS. Layers let one Nuxt project extend another's pages, composables, and server routes, which is useful for sharing setup across multiple apps in a monorepo.

## [Copy link to heading](#what's-new-in-nuxt-4)What's new in Nuxt 4?

The [Nuxt 4 release](https://nuxt.com/blog/v4) reorganizes project structure, data fetching, and the TypeScript experience. The overall direction is a clearer separation between client code, server code, and code shared between them.

Nuxt 4 introduces a handful of changes that affect how projects are structured and how data moves through them:

- **New** **`app/`** **directory:** Client-side code, including `pages/`, `components/`, `composables/`, `layouts/`, `middleware/`, and `plugins/`, moves inside `app/`, while `server/`, `shared/`, `public/`, and `nuxt.config.ts` stay at the project root.

- **`shared/`** **directory for cross-context code:** Files under `shared/utils/` and `shared/types/` auto-import into both the Vue app and the Nitro server, which replaces the previous pattern of reaching across the client/server boundary with relative imports.

- **Shared data by key:** Multiple components calling `useAsyncData` or `useFetch` with the same key share the same reactive `data`, `error`, `status`, and `pending` refs, so duplicate requests across the component tree collapse into one.

- **Shallow reactivity by default:** The `data` returned from `useAsyncData` and `useFetch` uses `shallowRef`, with deep reactivity available by passing `deep: true` per call or as a global setting in `nuxt.config.ts`.

Each of these changes makes a previously hidden runtime explicitly default in code.

## [Copy link to heading](#what-you-can-build-with-nuxt)What you can build with Nuxt

Nuxt's hybrid rendering and full-stack primitives cover a range of project types, from read-heavy sites to dashboards with authenticated APIs. A few categories come up most often.

Common Nuxt project types include:

- **Content sites and blogs:** SSG pairs with `@nuxt/content` to author posts in markdown and build them to static HTML, so reads serve from a CDN without a running function.

- **Ecommerce storefronts:** Hybrid rendering pre-renders product listings for speed and SEO while cart and checkout flows run dynamically, often backed by a payments provider like

    [Stripe on Vercel](https://vercel.com/marketplace/stripe).

- **SaaS dashboards:** `routeRules` lets a single project serve public marketing pages via SSG and authenticated dashboard views via client-side rendering behind the same domain.

- **Marketing sites and landing pages:** Pages known at build time ship as static HTML, and Nuxt modules add the extras these sites usually need, including image optimization and structured SEO metadata.

Each category can evolve into the others over time, since a single Nuxt project can serve all four rendering patterns as requirements change.

## [Copy link to heading](#getting-started-with-nuxt)Getting started with Nuxt

Creating a Nuxt project takes a single command, and the starter application includes routing, auto-imports, and a dev server out of the box. The main ramp-up is understanding how Nuxt 4 separates app code, server code, and shared code.

### [Copy link to heading](#installing-nuxt-and-scaffolding-a-project)Installing Nuxt and scaffolding a project

Node.js 20 or newer is required. The following commands scaffold a Nuxt 4 project and start the dev server on `http://localhost:3000`:

```
npm create nuxt@latest my-app
cd my-app
npm run dev -- -o
```

The scaffold includes a working home page, TypeScript config, and the default `app/` and `server/` directories.

### [Copy link to heading](#understanding-the-project-structure)Understanding the project structure

A Nuxt 4 project puts client code in `app/`, server code in `server/`, and cross-context code in `shared/`. Pages, components, composables, layouts, middleware, and plugins live under `app/`. API routes, server middleware, and Nitro plugins go in `server/`, while utilities and types that both sides import sit in `shared/utils/` and `shared/types/`.

A `<NuxtPage />` component in `app/app.vue` turns on routing, and a new file at `app/pages/index.vue` becomes the home route. A `useFetch` call inside that page fetches data on the server during SSR and forwards the result to the browser, so hydration doesn't issue a duplicate request.

## [Copy link to heading](#how-to-deploy-nuxt-on-vercel)How to deploy Nuxt on Vercel

Vercel auto-detects Nuxt projects during import and configures the build without a `vercel.json`. The same project can deploy its Nitro server as a Vercel Function and its static assets to the global CDN, which is what makes Nuxt's hybrid rendering practical in production.

A Vercel deployment for a Nuxt project includes:

- **Zero-config build detection**: Vercel runs `nuxt build` and deploys `/server/api`, `/server/routes`, and `/server/middleware` as a single Vercel Function.

- **Preview deployments per pull request**: Every PR gets a unique preview URL so teams can review rendered output before merging to production.

- [**Fluid compute**](https://vercel.com/docs/fluid-compute) **for SSR functions**: Nitro runs inside Fluid compute with pre-warmed instances and in-function concurrency, and bills for Active CPU only during execution rather than idle I/O wait.

- [**Incremental Static Regeneration**](https://vercel.com/docs/isr) **through route rules**: Setting `isr: 60` on a route in `routeRules` serves the cached HTML and refreshes it in the background every 60 seconds, with generated pages cached and persisted to durable storage.

- **Zero-config image optimization:** `@nuxt/image` integrates with Vercel's image optimization without additional setup, so responsive variants generate on the fly.

For routes that need regional placement, Nitro exposes Vercel-specific overrides through `vercel.functionRules` in `nuxt.config.ts`, which assigns one or more regions to a specific route pattern. That is useful when a route reads from a database in a particular region, and you want the function to run near it.

## [Copy link to heading](#ship-nuxt-apps-on-vercel)Ship Nuxt apps on Vercel

Nuxt gives Vue teams one framework where rendering strategy, server logic, and frontend code sit in the same project. Hybrid rendering lets each route pick its own mode, so a product that starts as a static marketing site can add dashboards and APIs without switching frameworks. Conventions around files, auto-imports, and typed composables reduce the infrastructure code you have to maintain along the way.

Vercel fits that model through framework detection, preview deployments, Fluid compute, ISR, and built-in image optimization. A new project can start from one of the [Nuxt templates](https://vercel.com/templates/nuxt) to go from `git push` to a deployed URL in minutes, and [Speed Insights](https://vercel.com/docs/speed-insights) tracks Core Web Vitals from real visitors once traffic is live.

## [Copy link to heading](#frequently-asked-questions-about-nuxt)Frequently asked questions about Nuxt

### [Copy link to heading](#is-nuxt-the-same-as-vue)Is Nuxt the same as Vue?

No. Vue is a UI library for building components with declarative rendering and reactivity. Nuxt is a full-stack framework built on Vue that adds file-based routing, server-side rendering, a Nitro-powered server, and auto-imports. A Nuxt project contains Vue inside it; a Vue project does not contain Nuxt.

### [Copy link to heading](#is-nuxt-better-than-next.js)Is Nuxt better than Next.js?

Neither framework is universally better. Nuxt is built on Vue, and [Next.js](https://vercel.com/i/astro-vs-next-js) is built on React, so the choice usually starts with which component library your team already knows. Both ship with file-based routing, server-side rendering, and hybrid static/dynamic output, and both [deploy on Vercel](https://vercel.com/docs/frameworks/full-stack/nuxt) without extra configuration.

### [Copy link to heading](#is-nuxt-frontend-or-backend)Is Nuxt frontend or backend?

Both. Nuxt is a full-stack framework with a Vue-based frontend layer and a Nitro-powered server layer in a single codebase. The `server/` directory contains API routes and middleware, and those handlers deploy as [Vercel Functions](https://vercel.com/docs/functions) in production.

### [Copy link to heading](#do-you-need-to-know-vue-to-learn-nuxt)Do you need to know Vue to learn Nuxt?

Not to start, but it helps. You can scaffold a Nuxt project and follow the getting-started guide without Vue experience, since Nuxt handles most of the boilerplate. Vue concepts like single-file components, the Composition API, and `vue-router` apply directly once you move past the starter, so reading the Vue docs alongside Nuxt's is worth the time.