Skip to content

Manifest API Reference

interface PluginManifest {
// Identification
slug: string;
name: string;
version: string;
description?: string;
author?: string;
// Classification
category?: 'productivity' | 'communication' | 'analytics' | 'integration' | 'utility';
tags?: string[];
// Availability
businessTypes?: BusinessType[];
premiumTiers?: string[];
// Extensions
extensions: ExtensionRegistration[];
// Server Integration
serverRouter?: (t: any) => any;
// Lifecycle Hooks
handlers?: {
onEnable?: () => Promise<void>;
onDisable?: () => Promise<void>;
onInstall?: () => Promise<void>;
onUninstall?: () => Promise<void>;
};
// UI Configuration
settingsComponent?: React.ComponentType<any>;
icon?: React.ComponentType<any>;
}
  • Type: string
  • Required: Yes
  • Description: Unique identifier for the plugin (kebab-case)
  • Example: 'timer', 'task-manager', 'ai-insights'
  • Type: string
  • Required: Yes
  • Description: Display name shown in UI
  • Example: 'Time Tracker', 'Task Manager'
  • Type: string
  • Required: Yes
  • Description: Semantic version number
  • Example: '1.0.0', '2.1.3-beta'
  • Type: string
  • Required: No
  • Description: Brief description of plugin functionality
  • Example: 'Track time spent on work units and projects'
  • Type: string
  • Required: No
  • Description: Plugin author or organization
  • Example: 'Aether Team', 'john@example.com'
  • Type: 'productivity' | 'communication' | 'analytics' | 'integration' | 'utility'
  • Required: No
  • Description: Primary category for organization
  • Example: 'productivity'
  • Type: string[]
  • Required: No
  • Description: Searchable tags for discovery
  • Example: ['time-tracking', 'billing', 'reporting']
  • Type: BusinessType[]
  • Required: No
  • Default: [] (all business types)
  • Description: Which business types can use this plugin
  • Example: ['SERVICE', 'PROJECT'] or [] for all
  • Type: string[]
  • Required: No
  • Default: [] (all tiers)
  • Description: Required premium tier for access
  • Example: ['PREMIUM', 'ENTERPRISE']
  • Type: ExtensionRegistration[]
  • Required: Yes (can be empty)
  • Description: Array of extension registrations
  • See: Extension Points Reference
extensions: [
{
point: 'work-unit.detail.tabs',
plugin: 'my-plugin',
priority: 50,
match: {
businessType: ['SERVICE']
},
extension: {
type: ExtensionType.TAB,
id: 'my-tab',
label: 'My Tab',
icon: IconExample,
component: MyTabComponent,
}
}
]
  • Type: (t: any) => any
  • Required: No
  • Description: tRPC router factory for plugin API endpoints
  • Example:
serverRouter: (t) => t.router({
getData: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return await fetchData(input.id);
}),
saveData: t.procedure
.input(z.object({ id: z.string(), data: z.any() }))
.mutation(async ({ input }) => {
return await saveData(input.id, input.data);
}),
})
  • Type: () => Promise<void>
  • Required: No
  • Description: Called when plugin is enabled by user
  • Use Cases: Initialize resources, set up listeners, migrate data
onEnable: async () => {
console.log('Plugin enabled');
await initializeDatabase();
}
  • Type: () => Promise<void>
  • Required: No
  • Description: Called when plugin is disabled by user
  • Use Cases: Clean up resources, remove listeners, archive data
onDisable: async () => {
console.log('Plugin disabled');
await cleanupResources();
}
  • Type: () => Promise<void>
  • Required: No
  • Description: Called once when plugin is first installed
  • Use Cases: Run database migrations, create default data
onInstall: async () => {
await runMigrations();
await createDefaultSettings();
}
  • Type: () => Promise<void>
  • Required: No
  • Description: Called when plugin is uninstalled
  • Use Cases: Remove plugin data, clean up database
onUninstall: async () => {
await removePluginData();
}
  • Type: React.ComponentType<any>
  • Required: No
  • Description: Custom settings UI component
  • Example:
settingsComponent: function PluginSettings({ config, onChange }) {
return (
<Stack>
<Switch
label="Enable notifications"
checked={config.notifications}
onChange={(e) => onChange({ notifications: e.target.checked })}
/>
</Stack>
);
}
  • Type: React.ComponentType<any>
  • Required: No
  • Description: Icon component for plugin (from @aether/ui/icons)
  • Example: icon: IconClock
import { definePlugin, ExtensionType } from '@aether/plugins-core';
import { IconClock } from '@aether/ui/icons';
import { TimerTab } from './components/TimerTab';
import { timerRouter } from './server/router';
export const timerPlugin = definePlugin({
// Identification
slug: 'timer',
name: 'Time Tracker',
version: '1.2.0',
description: 'Track time spent on work units and projects',
author: 'Aether Team',
// Classification
category: 'productivity',
tags: ['time-tracking', 'billing', 'reporting'],
// Availability
businessTypes: ['SERVICE', 'PROJECT'],
premiumTiers: [],
// Extensions
extensions: [
{
point: 'work-unit.detail.tabs',
plugin: 'timer',
priority: 70,
match: {
businessType: ['SERVICE', 'PROJECT']
},
extension: {
type: ExtensionType.TAB,
id: 'time-entries',
label: 'Time Tracking',
icon: IconClock,
component: TimerTab,
badge: (context) => context?.timeEntryCount
}
}
],
// Server Integration
serverRouter: timerRouter,
// Lifecycle Hooks
handlers: {
onEnable: async () => {
console.log('Timer plugin enabled');
},
onDisable: async () => {
console.log('Timer plugin disabled');
},
},
// UI Configuration
icon: IconClock,
});