Project structure and lifecycle
A plugin owns its feature code, selectors, UI descriptions, local assets, tests, and manifest. Its public dependency is @fluxplugs/plugin-api. Do not import runtime, adapter, or Rust internals.
Project layout
Section titled “Project layout”| Location | Purpose |
|---|---|
| fluxplug.json | Identity, capabilities, settings, integrity, and entry path |
| src/index.ts | definePlugin registration and lifecycle |
| Other source files | Your implementation and imported assets |
| dist/index.js | Typical single-file IIFE output |
| releases/ | ZIPs produced by the pack command |
Use definePlugin({ manifest: { id }, start(api), stop() }). The adjacent manifest is authoritative; the SDK definition supplies only the matching ID.
Start and stop
Section titled “Start and stop”Each enable creates an instance in an opaque-origin sandbox. Keep startup short: register features, then launch slower work with error handling. Custom views expose the existing instance rather than starting another one.
Save returned disposer functions and call them in reverse order from stop. Clear your timers and remove your own event listeners. Core also cleans owned resources on disable, reload, failure, and uninstall.
The guide snippets labeled api-example belong inside start(api), with a module-level cleanup: Array<() => void>. Their stop implementation should drain that array in reverse order. Snippets demonstrate one operation at a time; combine capabilities when combining features.
Work that finishes after stop
Section titled “Work that finishes after stop”Track a generation or stopped flag around asynchronous work. After each await, verify that the instance is still current. If a registration resolves after stopping, dispose it immediately instead of saving it for a stop that already happened.
Settings changes currently restart the instance through reconciliation. Read settings in start; there is no settings-change subscription in the public SDK.
Sandbox boundary
Section titled “Sandbox boundary”Your document belongs to your plugin. You cannot read parent.document, use Node/Electron, access the filesystem, or fetch arbitrary remote data. Use the capability-scoped services and handle their rejections.
