Feature Deep Dive

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.

Developer Experience

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.

example
// 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 },
      },
    },
  ],
})
🔌
Extensibility

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.

example
// 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 FlameCMSPlugin
🏠
Self-Hosted

Own 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.

example
# 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;
🚀
Speed

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.

example
# 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.47MB
🔒
Security

Security 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.

example
// 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}}' } },
    },
  },
}
📐
Productivity

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.

example
# 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.

FeatureFlameCMSStrapiPayloadDirectusContentfulGhost
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.

19,283
Requests / sec
4 vCPU VPS, 100 connections
4.9ms
Median latency
p50, uncached list endpoint
38ms
p99 latency
under sustained 100 req/s
820ms
Cold start
Node.js 20, 512MB RAM
benchmark — wrk -t4 -c100 -d30s
$ 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.22

Ready to see it in action?

Spin up FlameCMS in 5 minutes and build something real.