Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Nuxt 3.x reference covering SSR, file-based routing, auto-imports, server routes, and Nitro deployment.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/features-composables.md
1---2name: composables-auto-imports3description: Auto-imported Vue APIs, Nuxt composables, and custom utilities4---56# Composables Auto-imports78Nuxt automatically imports Vue APIs, Nuxt composables, and your custom composables/utilities.910## Built-in Auto-imports1112### Vue APIs1314```vue15<script setup lang="ts">16// No imports needed - all auto-imported17const count = ref(0)18const doubled = computed(() => count.value * 2)1920watch(count, (newVal) => {21console.log('Count changed:', newVal)22})2324onMounted(() => {25console.log('Component mounted')26})2728// Lifecycle hooks29onBeforeMount(() => {})30onUnmounted(() => {})31onBeforeUnmount(() => {})3233// Reactivity34const state = reactive({ name: 'John' })35const shallow = shallowRef({ deep: 'object' })36</script>37```3839### Nuxt Composables4041```vue42<script setup lang="ts">43// All auto-imported44const route = useRoute()45const router = useRouter()46const config = useRuntimeConfig()47const appConfig = useAppConfig()48const nuxtApp = useNuxtApp()4950// Data fetching51const { data } = await useFetch('/api/data')52const { data: asyncData } = await useAsyncData('key', () => fetchData())5354// State55const state = useState('key', () => 'initial')56const cookie = useCookie('token')5758// Head/SEO59useHead({ title: 'My Page' })60useSeoMeta({ description: 'Page description' })6162// Request helpers (SSR)63const headers = useRequestHeaders()64const event = useRequestEvent()65const url = useRequestURL()66</script>67```6869## Custom Composables (`app/composables/`)7071### Creating Composables7273```ts74// composables/useCounter.ts75export function useCounter(initial = 0) {76const count = ref(initial)77const increment = () => count.value++78const decrement = () => count.value--79return { count, increment, decrement }80}81```8283```ts84// composables/useAuth.ts85export function useAuth() {86const user = useState<User | null>('user', () => null)87const isLoggedIn = computed(() => !!user.value)8889async function login(credentials: Credentials) {90user.value = await $fetch('/api/auth/login', {91method: 'POST',92body: credentials,93})94}9596async function logout() {97await $fetch('/api/auth/logout', { method: 'POST' })98user.value = null99}100101return { user, isLoggedIn, login, logout }102}103```104105### Using Composables106107```vue108<script setup lang="ts">109// Auto-imported - no import statement needed110const { count, increment } = useCounter(10)111const { user, isLoggedIn, login } = useAuth()112</script>113```114115### File Scanning Rules116117Only top-level files are scanned:118119```120composables/121├── useAuth.ts → useAuth() ✓122├── useCounter.ts → useCounter() ✓123├── index.ts → exports ✓124└── nested/125└── helper.ts → NOT auto-imported ✗126```127128Re-export nested composables:129130```ts131// composables/index.ts132export { useHelper } from './nested/helper'133```134135Or configure scanning:136137```ts138// nuxt.config.ts139export default defineNuxtConfig({140imports: {141dirs: [142'composables',143'composables/**', // Scan all nested144],145},146})147```148149## Utilities (`app/utils/`)150151```ts152// utils/format.ts153export function formatDate(date: Date) {154return date.toLocaleDateString()155}156157export function formatCurrency(amount: number) {158return new Intl.NumberFormat('en-US', {159style: 'currency',160currency: 'USD',161}).format(amount)162}163```164165```vue166<script setup lang="ts">167// Auto-imported168const date = formatDate(new Date())169const price = formatCurrency(99.99)170</script>171```172173## Server Utils (`server/utils/`)174175```ts176// server/utils/db.ts177export function useDb() {178return createDbConnection()179}180181// server/utils/auth.ts182export function verifyToken(token: string) {183return jwt.verify(token, process.env.JWT_SECRET)184}185```186187```ts188// server/api/users.ts189export default defineEventHandler(() => {190const db = useDb() // Auto-imported191return db.query('SELECT * FROM users')192})193```194195## Third-party Package Imports196197```ts198// nuxt.config.ts199export default defineNuxtConfig({200imports: {201presets: [202{203from: 'vue-i18n',204imports: ['useI18n'],205},206{207from: 'date-fns',208imports: ['format', 'parseISO', 'differenceInDays'],209},210{211from: '@vueuse/core',212imports: ['useMouse', 'useWindowSize'],213},214],215},216})217```218219## Explicit Imports220221Use `#imports` alias when needed:222223```vue224<script setup lang="ts">225import { ref, computed, useFetch } from '#imports'226</script>227```228229## Composable Context Rules230231Nuxt composables must be called in valid context:232233```ts234// ❌ Wrong - module level235const config = useRuntimeConfig()236237export function useMyComposable() {}238```239240```ts241// ✅ Correct - inside function242export function useMyComposable() {243const config = useRuntimeConfig()244return { apiBase: config.public.apiBase }245}246```247248**Valid contexts:**249- `<script setup>` block250- `setup()` function251- `defineNuxtPlugin()` callback252- `defineNuxtRouteMiddleware()` callback253254## Disabling Auto-imports255256```ts257// nuxt.config.ts258export default defineNuxtConfig({259// Disable all auto-imports260imports: {261autoImport: false,262},263264// Or disable only directory scanning (keep Vue/Nuxt imports)265imports: {266scan: false,267},268})269```270271<!--272Source references:273- https://nuxt.com/docs/guide/concepts/auto-imports274- https://nuxt.com/docs/directory-structure/app/composables275- https://nuxt.com/docs/directory-structure/app/utils276-->277