# Plugin SDK Go module `git.dev.alexdunmow.com/block/pluginsdk`. **Purpose: this is the ONE plugin-facing artifact.** BlockNinja CMS plugins import this module and nothing else from the internal Go tree. Plugins must NOT import the first-party `core` module — core exists only for code shared between first-party entities (cms, orchestrator, ninja CLI). ## The contract is proto, not Go - `abi/proto/v1/*.proto` is **the contract**. The host↔guest wire is proto-only; a plugin in ANY language generates its own bindings from these files. - `abi/v1/` is the **Go** binding of that contract (`abiv1`). The rest of the Go surface here — `plugin/`, `plugin/wasmguest/**`, and the guest-facing type packages — is **one language binding** of the SDK. A non-Go plugin implements the ABI hooks directly and never sees these Go structs. - **The SDK ships no page chrome.** A template renders only its `TemplateDocument`; the **host** composes the document envelope (doctype / `` / `` / `` + bn chrome) around it. Through `templates.PageDocument` a guest supplies the body plus envelope attributes (body class, `lang`, extra `` attributes, and head/body-end extra HTML) — never head/body markup itself. Title, meta, and site chrome are host-authored: the host builds them from the doc map it also hands the guest as `doc_json`. ## Critical Rules - **NEVER use `replace` directives in go.mod** — not here, not in any consumer. All module resolution goes through the Gitea module proxy. To test local changes, tag and push a version. - All consumers are in-house — **no backwards-compatibility shims**. Change the API and update consumers. - Regenerate Go bindings after editing any `.proto`: `make proto`. ## Design Program spec (in the cms repo): `docs/superpowers/specs/2026-07-07-proto-first-plugin-sdk-design.md`.