Nuxt 3 Complete Guide | Full-Stack Vue.js Framework
이 글의 핵심
Nuxt 3 is the full-stack Vue.js framework — file-based routing, server routes, composables, and automatic SSR/SSG. This guide covers the Nuxt 3 ecosystem with practical examples for building production apps.
What This Guide Covers
Nuxt 3 brings full-stack capabilities to Vue — file-based routing, server API routes, universal data fetching, and automatic SSR/SSG. This guide covers the core features with a practical blog/app example.
Real-world insight: Migrating a Vue SPA to Nuxt 3 cut Time to First Byte by 70% and improved Core Web Vitals scores enough to boost organic traffic by 40% in two months.
Setup
npx nuxi@latest init my-app
cd my-app
npm install
npm run dev
App runs on http://localhost:3000.
Project Structure
my-app/
pages/ ← file-based routing
components/ ← auto-imported components
composables/ ← auto-imported composables (useX)
server/
api/ ← server API routes
middleware/ ← server middleware
layouts/ ← page layouts
middleware/ ← client/universal route middleware
plugins/ ← Nuxt plugins
public/ ← static assets
nuxt.config.ts
1. File-Based Routing
Create files in pages/ — Nuxt generates routes automatically:
pages/
index.vue → /
about.vue → /about
blog/
index.vue → /blog
[slug].vue → /blog/:slug
users/
[id]/
index.vue → /users/:id
posts.vue → /users/:id/posts
[...404].vue → catch-all / 404
<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
</script>
<template>
<article>
<h1>{{ post?.title }}</h1>
<p>{{ post?.body }}</p>
</article>
</template>
2. Server Routes (API)
Create files in server/api/ — Nuxt generates server endpoints:
// server/api/posts/index.get.ts
export default defineEventHandler(async (event) => {
// Access DB, external API, etc.
return [
{ id: 1, title: 'Nuxt 3 Guide', slug: 'nuxt-3-guide' },
{ id: 2, title: 'Vue Composables', slug: 'vue-composables' },
]
})
// server/api/posts/[slug].get.ts
export default defineEventHandler(async (event) => {
const slug = getRouterParam(event, 'slug')
// Fetch from DB...
return { id: 1, title: 'Nuxt 3 Guide', slug, body: '...' }
})
// server/api/posts/index.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
// Validate and save...
return { created: body }
})
File naming convention: [name].[method].ts — GET, POST, PUT, DELETE, PATCH.
3. Data Fetching
<script setup lang="ts">
// useFetch: SSR-aware, cached, auto-typed
const { data, pending, error, refresh } = await useFetch('/api/posts')
// $fetch: manual fetch (works client and server side)
const post = await $fetch('/api/posts/my-slug')
// useAsyncData: custom async logic
const { data: user } = await useAsyncData('user', () =>
$fetch(`/api/users/${userId}`)
)
// lazy loading (don't block navigation)
const { data: comments, pending } = useLazyFetch('/api/comments')
</script>
<template>
<div>
<div v-if="pending">Loading...</div>
<ul v-else>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
</div>
</template>
useFetch automatically shares data between server and client — no duplicate requests.
4. Composables
Composables in composables/ are auto-imported anywhere in your app:
// composables/useAuth.ts
export function useAuth() {
const user = useState<User | null>('auth-user', () => null)
const isLoggedIn = computed(() => user.value !== null)
async function login(email: string, password: string) {
const data = await $fetch('/api/auth/login', {
method: 'POST',
body: { email, password },
})
user.value = data.user
await navigateTo('/dashboard')
}
async function logout() {
await $fetch('/api/auth/logout', { method: 'POST' })
user.value = null
await navigateTo('/login')
}
return { user, isLoggedIn, login, logout }
}
<script setup lang="ts">
// No import needed — auto-imported
const { user, isLoggedIn, logout } = useAuth()
</script>
5. Layouts
<!-- layouts/default.vue -->
<template>
<div>
<AppHeader />
<main>
<slot /> <!-- page content goes here -->
</main>
<AppFooter />
</div>
</template>
<!-- layouts/dashboard.vue -->
<template>
<div class="dashboard">
<Sidebar />
<main><slot /></main>
</div>
</template>
<!-- pages/dashboard/index.vue -->
<script setup lang="ts">
definePageMeta({ layout: 'dashboard' })
</script>
6. Middleware
// middleware/auth.ts (client + server)
export default defineNuxtRouteMiddleware((to, from) => {
const { isLoggedIn } = useAuth()
if (!isLoggedIn.value && to.path !== '/login') {
return navigateTo('/login')
}
})
<!-- pages/dashboard/index.vue -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
</script>
Server middleware (runs on every request):
// server/middleware/logger.ts
export default defineEventHandler((event) => {
console.log(`[${new Date().toISOString()}] ${event.method} ${event.path}`)
})
7. State Management
Nuxt’s useState shares state between server and client:
// composables/useCounter.ts
export const useCounter = () => useState('counter', () => 0)
<script setup lang="ts">
const count = useCounter()
</script>
<template>
<button @click="count++">Count: {{ count }}</button>
</template>
For complex state, use Pinia (Nuxt’s recommended store):
npx nuxi module add pinia
// stores/cart.ts
export const useCartStore = defineStore('cart', () => {
const items = ref<CartItem[]>([])
const total = computed(() => items.value.reduce((sum, i) => sum + i.price, 0))
function addItem(item: CartItem) {
items.value.push(item)
}
return { items, total, addItem }
})
8. SEO and Meta
<script setup lang="ts">
useSeoMeta({
title: 'My Page Title',
ogTitle: 'My Page Title',
description: 'This is a description of my page.. Nuxt 3 Complete Guide에 대한 완전한 가이드입니다. 실전 예제와 함께 핵심 개념부터 고급 활용까지 다룹니다.',
ogDescription: 'This is a description of my page.',
ogImage: 'https://example.com/image.png',
twitterCard: 'summary_large_image',
})
// Dynamic meta
const { data: post } = await useFetch(`/api/posts/${slug}`)
useSeoMeta({
title: () => post.value?.title,
description: () => post.value?.excerpt,
})
</script>
9. nuxt.config.ts
export default defineNuxtConfig({
// Rendering mode
ssr: true, // SSR (default)
// Nitro server config
nitro: {
preset: 'cloudflare-pages', // or 'vercel', 'netlify', etc.
},
// Runtime config (env vars)
runtimeConfig: {
// Server-only (secret)
databaseUrl: process.env.DATABASE_URL,
// Public (exposed to client)
public: {
apiBase: process.env.API_BASE_URL || '/api',
},
},
// Modules
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss', '@nuxt/image'],
// TypeScript
typescript: { strict: true },
})
Access runtime config:
const config = useRuntimeConfig()
console.log(config.public.apiBase) // client or server
console.log(config.databaseUrl) // server only
10. Deployment
# Build for production
npm run build
# Deploy to Node.js server
node .output/server/index.mjs
# Deploy to Cloudflare Pages
NITRO_PRESET=cloudflare-pages npm run build
# Upload .output/public to Cloudflare Pages
# Static generation (SSG)
npm run generate
# Upload .output/public anywhere (S3, GitHub Pages, etc.)
Key Takeaways
| Feature | How |
|---|---|
| Routing | File-based in pages/ |
| Server API | Files in server/api/ |
| Data fetching | useFetch, useAsyncData, $fetch |
| State | useState (built-in), Pinia (recommended) |
| Auto-imports | components/, composables/ — no imports needed |
| SEO | useSeoMeta() |
| Deployment | Any platform via Nitro presets |
Nuxt 3’s key strength is reducing boilerplate — auto-imports, file-based routing, and built-in SSR mean you focus on features, not configuration. If you know Vue 3, Nuxt 3 is a natural upgrade for any project that needs SEO or a backend.
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. Build full-stack apps with Nuxt 3. Covers file-based routing, server routes, composables, Nitro server, data fetching, a…
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- The Complete Nuxt 3 Guide | Vue, SSR, Composables, Nitro, Server Routes
- The Complete SvelteKit Guide | Full Stack, Routing, Form Actions, Load, Hooks
- MCP (Model Context Protocol) Complete Guide
Keywords Covered in This Article (Related Search Terms)
This article covers Nuxt, Vue, JavaScript, SSR, Full-Stack, TypeScript.