3.5 KiB
| name | description |
|---|---|
| developing-blockninja-plugins | Use when creating, modifying, building, or publishing BlockNinja CMS plugins or themes — work in plugins/* repos, plugin registration, blocks, templates, plugin Connect services, migrations, ninja plugin commands, check-safety for plugins, or block/core SDK usage in standalone plugin repos. |
Developing BlockNinja Plugins
Overview
Never write plugin code from memory — every SDK symbol is locally verifiable. Truth lives at:
- SDK source:
~/src/blockninja/core— import prefixgit.dev.alexdunmow.com/block/core/...is the ONLY one allowed; neverblock/cms/... - Canonical guide:
~/src/blockninja/cms/docs/PLUGIN_DEVELOPMENT.md - Publish workflow + hard rules:
~/src/blockninja/plugins/CLAUDE.md - Exemplars:
plugins/messenger(compact),plugins/symposium(service-heavy: RPC, jobs, AI, embeddings)
Core-vs-plugin: platform-wide behavior → core; domain-specific or owns its own data/UI → plugin (decision table in PLUGIN_DEVELOPMENT.md).
Doc routing
| Working on | Read first (under cms/docs/) |
|---|---|
Scaffold, registration, blocks, CoreServices |
PLUGIN_DEVELOPMENT.md |
| Public HTTP routes (webhooks, widgets) | PLUGIN_HTTP_HANDLERS.md |
| Load/Unload, runtime state, goroutines | PLUGIN_LIFECYCLE_HOOKS.md |
| Themes, templates, master pages, CSS | TEMPLATE_PLUGINS.md |
| Block editor / settings UI (Module Federation) | PLUGIN_EDITOR_SDK.md |
| .so build pipeline, loader internals | compiled-plugin-architecture.md |
| Release, registry, install | plugins/CLAUDE.md (not cms/docs) |
Verifying SDK symbols
Before using an unfamiliar SDK call, check: (1) the pinned SDK the build compiles against — go doc git.dev.alexdunmow.com/block/core/plugin CoreServices from the plugin dir; (2) nearest exemplar usage in messenger/symposium; (3) the CMS-side implementation in cms/backend for semantics.
Missing capability ⇒ two sanctioned paths only: extend block/core (long-term; needs SDK release + re-pin + image rebuild), or vendor the cms-internal package into the plugin's internal/ with a provenance header (established convention — check-safety vendors cms internal/theme this way). NEVER replace directives; NEVER block/cms imports.
Version pinning: go.mod pins block/core to exactly what the CMS uses:
grep 'block/core ' ~/src/blockninja/cms/backend/go.mod
Gates — run before commit / bump / publish
make # CGO build; templ/sqlc drift surfaces here
cd ~/src/blockninja/check-safety && go run . <plugin-path> # MUST exit 0
make archive-check # proves `git archive HEAD` (= what publish ships) compiles
check-safety traps: plugin web/ lint extends ../../../cms/web/eslint.config.js, so it only runs from the canonical sibling layout; raw <button> in plugin UI fails (use @block-ninja/ui Button); any usage warns.
Release traps
ninja plugin bump patch # commits plugin.mod — does NOT git-tag
git tag vX.Y.Z # manual; must equal plugin.mod version (hard rule 6)
git push origin main vX.Y.Z # explicit — --follow-tags skips lightweight tags
ninja plugin publish # ships `git archive HEAD`: untracked files DON'T ship;
# web/dist and ALL generated Go must be committed
New plugin: ninja plugin init, minimal files per PLUGIN_DEVELOPMENT.md §Minimal Layout, copy the Makefile from messenger. First publish lands private; review via orchestrator dashboard.