Building Extensions
Smart Panel supports a plugin architecture that lets you extend both the backend (NestJS) and the admin UI (Vue.js) with custom functionality. Extensions are distributed as npm packages.
Overview
An extension is an npm package that declares one or both of these manifests in its package.json:
fastybird.smartPanelBackend— a NestJS module mounted at a route prefixfastybird.smartPanelAdmin— a Vue 3 plugin loaded into the admin interface
Smart Panel discovers installed extensions automatically by scanning node_modules for packages with these manifests.
Quick Start
The easiest way to get started is to use the example extension as a template.
Clone the example
The packages/example-extension/ directory in the Smart Panel repository contains a fully working extension with
both backend and admin components.
cp -r packages/example-extension my-extension
cd my-extensionPackage manifest
Your package.json must include the fastybird field with your extension manifests:
{
"name": "@my-org/my-extension",
"version": "1.0.0",
"fastybird": {
"smartPanelBackend": {
"kind": "plugin",
"routePrefix": "my-extension",
"extensionExport": "MyExtensionModule"
},
"smartPanelAdmin": {
"kind": "plugin",
"extensionEntry": "admin/index.js"
}
}
}The kind field can be "module" or "plugin". Modules are mounted at /api/<routePrefix>, while plugins are
mounted at /api/plugins/<routePrefix>.
Backend Extension
A backend extension is a standard NestJS module. It can define controllers, services, and entities just like any other module in the system.
Module definition
import { Module, OnModuleInit } from '@nestjs/common';
import { MyController } from './my.controller';
import { MyService } from './my.service';
@Module({
controllers: [MyController],
providers: [MyService],
})
export class MyExtensionModule implements OnModuleInit {
onModuleInit() {
console.log('My extension loaded');
}
}Controller
import { Controller, Get } from '@nestjs/common';
import { ApiExcludeController } from '@nestjs/swagger';
@ApiExcludeController()
@Controller()
export class MyController {
@Get('status')
getStatus() {
return {
name: 'my-extension',
ok: true,
timestamp: new Date().toISOString(),
};
}
}With routePrefix: "my-extension" and kind: "plugin", this endpoint will be available at
GET /api/plugins/my-extension/status.
Configuration DTO
Extensions can accept configuration through the plugin config system:
import { IsBoolean, IsOptional } from 'class-validator';
import { UpdatePluginConfigDto } from '@fastybird/smart-panel-backend';
export class MyConfigDto extends UpdatePluginConfigDto {
@IsOptional()
@IsBoolean()
enabled?: boolean;
}Admin Extension
An admin extension is a Vue 3 plugin that gets installed into the admin application.
Plugin entry point
Create an assets/index.ts file (or wherever your extensionEntry points after build):
import type { App } from 'vue';
export default {
install(app: App) {
// Register components, routes, or provide services
// app.component('MyWidget', MyWidget);
},
};Build configuration
Use Vite to build the admin entry as an ESM library:
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: 'assets/index.ts',
formats: ['es'],
fileName: 'index',
},
outDir: 'admin',
rollupOptions: {
external: ['vue'],
},
},
});Manifest Reference
Backend manifest (fastybird.smartPanelBackend)
| Field | Type | Required | Description |
|---|---|---|---|
kind | "module" | "plugin" | Yes | Route mounting strategy |
routePrefix | string | Yes | URL path segment(s) |
extensionExport | string | Yes | Named export of the NestJS module class |
sdkVersion | string | No | Compatible SDK version |
displayName | string | No | Human-readable name |
description | string | No | Short description |
Admin manifest (fastybird.smartPanelAdmin)
| Field | Type | Required | Description |
|---|---|---|---|
kind | "module" | "plugin" | Yes | Plugin type |
importPath | string | No | Module specifier for static import |
extensionExport | string | No | Named export (if not using default export) |
extensionEntry | string | No | ESM entry point for runtime loading |
sdkVersion | string | No | Compatible SDK version |
displayName | string | No | Human-readable name |
description | string | No | Short description |
Installing Your Extension
Once published to npm (or a private registry), install it into your Smart Panel:
npm install @my-org/my-extensionRestart the backend and the extension will be discovered and loaded automatically.
For local development, you can use npm link or a pnpm workspace to link your extension package directly.
What’s Next?
- Browse the example extension source code
- Read the Plugins Overview to understand existing plugins
- Check the API Reference for available backend services you can integrate with