1. Route Middleware
// middleware/auth.ts — named middleware
export default defineNuxtRouteMiddleware((to, from) => {
const { loggedIn } = useUserSession()
if (!loggedIn.value) {
return navigateTo('/login', { redirectCode: 301 })
}
})
// middleware/admin.ts
export default defineNuxtRouteMiddleware((to) => {
const { user } = useUserSession()
if (user.value?.role !== 'admin') {
return abortNavigation({
statusCode: 403,
message: 'Không có quyền truy cập',
})
}
})
<!-- pages/dashboard.vue — apply middleware -->
<script setup lang="ts">
definePageMeta({
middleware: ['auth'], // Named middleware
})
</script>
<!-- pages/admin.vue — multiple middleware -->
<script setup lang="ts">
definePageMeta({
middleware: ['auth', 'admin'],
})
</script>
// middleware/01.global.ts — runs on every route
export default defineNuxtRouteMiddleware((to, from) => {
console.log(`Navigate: ${from.path} → ${to.path}`)
})
2. Nuxt Plugins
// plugins/api.ts
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const api = $fetch.create({
baseURL: config.public.apiBase,
onRequest({ options }) {
const token = useCookie('token')
if (token.value) {
options.headers.set('Authorization', `Bearer ${token.value}`)
}
},
onResponseError({ response }) {
if (response.status === 401) {
navigateTo('/login')
}
},
})
return {
provide: {
api, // Available as useNuxtApp().$api
},
}
})
// plugins/dayjs.client.ts — client-only plugin
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/vi'
export default defineNuxtPlugin(() => {
dayjs.extend(relativeTime)
dayjs.locale('vi')
return {
provide: {
dayjs,
},
}
})
3. Nuxt Modules Ecosystem
| Module | Function |
|---|---|
| @nuxtjs/tailwindcss | Tailwind CSS integration |
| @pinia/nuxt | Pinia state management |
| @nuxt/image | Image optimization |
| @nuxt/content | File-based CMS |
| @nuxtjs/i18n | Internationalization |
| @sidebase/nuxt-auth | Authentication |
| nuxt-auth-utils | OAuth helpers |
| @nuxt/fonts | Font optimization |
| @nuxt/scripts | Third-party scripts |
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@pinia/nuxt',
'@nuxt/image',
'@nuxtjs/i18n',
],
i18n: {
locales: [
{ code: 'vi', file: 'vi.json' },
{ code: 'en', file: 'en.json' },
],
defaultLocale: 'vi',
langDir: 'locales/',
},
image: {
quality: 80,
format: ['webp', 'avif'],
},
})
4. Custom Modules
// modules/analytics/index.ts
import { defineNuxtModule, addPlugin, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-analytics',
configKey: 'analytics',
},
defaults: {
trackingId: '',
},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
// Add runtime plugin
addPlugin(resolver.resolve('./runtime/plugin'))
// Add composable
nuxt.options.alias['#analytics'] = resolver.resolve('./runtime/composables')
},
})
Next article: Authentication & Authorization — OAuth, sessions, RBAC.