Getting started

Introduction

A headless CMS an AI can run end to end over MCP, with structure and pages stored as data.


@interactive-inc/cms is a headless CMS library for Cloudflare Workers (D1 + R2). Collections, their fields, documents, and the pages that present them all live in D1, so changing the structure needs no migration. An AI agent connected over MCP can operate the whole site right after deploy.

Code holds the kinds, data holds the combinations

The boundary is deliberate. Code fixes what kinds of things exist; D1 holds how they are combined and what they contain.

  • In code: the field types, the hook kinds, the access mechanism, the built-in collections for pages, layouts, menus, and the site and theme globals, the MCP tools, and the host's component catalog.

  • In D1: user-defined collection definitions (cms_collections), documents as JSON (cms_documents), page specs, layouts, menus, site settings, and theme tokens.

  • A new kind of feature is a code change that goes through a pull request. A new collection or field is a data change that goes through a proposal.

Who does what

  • Structure changes are saved as proposals and applied only when an admin approves them. Admins go through the same path.

  • Editors, and AI agents holding editor API keys, write drafts and request review. Admins publish.

  • Every interface goes through the same engine and the same access checks: the REST API, the MCP server, and server-side loaders.

What is built in

  • Draft and live copies per document, review workflow, revisions and restore

  • Scheduled publishing, document-level localization, full-text search (FTS5 trigram)

  • Media on an R2-compatible bucket, API keys with roles, a durable outbox with signed webhooks

  • Pages as json-render specs with data queries, layouts with an Outlet, menus, and theme tokens

  • A stateless MCP server with 31 tools and three resources

This site is itself built with it on Void: the page you are reading is a document in a docs collection, rendered by a page spec stored in pages.