Creating Your First Plugin
Now that you understand the pieces, building one is refreshingly mechanical — because you don't start from scratch. The intended path is to copy the default plugin and adapt it, then let the plugin loader do the wiring.
The five steps
cp -r plugins/default_plugin plugins/my_thing
- Copy the default plugin to
plugins/{your_slug}/. - Edit
manifest.ts— change the slug, entity name, description, workspace statuses, route prefix, and menu. - Edit
migrations/001_initial.sql— rename the tables and adjust the columns to your domain. - Build out
api/,fe/, andtests/for your entity — using the copied default-plugin code as your starting point. - Start the API. The loader discovers
plugins/my_thing/, validates it, registers the entity, seeds the statuses, and mounts the routes.
That's it — no symlinks, no manual CI/CD changes, no wiring beyond editing files. (The one exception today is frontend route/sidebar registration, which is still added by hand in App.tsx / Layout.tsx.)
A few conventions to get right
entity_slugis lowercase snake_case (my_thing, notMy_Thingormy-thing). It prefixes your tables and drives your migration path.plugins/sits at the repo root, a peer ofapi/andfrontend/; everything about your plugin lives underplugins/{slug}/.- The build is already set up to include plugin code: the API and frontend configs pick up
plugins/*/api/andplugins/*/fe/, and the migration script scansplugins/*/migrations/.
Why copying is the right move
The default plugin is a complete, working reference — a manifest with all four extension points, the full table pattern, workspace statuses, frontend pages, and a test suite. Copying it means you start from something that already runs and already respects the contract, then change it into your domain a piece at a time. It's a boilerplate to copy, not a library to import from — so once you've copied it, it's entirely yours.
When your first run doesn't behave, the troubleshooting guide covers the usual culprits — most of which trace back to the loader's validation checks.