Architecture Overview
How the InlineCMS monorepo is structured and how the pieces fit together.
Monorepo structure
Section titled “Monorepo structure”packages/ types/ Shared TypeScript interfaces — the system contract core/ InlineCMSClient, ContentStore, ComponentRegistry, AuthManager react/ InlineCMSProvider, useCMS, useAuth, InlineElements, withCMS, CMSToolbar vue/ InlineCMSPlugin, useCMS, useAuth, CMSField, defineInlineComponent vite-plugin/ Build-time JSX transform + SHA1 fingerprint injection babel-plugin/ Same transform for non-Vite toolchains
apps/ api/ Hono API + Drizzle ORM + PostgreSQL dashboard/ React management UI docs/ Starlight documentation (this site) demo/ Demo app for testing the SDK
docker/ Dockerfile Multi-stage production build docker-compose Self-hosted setup with PostgreSQLCore SDK classes
Section titled “Core SDK classes”InlineCMSClient
Section titled “InlineCMSClient”Handles all HTTP. Routes content fetches to CDN for visitors and directly to the API for editors (bypassing cache so they always see drafts).
ComponentRegistry
Section titled “ComponentRegistry”Tracks every mounted CMS component on the page. Debounced sync to the backend (300ms) prevents request floods during initial render.
ContentStore
Section titled “ContentStore”In-memory cache of field values with optimistic local updates. setField() writes locally immediately; persistence is async. Re-fetches content after login and after component sync.
AuthManager
Section titled “AuthManager”CMS session lifecycle. Persists to sessionStorage (survives page refresh, cleared on tab close). Notifies subscribers on login/logout.
Content flow
Section titled “Content flow”Write path
Section titled “Write path”Editor publishes → API saves to PostgreSQL (status: published) → CDN cache invalidated via webhook → Content history record written (audit trail)Read path
Section titled “Read path”Visitor request → CDN edge (~5ms) → Cache miss → API → PostgreSQL → Response cached at edge
Editor request → API directly (bypass CDN) → Returns drafts + publishedAuth model
Section titled “Auth model”Editors are invited into a project and authenticate with InlineCMS directly
(email + password, Argon2-hashed, JWT session). Each editor has a role
(admin / editor / viewer) and, optionally, a set of allowedPaths that scopes
which page URLs they may edit (glob wildcards supported, e.g. /blog/*).
To edit a live page, an editor signs into the admin and “enables editing” on a site, which mints a short-lived, single-use, origin-bound handoff token that the page redeems for an editor session. InlineCMS does not integrate with or depend on the host application’s own user system.
Database
Section titled “Database”Core tables, managed by Drizzle ORM:
| Table | Purpose |
|---|---|
organizations | Optional ownership grouping above projects (tenancy seam) |
projects | Top-level tenant with API key and domains |
cms_users | Editor accounts with roles + optional URL scoping |
sessions | Server-side JWT tracking for invalidation |
handoff_tokens | Single-use, origin-bound tokens for live-page editor access |
pages | Registered pages (path + title) |
component_definitions | Field schemas registered by the SDK |
content_entries | Actual content (draft/published/archived) |
content_history | Immutable publish audit trail |
media | Uploaded files |