Nuxt.js Cheat Sheet
A reference for Nuxt 3's file-based routing, useFetch and useAsyncData composables, and server API routes for full-stack Vue apps.
File-Based Page
Pages are auto-routed from the pages/ directory; params come from useRoute().
<!-- pages/posts/[id].vue --><script setup>const route = useRoute();const { data: post } = await useFetch(`/api/posts/${route.params.id}`);</script><template> <h1>{{ post.title }}</h1></template>
Data Fetching
SSR-aware composables for fetching and sharing async data.
<script setup>// useFetch: SSR-friendly fetch that caches and dedupes requestsconst { data, pending, error, refresh } = await useFetch('/api/products');// useAsyncData: for custom async logic or combining multiple sourcesconst { data: user } = await useAsyncData('user', () => $fetch('/api/user'));</script>
Core Composables
The building blocks of a typical Nuxt 3 application.
- useFetch- SSR-aware wrapper around $fetch that caches and dedupes requests
- useAsyncData- resolves any async logic and shares its state between server and client render
- $fetch- Nuxt's built-in fetch utility (from ofetch), usable anywhere including server API routes
- useState- creates SSR-safe, shared reactive state keyed by name, like a lightweight store
- useRoute / useRouter- access the current route and perform programmatic navigation
- definePageMeta- sets per-page metadata such as layout, middleware, or transition
- server/api/- directory for defining server (Nitro) API routes that are auto-registered
nuxt.config.ts
Central configuration for modules and runtime config.
export default defineNuxtConfig({ modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt'], runtimeConfig: { apiSecret: process.env.API_SECRET, public: { apiBase: '/api' }, }, devtools: { enabled: true },});
Nitro Server Event Handlers
Define API routes with H3's defineEventHandler, reading params, query, and validated bodies.
// server/api/posts/[id].patch.tsimport { z } from 'zod';const bodySchema = z.object({ title: z.string().min(1) });export default defineEventHandler(async (event) => { const id = getRouterParam(event, 'id'); const body = await readValidatedBody(event, bodySchema.parse); const updated = await db.posts.update(id, body); if (!updated) { throw createError({ statusCode: 404, statusMessage: 'Post not found' }); } return updated;});
Nuxt Plugins
Inject a service or third-party client into every component via defineNuxtPlugin and provide.
// plugins/analytics.client.tsexport default defineNuxtPlugin((nuxtApp) => { const analytics = createAnalyticsClient(useRuntimeConfig().public.analyticsKey); nuxtApp.hook('page:finish', () => analytics.trackPageview()); return { provide: { analytics }, };});// usage in a componentconst { $analytics } = useNuxtApp();$analytics.track('signup_clicked');
Hybrid Rendering with routeRules
Mix static, SWR-cached, and SSR strategies per route from a single config -- no per-page code changes needed.
export default defineNuxtConfig({ routeRules: { '/': { prerender: true }, '/blog/**': { swr: 3600 }, // stale-while-revalidate cache, 1hr '/admin/**': { ssr: false }, // client-only rendering '/api/legacy/**': { proxy: 'https://old-api.example.com/**' }, '/dashboard': { headers: { 'cache-control': 'no-cache' } }, },});
Advanced Nuxt Concepts
Pieces you reach for once a Nuxt app grows past basic pages and fetch calls.
- Nitro- the universal server engine powering server/api routes, routeRules, and multi-platform deployment presets
- Layers- extend a Nuxt config/app from another Nuxt project or npm package via the extends option, for shared design systems
- Nuxt Hooks- lifecycle hooks (app:mounted, page:finish, build:before) for tapping into core Nuxt/Nitro behavior
- useNuxtApp()- access the current app instance, injected plugins ($fetch helpers), and hook APIs from anywhere
- useHead / useSeoMeta- composables for reactive <head> tags and typed SEO meta without a separate head plugin
- defineNuxtRouteMiddleware- per-route navigation guards run before rendering, usable globally or per-page via definePageMeta
- Islands / server components- <NuxtIsland>-backed server-only components that ship zero client JS for static UI chunks
Route Middleware (Auth Guard)
Global or named middleware that runs before a route resolves, redirecting unauthenticated users.
// middleware/auth.global.tsexport default defineNuxtRouteMiddleware((to) => { const { loggedIn } = useAuth(); if (!loggedIn.value && to.path.startsWith('/dashboard')) { return navigateTo('/login', { redirectCode: 302 }); }});// pages/settings.vue -- opt out of the global guard for a public pagedefinePageMeta({ middleware: [] });
Use useFetch or useAsyncData instead of onMounted + fetch for anything that should render on the server -- otherwise you lose SSR and get a content flash, because the component has no data during the server render pass.