Everything You Need to Build
Modern Content Platforms
FlameCMS is not another bolted-together headless CMS. Every design decision — from the Fastify runtime to the plugin-first architecture — is deliberate and documented here.
Six Design Principles
The opinionated choices that make FlameCMS different — and why we made them.
Code-First, Not GUI-First
FlameCMS is designed for developers, not non-technical users poking around a drag-and-drop interface. Every schema, plugin, hook, and configuration lives in TypeScript files that you commit, review, and version-control like any other part of your application.
This means your CMS setup is reproducible. Clone the repo, run the installer, and your entire content model is restored in seconds — no database exports, no manual reconfiguration.
The entire API surface is typed end-to-end. Your content types generate TypeScript interfaces automatically, so your frontend enjoys full autocomplete and compile-time safety without writing a single type by hand.
// flamecms.config.ts — your schema is just TypeScript
import { defineConfig } from 'flamecms'
export default defineConfig({
contentTypes: [
{
name: 'BlogPost',
fields: {
title: { type: 'string', required: true },
slug: { type: 'slug', from: 'title' },
body: { type: 'richtext' },
tags: { type: 'relation', to: 'Tag', many: true },
published: { type: 'boolean', default: false },
},
},
],
})Plugin Everything
Authentication, email, image processing, search, caching, analytics — none of these ship in the core. They are first-class plugins installed from npm, giving you full control over your dependency tree.
Every internal system in FlameCMS exposes hooks: before-save, after-save, before-delete, on-auth, on-request, and dozens more. Plugins can intercept any lifecycle event and modify behavior without forking the codebase.
Writing your own plugin takes minutes. Export a FlameCMSPlugin object, declare your hooks, and publish to npm. The ecosystem grows because the bar to contribute is intentionally low.
// plugins/audit-log/index.ts
import type { FlameCMSPlugin } from 'flamecms'
export default {
name: '@acme/audit-log',
version: '1.0.0',
hooks: {
'content:afterCreate': async ({ doc, user, ctx }) => {
await ctx.db.insert('audit_logs', {
action: 'create',
collection: doc._type,
docId: doc._id,
userId: user.id,
ts: new Date(),
})
},
},
} satisfies FlameCMSPluginOwn Your Data
FlameCMS is 100% self-hosted. Your PostgreSQL database, your server, your rules. There are no usage-based pricing tiers, no vendor lock-in, and no phone-home telemetry unless you explicitly enable it.
All content is stored in standard PostgreSQL tables with predictable, documented schemas. You can query your data directly with any SQL client, connect BI tools like Metabase or Grafana, or export to any format you need — zero proprietary formats.
The licensing is MIT. Use it in commercial projects, fork it, modify it, redistribute it. Your CMS investment belongs to you.
# Your data in plain PostgreSQL — always accessible
psql $DATABASE_URL
\dt flame_*
# flame_users flame_sessions
# flame_content_posts flame_content_tags
# flame_media flame_audit_logs
SELECT title, published_at
FROM flame_content_posts
WHERE published = true
ORDER BY published_at DESC
LIMIT 10;Performance Obsessed
The FlameCMS API server is built on Fastify, the fastest Node.js HTTP framework available. A cold-start benchmark on a standard $6/month VPS delivers over 18,000 API requests per second with sub-10ms median latency.
Response caching is built into the plugin system. Install @flamecms/cache-redis and every GET endpoint is cached transparently with automatic cache invalidation on write — zero code changes required.
Database queries are generated by a query builder that avoids N+1 patterns by default. Relations are fetched with a single JOIN rather than multiple round-trips, and you can inspect every query via the built-in query logger.
# Benchmark — 4 vCPU, 8GB RAM VPS
wrk -t4 -c100 -d30s http://localhost:3001/api/posts
Running 30s test @ http://localhost:3001/api/posts
4 threads and 100 connections
Thread Stats Avg Stdev Max
Latency 4.92ms 1.84ms 38.21ms
Req/Sec 4.82k 312.15 5.21k
Requests/sec: 19,283.44
Transfer/sec: 12.47MBSecurity by Default
Every API endpoint requires authentication unless you explicitly mark it public. Role-based access control is built into the core — not bolted on via a plugin. Roles and permissions are defined in code and enforced at the query layer, not just the route layer.
FlameCMS ships with OWASP-aligned defaults: bcrypt password hashing, JWT with short expiry and refresh token rotation, rate limiting on auth endpoints, SQL injection protection via parameterised queries, and CSRF protection for cookie-based sessions.
Content-level permissions let you restrict not just access to a collection but which fields a role can read or write. A "editor" role can update body but not the published flag; an "author" role can only see their own drafts.
// Role-based field-level permissions
{
role: 'editor',
collections: {
posts: {
read: ['*'], // all fields
create: ['title', 'body', 'tags'],
update: ['title', 'body', 'tags'],
delete: false, // cannot delete
},
},
}
// Author can only see their own content
{
role: 'author',
collections: {
posts: {
read: { filter: { author: '{{user.id}}' } },
create: ['title', 'body'],
update: { filter: { author: '{{user.id}}' } },
},
},
}Convention over Configuration
FlameCMS ships with sensible defaults for routing, media storage, CORS, caching headers, and database connection pooling. You can override anything, but you rarely need to. A production-ready API is running in under 5 minutes.
The project structure is prescribed. Content types go in content-types/, plugins go in plugins/, media goes through the built-in upload handler. This predictability means a new team member can navigate any FlameCMS project without a tour.
The CLI scaffolding tool generates content types, plugins, migrations, and test stubs from the command line. You describe what you want; the framework generates the boilerplate.
# Scaffold a new content type in seconds
npx flamecms generate content-type Article
? Fields: title(string), slug(auto), body(richtext),
author(relation:User), tags(relation:Tag,many)
✔ Created content-types/article.ts
✔ Generated migration migrations/0012_add_article.sql
✔ Updated flamecms.config.ts
✔ Created tests/content-types/article.test.ts
Run `flamecms migrate` to apply the schema change.Core Engine Modules
Six independent subsystems — each replaceable, each extensible.
Content Engine
- ✓ Dynamic content types via config (no code-gen required)
- ✓ Rich text editor with custom block support
- ✓ Draft / published / scheduled workflow
- ✓ Revision history and diff viewer
- ✓ Nested relations (one-to-many, many-to-many)
- ✓ Field-level validation with custom rules
- ✓ Soft delete with trash bin
Auth System
- ✓ Local auth with bcrypt + JWT + refresh tokens
- ✓ OAuth2 via @flamecms/auth-oauth (GitHub, Google, etc.)
- ✓ Magic link / passwordless via @flamecms/auth-magic
- ✓ Two-factor authentication (TOTP / SMS)
- ✓ Fine-grained RBAC with field-level permissions
- ✓ Session management and forced logout
- ✓ API key management for headless access
i18n Engine
- ✓ Per-field locale configuration
- ✓ Fallback chain (e.g. zh-TW → zh → en)
- ✓ Locale-aware URL routing (/en/blog, /zh/blog)
- ✓ Content translation workflow with completeness indicator
- ✓ Import/export translations (XLIFF, PO, JSON)
- ✓ Automatic machine translation via plugin
- ✓ Multi-currency support for commerce fields
SEO Engine
- ✓ Auto-generated meta tags per content type
- ✓ OpenGraph and Twitter Card support
- ✓ XML sitemap generated automatically
- ✓ Canonical URL management
- ✓ robots.txt configuration via config file
- ✓ Structured data (JSON-LD) generation
- ✓ Readability and keyword density hints
Plugin System
- ✓ Full lifecycle hooks (30+ events)
- ✓ Extend admin UI with custom React/Vue panels
- ✓ Add custom API routes under /api/plugins/:name
- ✓ Inject middleware into the Fastify server
- ✓ Custom field types with validation and UI
- ✓ Plugin-to-plugin communication via event bus
- ✓ Sandboxed plugin config with schema validation
Unified API
- ✓ REST API auto-generated for every content type
- ✓ GraphQL schema auto-generated (opt-in)
- ✓ Full OpenAPI 3.1 spec with Swagger UI
- ✓ Cursor-based and offset pagination
- ✓ Deep filtering: ?where[tags][name][$eq]=nuxt
- ✓ Sort, select fields, populate relations in one request
- ✓ Rate limiting, request logging, CORS — all configurable
How Does It Compare?
An honest look at where FlameCMS stands relative to Strapi, Payload, Directus, Contentful, and Ghost.
| Feature | FlameCMS | Strapi | Payload | Directus | Contentful | Ghost |
|---|---|---|---|---|---|---|
| Open Source / MIT | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| Self-hosted | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| TypeScript-first config | ✓ | — | ✓ | — | — | — |
| Fastify runtime | ✓ | — | — | — | — | — |
| PostgreSQL native | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| Built-in i18n | ✓ | ✓ | — | ✓ | ✓ | — |
| Plugin architecture | ✓ | ✓ | — | — | — | ✓ |
| Field-level permissions | ✓ | ✓ | ✓ | ✓ | — | — |
| GraphQL (optional) | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| Auto OpenAPI spec | ✓ | — | — | ✓ | — | — |
| Revision history | ✓ | — | — | ✓ | ✓ | — |
| CLI scaffolding | ✓ | ✓ | — | — | — | — |
| No usage-based pricing | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| Scheduled publishing | ✓ | — | — | — | ✓ | ✓ |
Based on publicly available documentation as of early 2025. Features may have changed.
Built for Performance
Fastify is the fastest Node.js HTTP framework. FlameCMS uses it as the runtime — not as a detail, but as a foundation.
$ wrk -t4 -c100 -d30s http://localhost:3001/api/posts?limit=20
Running 30s test @ http://localhost:3001/api/posts?limit=20
4 threads and 100 connections
Thread Stats Avg Stdev Max
Latency 4.92ms 1.84ms 38.21ms
Req/Sec 4.82k 312.15 5.21k
Requests/sec: 19,283.44
Transfer/sec: 12.47MB
# With @flamecms/cache-redis (Redis cache, cache-hit path):
Latency 0.81ms 0.22ms 6.14ms
Req/Sec 38.21k 1.04k 40.12k
Requests/sec: 152,841.22Ready to see it in action?
Spin up FlameCMS in 5 minutes and build something real.