Composables and utils
A composable is a function that hides repeating logic with reactive data, for example a likes counter. Its name usually starts with use. In Vue you import such functions by hand, while Nuxt makes them available automatically from the app/composables/ folder. For plain functions without reactivity there is a sibling folder, app/utils/.
Your own composable
npx nuxi add composable useLikesThe command creates app/composables/useLikes.ts. Replace its content:
// app/composables/useLikes.ts
export function useLikes() {
const likes = ref(0)
function like() {
likes.value++
}
return { likes, like }
}ref is not imported either: Nuxt provides Vue functions (ref, computed, watch, onMounted and others) itself.
Using it
Add a like button to the card app/components/PostCard.vue:
<!-- app/components/PostCard.vue -->
<script setup lang="ts">
defineProps<{
post: { id: number; title: string; text: string }
}>()
const { likes, like } = useLikes()
</script>
<template>
<article class="post-card">
<h3>
<NuxtLink :to="`/posts/${post.id}`">{{ post.title }}</NuxtLink>
</h3>
<button @click="like">Likes: {{ likes }}</button>
</article>
</template>Each card on /posts has its own counter: the function runs again for every component and creates a new ref.
Utils
Functions without reactivity go into app/utils/. Create app/utils/formatDate.ts:
// app/utils/formatDate.ts
export function formatDate(date: string) {
return new Date(date).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric'
})
}Now any component can write {{ formatDate('2025-03-14') }} and get "March 14, 2025" without an import.
What is imported automatically
| From | What |
|---|---|
| Vue | ref, computed, watch, onMounted and others |
| Nuxt | useRoute, navigateTo, useFetch, useState and others |
app/composables/ | Exports of top-level files |
app/utils/ | Exports of top-level files |
app/components/ | Components |
An explicit import also works if it reads better: import { useLikes } from '~/composables/useLikes'.
Where to call composables
Nuxt composables (useRoute, useFetch, useState) and your own ones that use them are called in <script setup>, in another composable, in middleware or in a plugin. Calling them inside setTimeout or after an await in a regular function can fail with "A composable that requires access to the Nuxt instance was called outside of a plugin".
Common mistake
Nuxt scans only the top-level files of app/composables/. A file in a subfolder, such as app/composables/posts/usePosts.ts, is not imported automatically, and the template fails with usePosts is not defined. Keep composables directly in the folder or import a subfolder file explicitly.