The maintained Notes example shows all three plugin surfaces in one package.
It uses monorepo workspace: and catalog: dependencies. Use it inside the
Sero monorepo unless you port its complete manifest to published dependencies:
Use this index to find the smallest relevant example.
For an external repository, use the maintained Kanban starter and its setup guide.
| Task | File |
|---|---|
| Define the Pi, app, and plugin manifests | package.json |
| Set runtime ABI 2 and required host capabilities | package.json |
| Define JSON-serialisable state and defaults | shared/types.ts |
| Register a tool, command, and CLI metadata | extension/index.ts |
| Read and write state from the React UI | ui/NotesApp.tsx |
| Call a plugin tool from the UI | ui/NotesApp.tsx |
| Create and clean up long-running behavior | runtime/index.ts |
| Contribute a static Dashboard widget | package.json and ui/widgets/NotesWidget.tsx |
| Register a widget for the renderer session | ui/NotesApp.tsx |
| Expose the app and widget through Module Federation | vite.config.ts |
| Isolate plugin CSS | ui/styles.css and vite.config.ts |
The manifest uses component names without ./. The Vite exposes map uses
keys with ./:
NotesApp.tsx and NotesWidget.tsx each have a default React component export.
Each directly exposed entry also imports styles.css. The Vite configuration
uses base: './' for production and seroPluginCssScope() after Tailwind.
For UI and extension only, remove runtime/, the runtime manifest field, the
appRuntime.background capability, and runtime typecheck entries. For an
extension-only plugin, also remove ui/, vite.config.ts, app UI fields,
widgets and other contributions, Module Federation exposes, and UI build or
typecheck entries.
Follow Plugin Quickstart for the complete first journey. Use Plugin Extension Points for the contribution schema and lifecycle rules.