Plugins in Nuxt
Running setup code once when the app starts — registering a library, injecting a helper, or hooking into Vue's app instance.
2 min de lectura
Some code needs to run once, when the app first starts up, rather than per-component or per-page — registering a third-party library with Vue, setting up a global error handler, or injecting a helper you want available everywhere. Nuxt's plugins/ directory is for exactly that.
A basic plugin
Any file in plugins/ runs automatically during app startup, in filename order:
// plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
console.error("Global error:", error, info);
// report to an error-tracking service here
};
});defineNuxtPlugin hands you nuxtApp, which wraps the underlying Vue app instance (nuxtApp.vueApp) along with Nuxt-specific hooks and helpers. This is the same place you'd register a Vue plugin that expects app.use(...):
// plugins/toast.ts
import Toast from "some-toast-library";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toast);
});Injecting a helper available everywhere
provide on a plugin makes a value available as $name in every component's template and via useNuxtApp() in script, without importing it each time:
// plugins/format.ts
export default defineNuxtPlugin(() => {
return {
provide: {
formatCurrency: (amount: number) =>
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(amount),
},
};
});<template>
<p>{{ $formatCurrency(29.99) }}</p>
</template>
<script setup>
const { $formatCurrency } = useNuxtApp();
console.log($formatCurrency(29.99));
</script>Client-only and server-only plugins
A filename suffix restricts where a plugin runs, which matters for libraries that only work in the browser (most charting or DOM-measurement libraries, for instance):
plugins/
├─ analytics.client.ts # browser only
└─ logger.server.ts # server only
Trying to run a browser-only library's setup code during SSR typically crashes the server render outright, since it reaches for window or document, which don't exist in Node — the .client.ts suffix is what keeps that code from ever being evaluated there.
Plugins vs. composables
It's worth being clear about the difference: a composable is called explicitly, from wherever you need its logic — it does nothing on its own until a component calls it. A plugin runs unconditionally, once, at startup, whether or not anything ends up using what it sets up. Reach for a plugin when something needs to exist before any component runs (a library registration, a global helper); reach for a composable for logic a component opts into.