Home Architecture Docs Roadmap Pricing GitHub
Architecture source doc updated April 2, 2026

HTMLess architecture for builders who want clarity

This page turns the architecture document into a readable system map: three API surfaces, a PostgreSQL source of truth, Redis for cache and queues, Docker-first deployment, and a monorepo split across admin, API, and worker packages.

Explore the system from the angle you care about

The tabs below are pulled from the architecture document itself, then reorganized into overview, APIs, data model, infrastructure, and codebase views.

Type
Headless CMS

Open source core with room for hosted and SaaS layers on top.

Backend
Node.js + Prisma

The API runtime is in the monorepo core package, backed by PostgreSQL.

Frontend
Next.js Admin

The editing interface lives as a separate app instead of being mixed into the API.

Cache / Queue
Redis

Used for caching, queueing, retries, and rate-limit state.

Tenancy
Multi-space

Shared database with scope-based isolation around spaces, roles, and content.

Deployment
Docker-first

Admin, API, worker, PostgreSQL, and Redis are all part of the deployment story.

Philosophy

UX over feature count

HTMLess is inspired by WordPress-style authoring ergonomics, but without server-rendered theme assumptions. The architecture is meant to make the path from schema to published API feel clean, not overloaded.

  • Schema
  • Content
  • API
  • Preview
  • Publish
Why this shape

Separate concerns, clearer operations

The architecture avoids a one-bucket CMS model. Editors hit CMA, public clients hit CDA, preview uses short-lived access, the worker owns retries, and the database remains the canonical truth.

  • Cleaner mental model for developers and agencies
  • Safer publish semantics than a single all-purpose API
  • A solid base for Phase 9 delivery optimization
CMA

/cma/v1

Write and read surface for editors, admin UI, and automation. Returns drafts, metadata, and versions.

Write / Read
Preview

/preview/v1

Draft-inclusive reads protected by preview tokens so teams can review unpublished changes.

Draft Reads
CDA

/cda/v1

Read-only, published-only, cacheable delivery for public websites, apps, and frontends.

Read-only
Semantics

Three external surfaces, strict behavior

The architecture doc treats the three APIs as contract boundaries, not just route prefixes. That is why preview can be draft-inclusive, CDA can stay public-facing and cacheable, and CMA can remain editor-first.

  • CMA returns draft state, metadata, and versioning detail
  • Preview focuses on safe draft review with scoped access
  • CDA stays published-only and CDN-friendly by design
System links

Where the APIs connect

CMA writes into the content store and emits events. Preview reads drafts. CDA serves published state. The worker consumes async jobs and pushes signed webhooks with retries.

  • Content store and entry state sit behind the APIs
  • Event bus decouples publish actions from side effects
  • Webhook dispatcher owns delivery attempts and status
Identity + Tenancy

Spaces, users, roles, bindings

Spaces define the tenant boundary. Users, roles, and role bindings scope access within each space.

Schema Registry

Content types + fields

Content models live in the database so schemas can evolve without requiring code redeploys.

Content State

Entries, versions, state pointers

Stable entry identity, immutable snapshots, and draft/published pointers define content history and publishing.

Access Tokens

API + preview tokens

Machine tokens and short-lived preview tokens enforce scoped access across public and editorial workflows.

Media + Usage

Assets and asset usages

Media metadata is tracked separately from content, with references recorded for better visibility and control.

Events + Audit

Webhooks and audit logs

Outbound integrations and security-sensitive actions are captured instead of disappearing into the background.

Entry point

Traefik

SSL termination and routing sit in front of the admin and API services.

Frontend

htmless-admin

Next.js admin application served separately from the backend runtime.

Core API

htmless-api

Node.js service exposing CMA, CDA, and Preview APIs.

Async work

htmless-worker

Handles jobs, retries, and webhook dispatch without blocking the API layer.

Primary data

PostgreSQL

Relational datastore for tenancy, schema, content, assets, webhooks, and audit logs.

Transient state

Redis

Cache, queues, invalidation, and rate limiting all live here.

API runtime

packages/core

Route handlers, auth, spaces, schema registry, content lifecycle, media handling, events, webhooks, cache helpers, and utilities.

Async jobs

packages/worker

Jobs, queues, and runners that keep retryable background work out of the request path.

Admin UI

packages/admin

App router, components, feature modules, and client helpers for the editorial interface.

Monorepo shape

Top-level project layout

htmless/
├── docs/
├── packages/core/
├── packages/worker/
├── packages/admin/
├── docker-compose.yml
├── Dockerfile.api
├── Dockerfile.admin
├── Dockerfile.worker
├── package.json
└── pnpm-workspace.yaml
Core package

Important source folders

src/
├── api/ cma/, cda/, preview/
├── auth/ login, tokens, middleware
├── spaces/ tenant scoping
├── schema/ type registry, validation
├── content/ CRUD, versions, publish flow
├── media/ uploads and metadata
├── events/ internal emitters
├── webhooks/ signing and dispatch policy
└── cache/ keys and invalidation

Slides for the parts that matter most

These horizontal flows turn the architecture doc into scan-friendly steps for editors, developers, and anyone trying to understand how the system actually behaves.

Publish path

How content moves from the editor-facing surface toward published delivery and async side effects.

1

Editor UI

Editors work from the admin app and authenticate with a bearer user token.

2

CMA

The content management API handles schema work, drafts, versions, and publish actions.

3

Content store

Entries, immutable versions, and draft/published pointers are updated in PostgreSQL.

4

Preview and CDA

Preview can read draft state while CDA stays published-only and cacheable.

5

Worker and webhooks

Publish events feed the async pipeline for signed webhook delivery and retries.

Database domains

The PostgreSQL model is easier to understand when grouped by responsibility instead of as a raw table list.

A

Spaces + users

Tenant boundary, identity, roles, and membership mappings.

B

Schema registry

Content types and field definitions per space.

C

Entry lifecycle

Stable entries, immutable versions, and state pointers for draft and published content.

D

Assets

Media metadata and usage tracking tied back to content.

E

Events + audit

Webhook config, delivery attempts, and the audit trail for sensitive changes.

Deployment path

A compact version of the system topology from the source document.

1

Internet

Traffic enters through the public edge.

2

Traefik

Routing and SSL termination decide where requests go next.

3

Admin + API

The Next.js admin and Node.js API run as separate services.

4

Worker

Background jobs and webhook retries stay off the request path.

5

PostgreSQL + Redis

Persistent relational data on one side, transient cache and queue state on the other.

Architecture principles worth remembering

PostgreSQL is the source of truth

The architecture is intentionally SQL-first even as Phase 9 pushes delivery closer to document-style speed.

The APIs are product boundaries

CMA, CDA, and Preview are not just technical routes. They represent different behaviors, trust levels, and cacheability rules.

Worker isolation matters

Webhooks and retries belong in the async layer so API responsiveness is not tied to downstream services.