install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/nuxt-plugins-pattern" ~/.claude/skills/intense-visions-harness-engineering-nuxt-plugins-pattern-e60ca3 && rm -rf "$T"
manifest:
agents/skills/codex/nuxt-plugins-pattern/SKILL.mdsource content
Nuxt Plugins Pattern
Extend the Nuxt application instance, register global services, and provide values to composables using defineNuxtPlugin
When to Use
- You need to register a third-party Vue plugin (e.g., a component library, analytics SDK, i18n)
- You need to provide a global helper or service accessible via
useNuxtApp().$myHelper - You want to run initialization code once when the app starts (client or server)
- You need to initialize something only on the client (browser APIs) or only on the server
Instructions
- Create files in
— they are automatically registered. Files are named without registration inplugins/
:nuxt.config.ts
// plugins/my-plugin.ts export default defineNuxtPlugin((nuxtApp) => { // runs on both server and client });
- Register Vue plugins by calling
: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 }); });
- Provide values accessible throughout the app via
: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');
- Augment TypeScript types for provided values:
// types/nuxt.d.ts declare module '#app' { interface NuxtApp { $analytics: AnalyticsClient; } } declare module 'vue' { interface ComponentCustomProperties { $analytics: AnalyticsClient; } } export {};
- Restrict execution to client-only by naming the file
:.client.ts
// plugins/crisp-chat.client.ts export default defineNuxtPlugin(() => { // runs only in the browser window.$crisp = []; window.CRISP_WEBSITE_ID = 'your-id'; });
- Restrict execution to server-only by naming the file
:.server.ts
// plugins/db-connection.server.ts export default defineNuxtPlugin(async () => { await connectDatabase(); });
- Control plugin execution order using numeric prefixes or the
property:order
// 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) { /* ... */ }, });
- Access other plugins or Nuxt context within a plugin via the
argument:nuxtApp
export default defineNuxtPlugin((nuxtApp) => { nuxtApp.hook('app:mounted', () => { console.log('App is mounted'); }); });
Details
Plugin vs. composable vs. module:
- Plugin — runs once at app startup; registers global functionality or third-party integrations
- Composable — called per-component, per-request; encapsulates reactive logic
- Module — build-time extension; modifies Nuxt/Nitro configuration, adds files, extends auto-imports
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
— runs before all default pluginsenforce: 'pre'
— runs after all default pluginsenforce: 'post'- Numeric filename prefix (01, 02...) — controls order within the same enforce group
When NOT to use:
- Per-request initialization — use server middleware instead
- Business logic shared between components — use composables instead
- Build-time configuration — use Nuxt modules instead
Source
https://nuxt.com/docs/guide/directory-structure/plugins
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.