A complete content-system stack for delivering full web apps to boas.dev clients — authoring, storage, delivery, framework, and hosting layers. Vendor evaluation across four candidates against twelve axes, with material findings from current vendor state.
Database-first headless CMS, self-hosted on Docker, BSL 1.1 licensed but effectively free at agency scale ($5M revenue threshold). Wins on schema flexibility, lock-in escape, API surface, file handling, and overall stack alignment. Pairs cleanly with the existing Cloudflare R2 storage layer and supports IS-first localization with the draft+preview+manual-publish workflow required for the brand voice.
Full picture of what gets adopted, not just the CMS choice. Each layer answers one question; together they cover the lifecycle from author → store → deliver → render.
pg_dump is the export story. No proprietary content format. Schema lives in raw SQL.aws-s3 file driver (S3-API compatible). $0.015/GB storage, $0 egress. CMS file field owns referential integrity; R2 owns bytes.Each axis scored 1–5. The CMS choice is one decision; the surrounding stack is a separate decision. This matrix evaluates the four shortlist candidates strictly on CMS capability + adoption posture.
| # | Axis | Directus | Payload | Strapi | Sanity |
|---|---|---|---|---|---|
| 1 | Authoring UX | 4 | 4 | 4 | 5 |
| 2 | Schema flexibility | 5 | 5 | 4 | 5 |
| 3 | API surface | 5 | 4 | 5 | 4 |
| 4 | File handling (R2 via S3) | 5 | 5 | 4 | 3 |
| 5 | Self-host posture | 4 | 4 | 4 | 1 🚩 |
| 6 | Vendor risk | 4 | 2 🚩 | 3 | 4 |
| 7 | Total cost (self-host scale) | 5 | 5 | 4 | 3 |
| 8 | Lock-in cost | 5 | 4 | 3 | 2 |
| 9 | Front-end integration | 4 | 5 | 4 | 5 |
| 10 | Multi-tenant pattern | 3 | 3 | 2 | 4 |
| 11 | Time-to-first-app | 4 | 5 | 4 | 5 |
| 12 | Stack alignment (Docker · Postgres · S3) | 5 | 4 | 3 | 2 |
| Σ / 60 | 53 | 50 | 43 | 43 | |
Four firecrawl-confirmed findings from current vendor state. Two are licensing / trajectory pivots that reshape the conventional rankings.
Self-hosting is free below the $5M annual revenue threshold. BSL converts to GPL 3 years after each release date. For any agency operating below the threshold, Directus is functionally MIT-equivalent. Commercial fallback path exists from Monospace Inc if scale crosses the line.
Payload joined Figma. Cloud has paused deployment of new projects; existing Cloud customers must eventually migrate. Open-source MIT core is "committed to maintain" per the announcement, but the roadmap is now subject to Figma's product strategy rather than CMS-product DNA. Self-host of the OS core remains viable; reserve as plan B only.
Community Edition keeps MIT, RBAC, custom roles + permissions, REST + GraphQL, unlimited usage, and full content management. Enterprise Edition (quote-based) walls SSO, audit logs, review workflows, Strapi AI, and content history. Strapi Cloud Growth $45/mo. Less aggressive walling than competitor folklore suggests — but multi-tenant pattern remains historically weak.
Free tier is genuinely generous: 20 seats, 10k documents, 1M API requests/month. Growth is $15 per seat per month org-scoped, not per-project — so a 5-seat org pays $75/mo regardless of project count. Cost ceiling reachable for small agencies but managed-only model conflicts with self-host preference. Useful as authoring-UX reference, not as primary tier.
Six cells scored 5/5. Pinned strengths against the brief:
pg_dump. Migration to a future vendor is "rewrite the app layer on the same schema" rather than "rewrite schema + content + queries." Lowest lock-in among the candidates.
aws-s3 driver works against R2 out of the box via S3-API compatibility. CMS file field owns the upload UX + RBAC + referential integrity; R2 owns the bytes. Bunny CDN sits in front unchanged.
Eight other candidates considered and dropped, with one-line reasons.
Each client web app gets a dedicated Docker pair: Directus + Postgres, isolated on a shared VPS alongside sibling services. Content authors work in the Directus admin — drafts, revisions, IS / EN per-field translations, role-gated publish. File uploads flow through the Directus file field into Cloudflare R2 via the aws-s3 driver, with Bunny CDN as the hot-path edge. The front-end — Astro for content-heavy clients, Next.js for app-heavy clients — consumes Directus via REST or GraphQL through the official SDK. Image transforms route through Cloudflare Images when added; video routes through Bunny Stream when added. Backup is pg_dump on a daily cadence plus R2 bucket versioning. Upgrades happen per client on independent windows because the per-client isolation pattern decouples them.