Nuxt Introduction
What Nuxt adds over plain Vue, installing it, and the Nuxt 3 project structure.
What Nuxt adds on top of Vue
Vue (its own track) is a UI library — it renders components, but leaves routing, data fetching strategy, and build configuration up to you. Nuxt is a full framework built on Vue that adds:
| Concern | Plain Vue (e.g. via Vite) | Nuxt 3 |
|---|---|---|
| Routing | Add Vue Router yourself, configure routes manually | File-based, generated automatically from pages/ |
| Rendering | Client-side only by default | Server-rendered, statically generated, or SPA — chosen per project or per route |
| Imports | Import components/composables explicitly everywhere | Auto-imported — components, composables, and Vue APIs are available with no import statement |
| Backend endpoints | A separate server needed | Server routes built in, under server/api/ |
| Build config | Configure Vite/webpack yourself | Zero-config, sensible defaults, extendable via nuxt.config.ts |
Installing Nuxt
Bash
npx nuxi@latest init my-app
cd my-app
npm install
npm run dev
The dev server runs at http://localhost:3000 by default, with hot module reload.
The Nuxt 3 project structure
Plaintext
my-app/
├── app.vue # the root component
├── nuxt.config.ts # project configuration
├── pages/ # file-based routes (requires <NuxtPage /> in app.vue)
│ └── index.vue
├── components/ # Vue components, auto-imported anywhere
├── composables/ # reusable reactive logic, auto-imported
├── layouts/ # shared page shells (default.vue, etc.)
├── server/
│ └── api/ # server-only API routes
└── public/ # static assets served as-is
app.vue is the single entry component every request renders — for a routed app it's usually just:
HTML
<template>
<NuxtPage />
</template>
<NuxtPage /> is where Nuxt renders whichever pages/ file matches the current URL — omit it, and the pages you create in pages/ are never actually shown.
Common mistakes
- Creating files under
pages/but forgetting<NuxtPage />inapp.vue— routing silently does nothing without it. - Manually
import-ing a component fromcomponents/— Nuxt auto-imports it by filename already, and the extra import is redundant (though harmless). - Expecting
server/api/code to run in the browser — it's server-only, which is exactly where secrets and privileged logic (like a database call) belong.