Plugin Creation Guide
Plugin Creation Guide
This guide creates a simple welcome-banner plugin that adds a dashboard page and a new sidebar item.
Step 1: Create Folder Structure
mkdir -p plugins/welcome-banner/pages/dashboard/welcome-banner
mkdir -p plugins/welcome-banner/components
Step 2: Create Layer Configuration
Create plugins/welcome-banner/nuxt.config.ts:
export default defineNuxtConfig({
imports: {
dirs: ['stores']
}
})
imports.dirs is optional. Use it when the plugin has a stores/ folder or other auto-import folders.
Step 3: Create Plugin Configuration
Create plugins/welcome-banner/plugin.config.ts:
import type { PluginConfig } from '../../shared/types/plugin'
export default {
enabled: true,
routes: [
{
key: 'welcome-banner',
path: '/dashboard/welcome-banner',
icon: 'i-heroicons-megaphone',
label: 'Welcome Banner'
}
]
} satisfies PluginConfig
The routes field is the source for static sidebar menu items. The path should match the page you create.
Step 4: Create Plugin Page
Create plugins/welcome-banner/pages/dashboard/welcome-banner/index.vue:
<template>
<main class="space-y-4">
<WelcomeBanner />
</main>
</template>
Step 5: Create Component
Create plugins/welcome-banner/components/WelcomeBanner.vue:
<template>
<section class="rounded-lg border border-primary-200 bg-primary-50 p-6">
<h1 class="text-xl font-semibold text-primary-950">
Welcome to the LMS
</h1>
<p class="mt-2 text-primary-700">
This page comes from a plugin loaded as a Nuxt Layer.
</p>
</section>
</template>
Step 6: Add Dynamic Sidebar (Optional)
If the plugin needs to add child menu items from an API, create plugins/welcome-banner/sidebar.ts:
import { defineSidebarProvider } from '../../shared/types/menu'
export default defineSidebarProvider(({ route }) => {
if (!route.path.startsWith('/dashboard/welcome-banner')) {
return []
}
return [
{
key: 'welcome-banner',
path: '/dashboard/welcome-banner',
icon: 'i-heroicons-megaphone',
label: 'Welcome Banner',
source: 'plugin',
pluginId: 'welcome-banner',
children: [
{
key: 'welcome-banner.settings',
path: '/dashboard/welcome-banner/settings',
icon: 'i-heroicons-cog-6-tooth',
label: 'Settings',
source: 'plugin',
pluginId: 'welcome-banner'
}
]
}
]
})
Because the key matches the static route item, this item will be merged and the child menu will appear under Welcome Banner.
Replacing a Core
If this plugin should replace a core, add replaces:
export default {
enabled: true,
replaces: ['program'],
routes: [
{
key: 'welcome-banner',
path: '/dashboard/welcome-banner',
icon: 'i-heroicons-megaphone',
label: 'Welcome Banner'
}
]
}
When active, the program core will not be loaded by auto-discovery.
Verification
Run:
pnpm dev
Open /dashboard/welcome-banner. If enabled: true, the plugin will be loaded as a layer and the sidebar item will appear from plugin.config.ts.
