Nuxt occupies the same spot for Vue that Next.js occupies for React — the application-level framework that turns a component library into something you can actually build and deploy a full product on top of.
Nuxt.js is a full-stack application framework built on Vue, providing file-based routing, multiple rendering modes (SSR, static site generation, client-side rendering, and a hybrid mix), auto-imports, and a module ecosystem covering common application needs (state management, SEO, images). It's the standard choice for building a production Vue application beyond a single embedded component.
Why Nuxt.js Matters (and When to Skip It)
Building routing, SSR, and data-fetching infrastructure yourself on top of plain Vue means reimplementing what most real applications need from scratch. Nuxt provides this as an integrated framework with sensible defaults, while still allowing per-route control over rendering strategy — a page can be statically generated, server-rendered, or client-rendered based on what fits its actual content.
Skip Nuxt for a single embedded Vue component within a non-Vue host application, or where you specifically need the flexibility of assembling your own router/build setup for unusual requirements a framework's conventions don't accommodate well.
Getting Started with Nuxt.js
npx nuxi@latest init my-app
cd my-app
npm install
npm run dev
File-based routing with data fetching:
pages/
index.vue
products/
[id].vue
<!-- pages/products/[id].vue -->
<script setup>
const route = useRoute();
const { data: product } = await useFetch(`/api/products/${route.params.id}`);
</script>
<template>
<h1>{{ product.name }}</h1>
</template>
A server API route colocated in the same project:
// server/api/products/[id].ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, "id");
return await db.products.findById(id);
});
Core Nuxt.js Concepts Every Developer Should Know
useFetch and useAsyncData handle data fetching with automatic SSR support, deduplicating requests between server and client hydration and integrating with Nuxt's rendering pipeline — using a plain fetch call directly in a component bypasses this integration and can cause double-fetching or hydration mismatches.
Rendering mode is configurable per route, not locked to a single strategy for the whole application — a marketing page can be statically generated while a dashboard is server-rendered, letting you match rendering strategy to each page's actual requirements.
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
"/": { prerender: true },
"/dashboard/**": { ssr: true },
},
});
Auto-imports reduce boilerplate significantly — composables, components, and Vue APIs are available without explicit import statements throughout the pages, components, and composables directories, a Nuxt-specific convenience that keeps files less cluttered.
Nitro (Nuxt's server engine) provides server API routes and deployment flexibility, letting the same codebase deploy to Node.js servers, serverless functions, or edge runtimes across various platforms with minimal per-platform configuration.
Common Nuxt.js Mistakes and How to Fix Them
Mistake 1: using plain fetch instead of useFetch/useAsyncData for data needed during SSR, causing hydration mismatches or duplicate fetching between server and client. Fix: use Nuxt's data fetching composables for anything that needs to work correctly with SSR.
Mistake 2: applying the same rendering mode to every route without considering what actually fits each page. A highly dynamic dashboard doesn't need static generation; a rarely-changing marketing page doesn't need full SSR on every request. Fix: configure route rules deliberately per page type.
Mistake 3: not leveraging server API routes for backend logic that belongs alongside the frontend, standing up a separate backend service unnecessarily for logic that could live in Nuxt's own server/api directory. Fix: use Nitro's server routes for backend logic that doesn't need to be a separate service.
When Should You Use Nuxt.js Instead of Plain Vue with Vite?
Use Nuxt.js for essentially any real application needing routing, SSR, or SEO — its conventions and integrated tooling save substantial setup effort compared to assembling equivalent infrastructure manually. Use plain Vue with Vite for embedded components, isolated widgets, or cases where you specifically need a lighter-weight setup without a full application framework's conventions.
Nuxt.js in Production
Configure route rules deliberately based on each page's actual rendering needs rather than applying one strategy universally — this is one of Nuxt's most valuable capabilities and worth actively using, not leaving at defaults. Also use server API routes for backend logic that naturally belongs alongside the frontend, reducing the need for a fully separate backend service for straightforward cases.
If you're starting a new Vue-based application, Nuxt is close to the default correct choice over assembling routing and SSR manually — the main reason to skip it is a genuinely unusual architectural requirement its conventions don't fit.