Work
ClientClient · Custom product
Brainstorming

Brainstorming CMS

A custom editorial CMS: an API in Hono on Cloudflare Workers and an Angular admin, with block editing, autosave, history and preview.

View live site

Screenshot of Brainstorming CMS
SYSTEM.md

The problem

The editorial team needed to publish guides and articles across several sites without asking for code changes, and with control over who can edit what.

What I built

I built two independent repositories: an API in Hono on Cloudflare Workers (Drizzle, PostgreSQL and an OpenAPI contract) and an Angular admin with a rich-text and block editor.

Outcome

A custom CMS with history, a file library and per-site publishing status.

Decisions that mattered

  1. 01

    The contract rules

    Routes are defined with Zod schemas that validate input and generate OpenAPI 3.1. Angular imports a versioned copy of the contract and generates its types from it.

  2. 02

    Autosave without losing changes

    It saves after a 1.2-second pause. On a conflict or an error it stops retrying and keeps the local changes.

  3. 03

    Restore without publishing

    History restores a version as a draft; what is published doesn’t change until you publish again.

  4. 04

    Access by invitation

    A single administrator and editors with permissions. Only the Supabase publishable key reaches the browser.

Technologies

  • Angular
  • Hono
  • Cloudflare Workers
  • PostgreSQL
  • Drizzle
  • OpenAPI
  • Supabase

C4 model. The pulsing line is the main path of a request.

Level 1 · who uses the system and what it connects to

HTTPS1Deploy · content API2JWTHTTPSEditorial teamWrites and publishesBrainstorming CMSGuides and articlesBrainstorming sites[Astro · Vercel]Receive what is publishedSupabase Auth[Supabase Auth]User identityResend[Resend]Invitation emails

Level 2 · the applications and data stores it is made of

HTTPS1REST ·OpenAPI ·2JWT · joseR2 APISQL · HyperdriveDeploy · content API3React EmailEditorial teamWrites and publishesAdmin app[Angular 22 · Cloudflare Pages]Block editor and previewResend[Resend]Invitation emailsCMS API[Hono · Cloudflare Workers]OpenAPI contract generatedfrom ZodBrainstorming sites[Astro · Vercel]Receive what is publishedSupabase Auth[Supabase Auth]User identityFile library[Cloudflare R2]PDFs and imagesDatabase[PostgreSQL · Supabase ·Hyperdrive]Content, history and users

Level 3 · the components inside the API

calls1rulesport2JWT · jose3portSQL ·HyperdriveportR2 APIportVercel APIHono routes[Hono · @hono/zod-openapi]Validate input with ZodApplicationservices[Application services]Identity, content, filesand publishingDomain[Result · errors]Result and applicationerrorsIdentity adapter[jose]Verifies the JWTsSupabase Auth[Supabase Auth]User identityRepository[Drizzle]Queries with DrizzleDatabase[PostgreSQL · Supabase ·Hyperdrive]Content, history and usersFiles adapter[R2 binding]Uploads and serves by UUIDFile library[Cloudflare R2]PDFs and imagesPublisher[Vercel API]Triggers and confirmsbuildsBrainstorming sites[Astro · Vercel]Receive what is published
  • Person
  • System
  • Container
  • Database
  • External
  • Main path
  1. 01Editor
  2. 02Angular admin
  3. 03Hono API
  4. 04PostgreSQL
  5. 05Per-site publishing

CV

Get my CV

Leave your email and I will send the CV there. First I check the address is yours with a code.