Plugins

Backend Plugins

Extend Rasepi's .NET 8 API with custom services, action guards, event handlers, translation providers, and import/export processors.

Overview

Backend plugins run inside the Rasepi API process as loadable .NET assemblies. They have full access to the plugin SDK and can hook into the entry lifecycle, guard actions before they happen, provide translation engines, and more.

dotnet new classlib -n MyPlugin
dotnet add reference path/to/Rasepi.Plugins.SDK.csproj

Plugin SDK

The SDK provides interfaces and base types for building plugins.

IRasepiPlugin

The root interface every plugin must implement.

public class MyPlugin : IRasepiPlugin
{
    public PluginManifest Manifest => new()
    {
        Id = "my-plugin",
        Name = "My Plugin",
        Version = "1.0.0",
        Author = "Your Name"
    };

    public void ConfigureServices(IServiceCollection services)
    {
        // Register your services
    }
}

Plugin Interfaces

IRasepiPlugin

Root plugin interface. Every plugin implements this.

IPluginModule

Register services and middleware in the DI container.

IActionGuard

Intercept and allow/deny operations before they happen.

IPluginEventHandler

React to events after operations complete.

ITranslationProviderPlugin

Provide custom translation engines.

IImportPlugin

Import entries from external formats.

IExportPlugin

Export entries to external formats.

Action Guards

Action guards intercept operations before they happen. Return ActionGuardResult.Allow() or ActionGuardResult.Deny("reason").

public class ComplianceGuard : IActionGuard
{
    public Task<ActionGuardResult> EvaluateAsync(
        ActionGuardContext context)
    {
        if (context.ActionName == ActionNames.DeleteEntry
            && context.Entity is Entry entry
            && entry.IsPublished)
        {
            return Task.FromResult(
                ActionGuardResult.Deny(
                    "Cannot delete published entries"));
        }

        return Task.FromResult(ActionGuardResult.Allow());
    }
}

Available Actions

CreateHub
UpdateHub
DeleteHub
CreateEntry
UpdateEntry
DeleteEntry
PublishEntry
CreateTranslation
UpdateTranslation
RenewEntry
UpdateExpiry

Event Handlers

Event handlers react after operations complete. Use them for notifications, audit logging, cache warming, and integrations.

public class SlackNotifier : IPluginEventHandler
{
    public async Task HandleEventAsync(
        string eventName,
        IPluginContext context,
        object? payload)
    {
        if (eventName == "entry.published")
        {
            await _slack.PostAsync(
                $"New entry published: {payload}");
        }
    }
}

Translation Providers

Implement ITranslationProviderPlugin to add custom translation engines (DeepL, Google Translate, AI-based, etc.).

public class DeepLProvider : ITranslationProviderPlugin
{
    public string ProviderId => "deepl";
    public string DisplayName => "DeepL";

    public Task<IReadOnlyList<string>>
        GetSupportedLanguagesAsync()
        => Task.FromResult<IReadOnlyList<string>>(
            new[] { "en", "de", "fr", "es", "ja" });

    public async Task<TranslationBatchResult>
        TranslateAsync(
            IReadOnlyList<string> blocks,
            string sourceLanguage,
            string targetLanguage,
            TranslationOptions? options = null)
    {
        // Call DeepL API for each block
    }
}

Import / Export

Implement IImportPlugin and IExportPlugin for custom format support (Word, Notion, Markdown, etc.).

public class MarkdownExporter : IExportPlugin
{
    public string FormatId => "markdown";
    public string DisplayName => "Markdown";
    public string FileExtension => ".md";

    public Task<byte[]> ExportAsync(
        Entry entry,
        IPluginContext context)
    {
        // Convert TipTap JSON blocks to Markdown
    }
}

Deployment

Build your plugin as a .NET class library and place the DLL in the Plugins/ directory. Rasepi loads plugins automatically on startup.

dotnet build -c Release
cp bin/Release/net8.0/MyPlugin.dll ../backend/Rasepi.Api/Plugins/

Configure in appsettings.json:

{
  "Plugins": {
    "AutoLoadDirectory": "Plugins",
    "Enabled": ["my-plugin"]
  }
}