Быстрый старт
Пошаговое руководство на базе reference-расширения project-notes (packages/extensions/project-notes/).
1. Структура пакета
my-extension/
extension.manifest.mjs # id, targets, contributes
package.json
vite.config.ts # ahExtensionFrontendViteConfig
tsconfig.json
src/
backend/index.ts # опционально
frontend/index.ts # опционально
frontend/components/
ai/index.ts # опционально
dist/ # build output (gitignored)
*.zip # архив (gitignored)2. package.json
json
{
"name": "@artiroute/ext-my-feature",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "extension-build --root .",
"dev": "extension-build --root . --no-pack"
},
"peerDependencies": {
"@artiroute/extension-sdk": "workspace:*",
"primevue": "^4.4.1",
"vue": "^3.5.22",
"vue-router": "^4.6.0"
},
"devDependencies": {
"@artiroute/extension-build": "workspace:*",
"@artiroute/extension-sdk": "workspace:*",
"@vitejs/plugin-vue": "^5.2.4",
"typescript": "^5.8.3",
"vite": "^7.1.7",
"vue": "^3.5.22"
}
}Добавьте пакет в packages/extensions/my-extension/ — workspace подхватит его автоматически.
3. Манифест
js
// extension.manifest.mjs
export const extensionManifest = {
id: '@artiroute/my-feature',
name: 'My Feature',
version: '1.0.0',
extensionApi: '1',
targets: {
backend: {},
frontend: {},
ai: {},
},
contributes: {
ext: {
extendsRegistries: [
{ registryId: 'app.sidebar', keys: ['my-feature'] },
{ registryId: 'app.routes', keys: ['my-feature'] },
],
},
},
};Каждый key в extendsRegistries должен совпадать с ключом в register() внутри setup(). Подробнее: Манифест.
4. vite.config.ts (frontend)
ts
import { fileURLToPath } from 'node:url';
import { ahExtensionFrontendViteConfig } from '@artiroute/extension-build';
import { extensionManifest } from './extension.manifest.mjs';
const root = fileURLToPath(new URL('.', import.meta.url));
export default ahExtensionFrontendViteConfig({ root, manifest: extensionManifest });5. Frontend entry
ts
import { defineExtension, getExtensionRegistry } from '@artiroute/extension-sdk/extension';
export default defineExtension(() => {
getExtensionRegistry('app.sidebar').register('my-feature', {
label: 'My Feature',
icon: 'pi pi-star',
to: '/ext/my-feature',
});
getExtensionRegistry('app.routes').register('my-feature', {
path: '/ext/my-feature',
name: 'ext:my-feature',
component: MyPage,
layout: 'default',
meta: { title: 'My Feature' },
});
});6. Сборка и установка
bash
# из корня monorepo
pnpm build:extensions
pnpm install:extensionsinstall:extensions распаковывает .zip (или копирует dist/) в apps/backend/data/extensions/<slug>/.
7. Проверка
- Перезапустите backend (
pnpm backend:dev) — миграции и Feathers поднимутся при bootstrap - Запустите frontend (
pnpm frontend:dev) — sidebar и routes подхватятся из реестра - Для AI target —
pnpm ai:dev
Расширение должно появиться в UI (sidebar, маршрут и т.д. в зависимости от зарегистрированных реестров).
8. Scaffold из примера
Самый быстрый путь — скопировать packages/extensions/project-notes/ и заменить id, keys и компоненты.
См. также:
- Пример project-notes
- Frontend: host-модули — что можно импортировать
- Troubleshooting