Skip to main content
This guide walks you through creating a minimal FDO plugin from scratch. By the end, you will have a working plugin class that FDO can load.

Prerequisites

Before you start, make sure you have the following installed:
  • Node.js >=18.0.0
  • npm >=9.0.0
  • TypeScript (installed as a dev dependency in your plugin project)

Install the SDK

1

Create your plugin project

Create a new directory and initialize an npm project:
mkdir my-fdo-plugin
cd my-fdo-plugin
npm init -y
npm install --save-dev typescript
2

Install the FDO SDK

npm install @anikitenko/fdo-sdk
3

Write your plugin

Create a plugin.ts file with the following minimal plugin scaffold. This is the canonical starting point for all new plugins:
plugin.ts
import { FDOInterface, FDO_SDK, PluginMetadata } from "@anikitenko/fdo-sdk";

export default class MinimalFixturePlugin extends FDO_SDK implements FDOInterface {
  private readonly _metadata: PluginMetadata = {
    name: "Fixture: Minimal Plugin",
    version: "1.0.0",
    author: "FDO SDK Team",
    description: "Minimal reference fixture for plugin scaffolding",
    icon: "cube",
  };

  get metadata(): PluginMetadata {
    return this._metadata;
  }

  init(): void {
    this.info("Minimal fixture initialized");
  }

  render(): string {
    return `
      <div style={{ padding: "16px" }}>
        <h1>${this._metadata.name}</h1>
        <p>Use this fixture as the baseline for new plugins.</p>
      </div>
    `;
  }
}

new MinimalFixturePlugin();

How the plugin lifecycle works

When FDO loads your plugin, it follows a fixed synchronous lifecycle:
  1. Instantiation — FDO creates an instance of your plugin class. The FDO_SDK constructor runs, registers the plugin with PluginRegistry, and emits an init event to the host.
  2. init() — FDO calls init() once. Use this method to set up initial state, register IPC handlers, and configure storage. Keep init() fast — do not block here.
  3. render() — FDO calls render() to get your plugin’s UI. Return a synchronous string. The SDK serializes this string and sends it to the FDO iframe host pipeline, which mounts it in the sandboxed iframe.
  4. renderOnLoad() (optional) — If you implement renderOnLoad(), FDO serializes its return value and injects it as a script into the iframe after the UI mounts. Use this for post-mount setup that runs in the iframe context.
Both render() and renderOnLoad() must return synchronously. Returning a Promise from either method throws a runtime error. Do not use async on these methods.

Required metadata fields

Every plugin must expose a metadata getter that returns a PluginMetadata object. All fields except id are required:
FieldTypeRequiredDescription
namestringYesDisplay name shown in the FDO plugin list
versionstringYesSemantic version string (e.g., "1.0.0")
authorstringYesPlugin author name
descriptionstringYesShort description of what the plugin does
iconstringYesBlueprintJS v6 icon name (see note below)
idstringNoOptional unique identifier; FDO assigns one if omitted
The icon field must be a valid BlueprintJS v6 icon name — for example, "cube", "cog", "dashboard", or "git-branch". FDO uses BlueprintJS v6 in the host application to render plugin icons. Passing an unrecognized name will result in a missing icon in the UI. You can validate icon names programmatically using the exported isBlueprintV6IconName helper:
import { isBlueprintV6IconName } from "@anikitenko/fdo-sdk";

console.log(isBlueprintV6IconName("cube"));      // true
console.log(isBlueprintV6IconName("not-an-icon")); // false

Next steps

Installation

Full installation reference, TypeScript config, and distribution notes

Plugin lifecycle

Deep dive into how FDO loads, runs, and manages plugins

UI rendering

Build rich UIs with DOM helpers and host-injected libraries

Operator plugins

Build Docker, Kubernetes, Terraform, and other operator panels