The problem every CMS has
Every CMS makes the same bet: hand the client the whole dashboard and hope they don't move a section, pick a neon-green heading, or delete the layout on the way out.
I got tired of taking that bet. So I built Castor — a CMS where you decide exactly what each client can change, and the system enforces it.
The one-liner: Let clients edit. Not break.
They change the words and the photos in the browser. They can't move a section, choose a colour that isn't yours, or touch the code.
Free, open source (AGPL-3.0), self-hosted. Live editor demo: https://castorcms.vercel.app
Most CMSes are binary. This one isn't.
In most tools a field is either editable or it isn't — and "editable" usually means the client gets everything.
Castor is per-capability. Each of these is an independent switch, with its own allowed range:
- text
- images
- links
- text colour
- section colours
- spacing
Any combination is valid. Set it per site, and a single page can override the site's defaults. You're not picking a tier — you're drawing a line exactly where you want it.
| The client may edit | The client may never touch |
|---|---|
| The words, the photos | The layout |
| Links and buttons | The structure |
| Colours you allow | Anything off-brand |
| Spacing you allow | The code |
The part I'm actually proud of: the Guardian
The permission switches are the UI. The enforcement is a separate, deterministic (no AI) policy engine I call the Guardian.
Every edit passes through it before it touches the draft. It validates against the per-capability permissions server-side — so even if the editor UI is wrong, or tampered with in the browser, an out-of-bounds edit still doesn't save.
The rule I held myself to: never trust the client UI alone to prevent an out-of-bounds edit. The line lives on the server.
Draft → Publish → Rollback
Nothing a client does is public until they explicitly publish.
- Edits land in a private draft.
- Publishing snapshots the whole site.
- Rollback moves the live pointer to any past version — one click.
The client can experiment freely; the live site stays exactly as it was until someone presses Publish.
Already have a site? Import it.
Drag a ZIP of HTML/CSS/JS onto the dashboard and it becomes editable. Imported pages render in a sandboxed iframe, so their own JavaScript still runs — but can't reach cookies or another client's site.
How it fits together
YOU (local) MongoDB Atlas YOUR CLIENT (any browser)
Admin dashboard ─build/import─▶ shared database ◀─edit─ /edit/<slug>
- set permissions per site • inline edit, in the page
- master editor, full control • Draft → Publish
│ • can't break the layout
└────────────── public site: your-app/<slug> ──────────────┘
One Next.js app, two modes. Site-building, importing, and structural editing run only locally; the deployed instance serves just the password-gated editor and the public sites. Both share one MongoDB Atlas database, so a site you build on your machine is instantly editable at its hosted link.
Content model: Site → Pages → Sections → Slots. A section is a typed block (hero, text, features, testimonials, faq, gallery, form, cta, footer, or an imported page); a slot is one editable value.
Stack
Next.js 16 (App Router) · TypeScript · Tailwind · MongoDB Atlas · deployed on Vercel. The whole thing runs on free tiers.
Why AGPL, not "source-available"
Because the whole pitch is trust.
Use it, modify it, run it commercially for as many clients as you like — free. The one condition: anything you build on it, including a version you host as a service, stays open under the same licence. You can't take Castor closed-source.
That's deliberate positioning, not just a licence checkbox: it competes with hosted page-builders on cost, and with closed source-available tools on trust.
What it doesn't do (yet)
It's early and does one thing on purpose — guarded content editing for content sites. So, honestly:
- Content sites, not apps. It renders content from a database; it doesn't run your framework. Build your React/Next project first, then import the output.
- Imported ZIP sites are frozen — every word is editable, but they won't restructure or pick up renderer improvements.
- Images are referenced by URL — no built-in upload/host step yet.
- One owner — a single admin password, no team roles yet.
- Undo/redo covers content, not structural changes.
Try it
- Live editor demo: https://castorcms.vercel.app
- Code: https://github.com/emmi-dev12/castor-cms
I'd love feedback on the permission model specifically. If you build sites for clients: where would you want to draw the line — and what's the first thing you'd try to break?

Top comments (0)