Skip to content

Development

github-actions[bot] edited this page Oct 26, 2026 · 3 revisions

Plugin Development Guide

This guide covers how to create custom nself plugins.

🚨 READ FIRST: Mandatory Standards

BEFORE developing a plugin, you MUST read and follow Standards.

Key requirements:

  • ✅ ALL tables must use np_ prefix
  • ✅ ALL plugins must use source_account_id for multi-app isolation
  • ✅ Use one of 13 official categories only
  • ✅ Plugin names must be lowercase-with-hyphens

Failure to comply will result in automated build failures.


Plugin Structure

Every plugin follows this structure:

plugins/<name>/
├── plugin.json           # Plugin metadata (required)
├── cmd/                  # Go service or CLI entry point (required)
├── migrations/           # Embedded SQL migrations, applied at boot (required for plugins with tables)
├── schema/
│   └── tables.sql        # Database schema reference
├── Dockerfile
└── docker-compose.plugin.yml

A plugin ships a binary. The CLI never runs per-plugin install.sh, uninstall.sh, actions/*.sh or webhooks/**/*.sh scripts, and the repository carries none. Install, upgrade and removal go through nself plugin install|upgrade|remove; migrations run when the service starts. Start from nself plugin new and follow Plugin Development.

Creating a Plugin

1. Create Plugin Directory

mkdir -p plugins/my-service/{cmd,migrations,schema}

2. Create plugin.json

The manifest file describes your plugin:

{
  "name": "my-service",
  "version": "1.0.0",
  "description": "Integration with My Service",
  "author": "Your Name",
  "license": "MIT",
  "minNselfVersion": "0.4.8",
  "category": "integrations",
  "tags": ["my-service", "integration"],

  "tables": [
    "np_myservice_items",
    "np_myservice_webhooks"
  ],

  "webhooks": {
    "item.created": "Sync new items",
    "item.updated": "Update item data"
  },

  "actions": {
    "sync": "Sync all data",
    "items": "Manage items"
  },

  "envVars": {
    "required": ["MYSERVICE_API_KEY"],
    "optional": ["MYSERVICE_WEBHOOK_SECRET"]
  },

  "multiApp": {
    "supported": true,
    "isolationColumn": "source_account_id",
    "pkStrategy": "uuid",
    "defaultValue": "primary"
  },

  "config": {
    "port": 4000,
    "webhookPath": "/webhooks/my-service"
  }
}

Key Points:

  • ⚠️ Tables MUST start with np_ prefix
  • ⚠️ Category must be one of 13 official categories
  • ⚠️ multiApp.isolationColumn MUST be source_account_id

3. Create Database Schema

Create schema/tables.sql:

-- ⚠️ IMPORTANT: ALL tables MUST use np_ prefix and include source_account_id

CREATE TABLE IF NOT EXISTS np_myservice_items (
    id UUID PRIMARY KEY,
    source_account_id VARCHAR(255) NOT NULL,  -- REQUIRED for multi-app
    name VARCHAR(255) NOT NULL,
    data JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    synced_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS np_myservice_webhooks (
    id UUID PRIMARY KEY,
    source_account_id VARCHAR(255) NOT NULL,  -- REQUIRED for multi-app
    type VARCHAR(100) NOT NULL,
    data JSONB NOT NULL,
    processed BOOLEAN DEFAULT FALSE,
    received_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Indexes for multi-tenant queries
CREATE INDEX IF NOT EXISTS idx_np_myservice_items_account
    ON np_myservice_items(source_account_id);

CREATE INDEX IF NOT EXISTS idx_np_myservice_items_name
    ON np_myservice_items(name);

CREATE INDEX IF NOT EXISTS idx_np_myservice_webhooks_account
    ON np_myservice_webhooks(source_account_id);

Schema Requirements:

  • ⚠️ Table name MUST start with np_
  • ⚠️ MUST include source_account_id VARCHAR(255) NOT NULL
  • ⚠️ MUST add index on source_account_id
  • Use UUID for primary keys (recommended)
  • Include created_at and synced_at timestamps

Testing Your Plugin

1. Install Locally

nself plugin install ./plugins/my-service

2. Test Actions

nself plugin my-service sync
nself plugin my-service items list

3. Test Webhooks

# Send test webhook
curl -X POST http://localhost/webhooks/my-service \
    -H "Content-Type: application/json" \
    -d '{"type":"item.created","item_id":"123","name":"Test"}'

Publishing

  1. Update version in plugin.json
  2. Create git tag: git tag my-service-v1.0.0
  3. Submit PR to nself-plugins repository

Best Practices

  1. Idempotent syncs - Running sync twice should produce same result
  2. Upsert data - Use ON CONFLICT for database inserts
  3. Handle errors gracefully - Log errors, don't crash
  4. Validate input - Check required fields exist
  5. Use transactions - For multi-table operations
  6. Rate limit awareness - Respect API rate limits
  7. Incremental sync - Support syncing only changes

Examples

See the Stripe plugin for a complete implementation example.

CI

Which checks run on a pull request is described in CI scope.

nself-plugins

Start

Commands

Architecture

Plugin Ecosystem

Popular Plugins

View All: Home (or see the full alphabetical list below — 129/129 synced with registry.json)

All Free Plugins

Guides

Operations


Related

Clone this wiki locally