The shared/ directory allows you to share code that can be used in both the Vue app and the Nitro server.
shared/ directory is available in Nuxt v3.14+.shared/ directory cannot import any Vue or Nitro code.Why You Cannot Mix Vue and Nitro Code
Nuxt builds two separate bundles: the Vue app (client and server-side rendering) and the Nitro server (API routes, server middleware, server plugins). They are bundled independently and run in different contexts. Code in the shared/ directory is used in both bundles, so it cannot import from either.
Vue App Code in Nitro
Components and composables need the Vue app runtime and often the Nuxt context (for example useNuxtApp() or useRoute()), neither of which exists in Nitro. Importing them into server code can cause build or runtime errors, and can pull the Vue app's dependencies into your server bundle.
Nitro Code in the Vue App
Server-only code (such as Node APIs, Nitro utilities, or server route handlers) must not run in the browser. Importing it into your app can break the client build, cause runtime errors in the browser, or leak server logic into the client bundle.
Type-Only Imports
import type is erased at compile time and does not pull runtime code into the other bundle, so importing only types across the boundary may appear to work. Even so, keep shared types (such as API response types) in shared/types/, where they are auto-imported in both contexts. This keeps the boundary clear, avoids accidentally turning a type import into a value import later, and matches Nuxt's separate type contexts for app, server, and shared code.
Usage
Method 1: Named export
export const capitalize = (input: string) => {
return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}
Method 2: Default export
export default function (input: string) {
return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}
You can now use auto-imported utilities in your Nuxt app and server/ directory.
<script setup lang="ts">
const hello = capitalize('hello')
</script>
<template>
<div>
{{ hello }}
</div>
</template>
export default defineEventHandler((event) => {
return {
hello: capitalize('hello'),
}
})
How Files Are Scanned
Only files in the shared/utils/ and shared/types/ directories will be auto-imported. Files nested within subdirectories of these directories will not be auto-imported unless you add these directories to imports.dirs and nitro.imports.dirs.
shared/utils and shared/types auto-imports work and are scanned is identical to the app/composables/ and app/utils/ directories.-| shared/
---| capitalize.ts # Not auto-imported
---| formatters
-----| lower.ts # Not auto-imported
---| utils/
-----| lower.ts # Auto-imported
-----| formatters
-------| upper.ts # Not auto-imported
---| types/
-----| bar.ts # Auto-imported
Any other files you create in the shared/ folder must be manually imported using the #shared alias (automatically configured by Nuxt):
// For files directly in the shared directory
import capitalize from '#shared/capitalize'
// For files in nested directories
import lower from '#shared/formatters/lower'
// For files nested in a folder within utils
import upper from '#shared/utils/formatters/upper'
This alias ensures consistent imports across your application, regardless of the importing file's location.