From harness-claude
Implements Nuxt plugins using defineNuxtPlugin to register Vue plugins, provide global services via useNuxtApp(), run client/server init code, control order, and augment TypeScript types.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Extend the Nuxt application instance, register global services, and provide values to composables using defineNuxtPlugin
Creates Nuxt modules with defineNuxtModule to extend apps at build time, adding components, imports, plugins, server routes, and Nitro/Vite configs programmatically. For reusable integrations.
Guides TDD-first Vue 3/Nuxt 3 development with Composition API, TypeScript, Pinia, Vitest tests, composables, SSR/SSG, performance optimization, and client-side security.
Share bugs, ideas, or general feedback.
Extend the Nuxt application instance, register global services, and provide values to composables using defineNuxtPlugin
useNuxtApp().$myHelperplugins/ — they are automatically registered. Files are named without registration in nuxt.config.ts:// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
// runs on both server and client
});
nuxtApp.vueApp.use():// plugins/vue-query.ts
import { VueQueryPlugin, QueryClient } from '@tanstack/vue-query';
export default defineNuxtPlugin((nuxtApp) => {
const queryClient = new QueryClient();
nuxtApp.vueApp.use(VueQueryPlugin, { queryClient });
});
useNuxtApp().$<name>:// plugins/analytics.ts
export default defineNuxtPlugin(() => {
const analytics = createAnalyticsClient();
return {
provide: {
analytics,
},
};
});
// In any composable or component:
const { $analytics } = useNuxtApp();
$analytics.track('page_view');
// types/nuxt.d.ts
declare module '#app' {
interface NuxtApp {
$analytics: AnalyticsClient;
}
}
declare module 'vue' {
interface ComponentCustomProperties {
$analytics: AnalyticsClient;
}
}
export {};
.client.ts:// plugins/crisp-chat.client.ts
export default defineNuxtPlugin(() => {
// runs only in the browser
window.$crisp = [];
window.CRISP_WEBSITE_ID = 'your-id';
});
.server.ts:// plugins/db-connection.server.ts
export default defineNuxtPlugin(async () => {
await connectDatabase();
});
order property:// plugins/01.init.ts — runs first
// plugins/02.auth.ts — runs second
// Or use the order property (lower = earlier):
export default defineNuxtPlugin({
name: 'auth',
enforce: 'pre', // or 'post'
setup(nuxtApp) {
/* ... */
},
});
nuxtApp argument:export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('app:mounted', () => {
console.log('App is mounted');
});
});
Plugin vs. composable vs. module:
Use a plugin when you need one-time initialization. Use a composable when you need reactive per-call state.
Async plugins:
Plugins can be async. Nuxt awaits them before rendering the app (blocking). Use sparingly for critical initialization; defer non-critical work to nuxtApp.hook('app:mounted', ...):
export default defineNuxtPlugin(async (nuxtApp) => {
await criticalInit(); // blocks SSR render
nuxtApp.hook('app:mounted', () => {
nonCriticalInit(); // deferred to client mount
});
});
Accessing the request event in server plugins:
export default defineNuxtPlugin((nuxtApp) => {
const event = useRequestEvent(); // only valid server-side
const userAgent = getHeader(event, 'user-agent');
});
Plugin execution order with enforce:
enforce: 'pre' — runs before all default pluginsenforce: 'post' — runs after all default pluginsWhen NOT to use:
https://nuxt.com/docs/guide/directory-structure/plugins