Skip to content

Plugins

Plugins#

Otok ships a typed plugin API for official extensions and app-specific integrations. Plugins are optional — existing composition packages and manual createOtokApp({ configure }) wiring continue to work.

Quick start#

pnpm otok add hello

Or manually in otok.config.ts:

// otok.config.ts
import { defineConfig } from "@kamod-ch/otok";
import hello from "@kamod-ch/otok-plugin-hello";

export default defineConfig({
  plugins: [hello()],
});

Wire resolved runtime config in src/server.ts:

import { createOtokApp, readOtokManifest } from "@kamod-ch/otok/server";
import { loadOtokResolvedConfig } from "virtual:otok-config";
import { routes, notFoundRoute, errorRoute } from "virtual:otok-routes";

const { runtime, applyAppPlugins } = await loadOtokResolvedConfig();

export default createOtokApp({
  routes,
  notFoundRoute,
  errorRoute,
  ...runtime,
  manifest: readOtokManifest(import.meta.url),
  configure: (app) => {
    void applyAppPlugins(app);
  },
});

Apps without otok.config.ts keep working. virtual:otok-config resolves to an empty config.

Hook order#

Plugins run in declared order:

  1. Option validation (schema)
  2. config
  3. configResolved
  4. configureVite
  5. configureServer (dev)
  6. buildStart / buildEnd
  7. configureApp (runtime)

buildEnd runs in reverse order.

Public vs internal API#

Public Internal
defineConfig, definePlugin PluginContainer internals
OtokPlugin, OtokUserConfig config file bundling
virtual:otok-config generated temp config bundles
virtual:otok-plugin/<name>/<id> devtools metadata (reserved)

Packages#

Package Purpose
@kamod-ch/otok-config Plugin contract and resolution
@kamod-ch/otok-plugin-hello Minimal example plugin
@kamod-ch/otok-plugin-fixture Test fixture plugin

See also Create your first Otok plugin, CLI — otok add, and Composition Packages.