nuxt-development
Nuxt.js Development Standards
Apply these standards when developing Nuxt.js 3 applications. For general Vue coding standards, also refer to the vue-development skill.
Prerequisites
This skill extends Vue.js development standards. Follow all Vue 3 Composition API guidelines unless specifically overridden here.
Nuxt-Specific Guidelines
Pages (File-Based Routing)
- Place all route pages in the
pages/directory - File and folder names automatically define the route structure
- Use
<script setup>at the top, followed by<template>, then<style scoped> - Use TypeScript for all pages when possible
Example structure:
pages/
├── index.vue # Route: /
├── about.vue # Route: /about
├── users/
│ ├── index.vue # Route: /users
│ └── [id].vue # Route: /users/:id
└── [...slug].vue # Catch-all route
Layouts
- Place shared layouts in the
layouts/directory - Use
default.vuefor the main app shell - Use
<NuxtLayout />component to switch layouts dynamically - Use
definePageMetacomposable for page-specific metadata
Example layout:
<script setup lang="ts">
// layouts/default.vue
</script>
<template>
<div class="layout">
<header>
<nav><!-- Navigation --></nav>
</header>
<main>
<slot />
</main>
<footer><!-- Footer --></footer>
</div>
</template>
Using layouts:
<script setup lang="ts">
definePageMeta({
layout: 'custom'
})
</script>
Auto-Import Components
- Place reusable components in the
components/directory - Nuxt auto-imports components - no manual imports needed
- Use PascalCase for component file names
- Organize with subdirectories for namespacing
Example:
components/
├── AppHeader.vue # <AppHeader />
├── TheFooter.vue # <TheFooter />
└── user/
└── UserCard.vue # <UserCard /> or <UserUserCard />
Composables
- Place composable functions in the
composables/directory - Nuxt auto-imports composables starting with
use - Use Nuxt-specific composables:
useRoute()- Current route informationuseRouter()- Router instanceuseAsyncData()- Fetch data with SSR supportuseFetch()- Simplified data fetchinguseState()- Shared state across componentsuseCookie()- Cookie managementuseHead()- Meta tags and SEO
Example composable:
// composables/useAuth.ts
export const useAuth = () => {
const user = useState('user', () => null)
const isAuthenticated = computed(() => !!user.value)
const login = async credentials => {
const data = await $fetch('/api/auth/login', {
method: 'POST',
body: credentials
})
user.value = data.user
}
const logout = () => {
user.value = null
}
return {
user,
isAuthenticated,
login,
logout
}
}
Data Fetching
Use useFetch or useAsyncData for SSR-compatible data fetching:
<script setup lang="ts">
// Automatic key generation
const { data: users } = await useFetch('/api/users')
// Manual key for more control
const { data: user, refresh } = await useAsyncData('user', () => $fetch(`/api/users/${route.params.id}`))
// With options
const { data, pending, error } = await useFetch('/api/data', {
method: 'POST',
body: { query: 'search' },
lazy: true, // Don't block navigation
server: true, // SSR
watch: [searchQuery] // Re-fetch on change
})
</script>
Server Routes (API)
- Place API routes in the
server/api/directory - Use event handlers with
defineEventHandler
Example:
// server/api/users/[id].get.ts
export default defineEventHandler(async event => {
const id = getRouterParam(event, 'id')
// Fetch user from database
const user = await prisma.user.findUnique({
where: { id: parseInt(id) }
})
if (!user) {
throw createError({
statusCode: 404,
message: 'User not found'
})
}
return user
})
Middleware
- Place middleware in the
middleware/directory - Auto-imported and available globally or per-page
Example:
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const auth = useAuth()
if (!auth.isAuthenticated.value) {
return navigateTo('/login')
}
})
Apply to page:
<script setup lang="ts">
definePageMeta({
middleware: ['auth']
})
</script>
Directory Structure
Follow Nuxt's conventions:
project/
├── .nuxt/ # Build output (auto-generated)
├── assets/ # Uncompiled assets (CSS, images)
├── components/ # Auto-imported components
├── composables/ # Auto-imported composables
├── layouts/ # App layouts
├── middleware/ # Route middleware
├── pages/ # File-based routing
├── plugins/ # App plugins
├── public/ # Static assets
├── server/ # Server-side code
│ ├── api/ # API endpoints
│ ├── middleware/ # Server middleware
│ └── routes/ # Server routes
├── stores/ # Pinia stores (if using state management)
├── nuxt.config.ts # Nuxt configuration
└── app.vue # Root component (optional)
Configuration
nuxt.config.ts:
export default defineNuxtConfig({
devtools: { enabled: true },
modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt'],
runtimeConfig: {
// Private (server-only)
apiSecret: process.env.API_SECRET,
// Public (client + server)
public: {
apiBase: process.env.API_BASE_URL || '/api'
}
},
app: {
head: {
title: 'My Nuxt App',
meta: [{ charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }]
}
}
})
Example Page Component
<script setup lang="ts">
import { ref } from 'vue'
// Auto-imported composables
const route = useRoute()
const router = useRouter()
// Page metadata
definePageMeta({
layout: 'default',
middleware: ['auth']
})
// SEO
useHead({
title: 'User Profile',
meta: [{ name: 'description', content: 'User profile page' }]
})
// Data fetching with SSR
const { data: user, pending } = await useFetch(`/api/users/${route.params.id}`)
// Local state
const isEditing = ref(false)
const saveProfile = async () => {
await $fetch(`/api/users/${route.params.id}`, {
method: 'PUT',
body: user.value
})
isEditing.value = false
}
</script>
<template>
<div class="profile">
<h1 v-if="pending">Loading...</h1>
<div v-else-if="user">
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
<button @click="isEditing = !isEditing">
{{ isEditing ? 'Cancel' : 'Edit' }}
</button>
<button v-if="isEditing" @click="saveProfile">Save</button>
</div>
</div>
</template>
<style scoped>
.profile {
padding: 2rem;
}
</style>
Best Practices
- Use auto-imports - No need to manually import Vue, Nuxt composables, or components
- SSR-first - Always consider server-side rendering in data fetching
- Use
useFetch- Prefer over manualfetchfor automatic SSR handling - Type safety - Enable TypeScript for better DX
- Middleware - Use for authentication, redirects, and data validation
- State management - Use
useStatefor simple shared state, Pinia for complex state - Error handling - Use
throw createError()for consistent error pages
When to Apply
Apply these standards when:
- Creating Nuxt.js projects
- Building pages and layouts
- Writing composables
- Creating API endpoints
- Implementing SSR/SSG
- User asks about Nuxt.js patterns
More from devbyray/github-copilot-starter
html-standards
Guidelines for writing HTML that is accessible, semantic, maintainable, and secure. Use when working with .html, .vue, .twig, .php, .cshtml, .svelte files, or when the user asks about HTML structure, semantic markup, accessibility, or web security best practices.
10markdown-standards
Documentation and content creation standards for Markdown files. Use when creating or editing .md files, writing documentation, README files, or when the user asks about Markdown formatting, content structure, front matter, or documentation best practices.
6css-standards
Guidelines for writing CSS that is simple, readable, and maintainable. Use when working with .css, .scss, .sass files, CSS-in-JS, styled-components, or when the user asks about CSS organization, selectors, specificity, reusability, performance, or responsive design patterns.
4javascript-typescript-standards
Guidelines for writing JavaScript and TypeScript code that is simple, readable, and maintainable. Use when working with .js, .jsx, .ts, .tsx, .mjs, .cjs files, or when the user asks about JavaScript/TypeScript coding standards, ES2022 features, Node.js modules, async/await patterns, or testing with Vitest.
4testing-tdd
Test-Driven Development workflow and testing standards. Use when writing tests, implementing TDD, working with Vitest (frontend), xUnit or MsTest (backend), or when the user asks about testing strategies, test coverage, or TDD methodology.
3csharp-standards
C# coding standards and conventions including naming, formatting, and best practices. Use when working with .cs files, writing C# code, or when the user asks about C# naming conventions, code structure, XML documentation, or .NET development patterns.
3