
File-Based Routing
Automatic routes based on your file structure
Server-Side Rendering
Built-in SSR for better SEO and performance
Auto Imports
Components and composables are auto-imported
Create a new Nuxt project with a single command:
npx nuxi@latest init my-app
cd my-app
npm install
npm run dev
Your app will be running at http://localhost:3000.
Nuxt uses a convention-based directory structure:
my-app/
├── app/
│ ├── components/ # Auto-imported Vue components
│ ├── composables/ # Auto-imported composable functions
│ ├── layouts/ # Layout templates
│ ├── pages/ # File-based routing
│ └── app.vue # Main app component
├── public/ # Static assets
├── server/ # Server routes and middleware
└── nuxt.config.ts # Nuxt configuration
Create files in the pages/ directory and they automatically become routes:
<!-- pages/index.vue → / -->
<template>
<div>
<h1>Home Page</h1>
</div>
</template>
<!-- pages/about.vue → /about -->
<template>
<div>
<h1>About Page</h1>
</div>
</template>
Use square brackets for dynamic parameters:
<!-- pages/posts/[id].vue → /posts/1, /posts/2, etc. -->
<script setup>
const route = useRoute()
const postId = route.params.id
</script>
<template>
<div>
<h1>Post {{ postId }}</h1>
</div>
</template>
Create reusable page layouts in the layouts/ directory:
<!-- layouts/default.vue -->
<template>
<div>
<header>
<nav>My App</nav>
</header>
<main>
<slot />
</main>
<footer>© 2025</footer>
</div>
</template>
Use a specific layout in a page:
<!-- pages/dashboard.vue -->
<script setup>
definePageMeta({
layout: "admin",
})
</script>
<template>
<div>Dashboard content</div>
</template>
Nuxt provides powerful composables for fetching data:
The simplest way to fetch data:
<script setup>
const { data: posts, status } = await useFetch("/api/posts")
</script>
<template>
<div v-if="status === 'pending'">Loading...</div>
<div v-else>
<article v-for="post in posts" :key="post.id">
<h2>{{ post.title }}</h2>
</article>
</div>
</template>
For more control over data fetching:
<script setup>
const { data: user } = await useAsyncData("user", () => {
return $fetch(`/api/users/${userId}`)
})
</script>
Create reusable logic in the composables/ directory:
// composables/useCounter.ts
export function useCounter(initial = 0) {
const count = ref(initial)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return { count, increment, decrement }
}
Use it in any component (auto-imported):
<script setup>
const { count, increment, decrement } = useCounter(10)
</script>
<template>
<button @click="decrement">-</button>
<span>{{ count }}</span>
<button @click="increment">+</button>
</template>
Nuxt makes SEO easy with the useSeoMeta composable:
<script setup>
useSeoMeta({
title: "My Amazing Page",
description: "This is a description of my page",
ogTitle: "My Amazing Page",
ogDescription: "This is a description for social sharing",
ogImage: "/og-image.png",
twitterCard: "summary_large_image",
})
</script>
Or use the useHead composable for full control:
<script setup>
useHead({
title: "My Page",
meta: [{ name: "description", content: "Page description" }],
link: [{ rel: "canonical", href: "https://example.com/page" }],
})
</script>
Add route middleware for authentication, redirects, and more:
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = false // Your auth logic
if (!isAuthenticated && to.path !== "/login") {
return navigateTo("/login")
}
})
Apply middleware to a page:
<script setup>
definePageMeta({
middleware: "auth",
})
</script>
Create API endpoints in the server/ directory:
// server/api/hello.ts
export default defineEventHandler((event) => {
return {
message: "Hello from the server!",
}
})
Access it at /api/hello.
Nuxt supports multiple deployment targets:
Vercel
Zero-config deployment with edge functions
Netlify
Automatic builds and serverless functions
Cloudflare
Global edge network with Workers
Build your app for production:
npm run build
Or generate a static site:
npm run generate