Nuxt 3 is a powerful meta-framework built on Vue 3 that provides server-side rendering, file-based routing, and many other features out of the box.
Why Nuxt 3?
Nuxt 3 offers several advantages over plain Vue:
- Server-Side Rendering (SSR) for better SEO and performance
- File-based routing - no need to configure routes manually
- Auto-imports - use components and composables without imports
- API routes - build full-stack applications
- Nitro engine - fast and lightweight server
Getting Started
bash
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run devDirectory Structure
my-nuxt-app/
├── .nuxt/ # Nuxt build files
├── assets/ # CSS, images, fonts
├── components/ # Vue components
├── composables/ # Vue composables
├── layouts/ # Layout components
├── middleware/ # Route middleware
├── pages/ # File-based routing
├── plugins/ # Vue plugins
├── public/ # Static files
├── server/ # Server API routes
└── nuxt.config.ts # Nuxt configurationFile-Based Routing
Create pages in the pages/ directory:
vue
<!-- pages/index.vue -->
<template>
<div>
<h1>Home Page</h1>
</div>
</template>
<!-- pages/about.vue -->
<template>
<div>
<h1>About Us</h1>
</div>
</template>
<!-- pages/blog/[slug].vue -->
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
</div>
</template>
<script setup>
const { slug } = useRoute().params
const { data: post } = await useFetch(`/api/blog/${slug}`)
</script>Auto-Imports
Nuxt automatically imports:
- Vue components
- Composables from
composables/ - Utility functions from
utils/ useFetch,useAsyncData,useRoute,useRouter, etc.
vue
<template>
<div>
<!-- Component auto-imported from components/Header.vue -->
<Header />
<!-- Composable auto-imported from composables/useCounter.js -->
<button @click="increment">{{ count }}</button>
</div>
</template>
<script setup>
const { count, increment } = useCounter()
</script>Data Fetching
useFetch()
vue
<script setup>
const { data: users, pending, error } = await useFetch('/api/users')
// With options
const { data: post } = await useFetch(`/api/posts/${id}`, {
key: `post-${id}`,
transform: (data) => data.post,
watch: [id]
})
</script>useAsyncData()
vue
<script setup>
const { data, pending } = await useAsyncData('users', () =>
$fetch('/api/users')
)
</script>Server API Routes
Create API endpoints in server/api/:
javascript
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: 'Hello from Nuxt!' }
})
// server/api/users/[id].ts
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id')
return { user: { id, name: 'John' } }
})
// server/api/post.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
// Process POST request
return { success: true }
})Composables
javascript
// composables/useUsers.js
export function useUsers() {
const { data: users, pending, error } = useFetch('/api/users')
const getUserById = (id) => {
return users.value.find(user => user.id === id)
}
return {
users,
pending,
error,
getUserById
}
}Middleware
javascript
// middleware/auth.js
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useCookie('token').value
if (!isAuthenticated) {
return navigateTo('/login')
}
})
// Usage in page
<template>
<div>Protected content</div>
</template>
<script setup>
definePageMeta({
middleware: 'auth'
})
</script>Layouts
vue
<!-- layouts/default.vue -->
<template>
<div>
<Header />
<slot />
<Footer />
</div>
</template>
<!-- layouts/custom.vue -->
<template>
<div class="custom-layout">
<slot />
</div>
</template>
<!-- Usage in page -->
<template>
<div>
<h1>Custom Layout Page</h1>
</div>
</template>
<script setup>
definePageMeta({
layout: 'custom'
})
</script>State Management with Pinia
javascript
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
user: null,
token: null
}),
getters: {
isAuthenticated: (state) => !!state.token
},
actions: {
setUser(user, token) {
this.user = user
this.token = token
},
logout() {
this.user = null
this.token = null
}
}
})Configuration
typescript
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss'],
app: {
head: {
title: 'My Nuxt App',
meta: [
{ name: 'description', content: 'My amazing Nuxt app' }
]
}
},
runtimeConfig: {
public: {
apiBase: '/api'
},
private: {
apiSecret: process.env.API_SECRET
}
},
css: ['~/assets/css/main.css'],
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/scss/variables" as *;`
}
}
}
}
})Deployment
Build for production:
bash
npm run buildDeploy to Vercel, Netlify, or any Node.js hosting platform.
Nuxt 3 provides a complete solution for building modern Vue applications with SSR, API routes, and excellent developer experience.