Skip to content

Plugin Module

Your bundle's default export is a PluginModule — the lifecycle the host calls on you. Wrap it in definePlugin() so TypeScript types the object correctly.

definePlugin

method

definePlugin(mod: PluginModule): PluginModule

An identity helper that types your module as a PluginModule. Use it as the default export of your entry file.

export default definePlugin({ activate, render, deactivate })

PluginModule

type

The lifecycle contract. Only render is required.

interface PluginModule {
  /** Called once after the manifest is verified, before the first render(). */
  activate?(host: RBrowserHost): void | Promise<void>
  /** Mount UI into the container. Called whenever the host panel re-mounts. */
  render(container: HTMLElement, host: RBrowserHost): void | Promise<void>
  /** Called when the plugin is unloaded. Must release resources. */
  deactivate?(): void | Promise<void>
}
Hook When Notes
activate? Once, after the manifest is verified and before the first render. Good place for one-time setup; receives the RBrowserHost.
render Every time the panel mounts. You own the container's contents. Mount your UI (e.g. a React root) here.
deactivate? On unload. Release resources — unmount roots, remove listeners, clear timers.

A typical React entry stores the root so render can remount cleanly and deactivate can tear down:

import * as ReactDOM from 'react-dom/client'
import { definePlugin } from '@rbrowser/plugin-sdk'

let root: ReactDOM.Root | null = null

export default definePlugin({
  activate(host) {
    console.log('[my-plugin] activate', host.info)
  },
  render(container, host) {
    if (root) root.unmount()
    root = ReactDOM.createRoot(container)
    root.render(<App host={host} />)
  },
  deactivate() {
    if (root) { root.unmount(); root = null }
  }
})

Permission

type

The capabilities a plugin can request in its manifest. The host bridge is scoped to the granted set — calling an API you didn't request is a no-op.

type Permission =
  | 'state:read'        // getState / subscribe / all read hooks
  | 'navigation:write'  // host.navigate(...)
  | 'highlight:write'   // host.highlight.add / remove / clear
  | 'storage:write'     // host.storage.get / set / remove / keys / clear

See the Host Bridge for what each permission unlocks.