---
title: Plugin Development
description: How to build extensions for ObjectStack
---

# Plugin Development

Plugins are the building blocks of ObjectStack. A plugin is a plain JavaScript/TypeScript object (or class) that conforms to the `Plugin` interface.

## Anatomy of a Plugin

```typescript
import type { Plugin, PluginContext } from '@objectstack/core';

export class MyPlugin implements Plugin {
    // Identity
    name = 'com.example.myplugin';
    version = '1.0.0';
    description = 'An example plugin';
    
    // Dependencies (Optional)
    dependencies = {
        '@objectstack/runtime': '^1.0.0'
    };

    // Configuration Schema (Optional Zod Schema)
    configSchema = z.object({
        apiKey: z.string()
    });

    /**
     * Initialization Phase
     * Use this to register services, listeners, or other early setup.
     */
    async onInit(ctx: PluginContext) {
        // Register a service
        ctx.services.register('myService', new MyService());
    }

    /**
     * Start Phase
     * The system is fully initialized. Use this to start servers or background jobs.
     */
    async onStart(ctx: PluginContext) {
        console.log('MyPlugin started!');
    }
}
```

## Plugin Types

ObjectStack uses `type` discrimination to optimize runtime behavior, allowing the kernel to intelligently handle different kinds of extensions.

### 1. Standard Plugin (`standard`)
*   **Role:** General purpose backend logic (default).
*   **Use Cases:** Registering Services, Hooks, Utilities, or non-UI middleware.
*   **Behavior:** Executed in the Node.js runtime with full access to the Kernel.

### 2. UI Plugin (`ui`)
*   **Role:** Frontend application host.
*   **Use Cases:** Admin Console, Low-code Studio, SPA Dashboard.
*   **Behavior:**
    *   **Passive:** Driven by `plugin-hono-server` (or other HTTP adapters).
    *   **Static Assets:** Must verify `staticPath` pointing to a build output (e.g., `dist/`).
    *   **Routing:** Automatically mounted to `/{slug}` with SPA fallback support.
    *   **Assets:** Files are served locally under `/{slug}/assets`.

### 3. App Plugin (`app`)
*   **Role:** Vertical Business Solution.
*   **Use Cases:** CRM, Project Management, ERP modules.
*   **Behavior:**
    *   Contains rich metadata (Objects, Flows, Reports).
    *   May bundle `ui-plugin` references for custom widgets.
    *   Focuses on business logic rather than infrastructure.

### 4. Driver Plugin (`driver`)
*   **Role:** Infrastructure Connectivity.
*   **Use Cases:** SQL Adaptors (`@objectstack/driver-sql`), Storage (`driver-s3`).
*   **Behavior:** Loaded early in the lifecycle to ensure data availability.

### 5. Server Plugin (`server`)
*   **Role:** Protocol Gateway.
*   **Use Cases:** REST API (`plugin-hono-server`), GraphQL, WebSocket.
*   **Behavior:** Responsible for binding ports and mapping incoming traffic.

### 6. Theme Plugin (`theme`)
*   **Role:** UI Appearance.
*   **Use Cases:** Dark Mode, Enterprise Branding.
*   **Behavior:** Provides CSS tokens and asset overrides to `ui-plugin`s.

### 7. Agent Plugin (`agent`)
*   **Role:** AI Capability.
*   **Use Cases:** RAG Pipelines, Autonomous Agents.
*   **Behavior:** Extensions for the AI Gateway.

## RuntimePlugin Interface Reference

The `RuntimePlugin` interface defines the contract that all functionality modules must implement.

```typescript
export interface RuntimePlugin {
    /**
     * Plugin Unique Identifier
     * Recommended format: com.organization.plugin-name
     */
    name: string;

    /**
     * Plugin Version
     * Must follow Semantic Versioning (SemVer)
     */
    version?: string;

    /**
     * Description
     * Brief explanation of the plugin's purpose.
     */
    description?: string;

    /**
     * Initialization Hook
     * Called during Kernel bootstrap. Use this to:
     * - Register Services
     * - Register Event Listeners
     * - Extend Metadata
     */
    onInit?: (context: PluginContext) => Promise<void>;

    /**
     * Start Hook
     * Called after all plugins are initialized. Use this to:
     * - Start HTTP servers
     * - Connect to databases
     * - Start background workers
     */
    onStart?: (context: PluginContext) => Promise<void>;

    /**
     * Stop Hook
     * Called during Kernel shutdown. cleanup resources here.
     */
    onStop?: (context: PluginContext) => Promise<void>;
}
```
