Your whole site is one file you can read. Content types, pages, logic, access, integrations — declared, not scattered across a plugin directory and a database nobody wants to open.
Edit it three ways, and they are the same edit:
- In the admin, as forms — no YAML in sight.
- In files, with
fcms— review it in a pull request like any other change. - With an AI assistant, which proposes a change you approve or reject.
Same validation, same history, same undo, whichever door the change came through.
content:
- key: booking
label: Booking
fields:
- { name: name, type: text, required: true }
- { name: when, type: datetime }
- { name: state, type: state, values: [pending, confirmed, done] }📖 Building a site — from nothing to a published site.
🔧 How it works — the data model, what filterable
compiles to, and where to look when something is wrong.
Longer tour and reference: https://fcms.kickjs.app
Node 22 or newer. Nothing else.
npx @forinda/fcms-cli init my-site && cd my-site
npm install
npm run devinit writes a site you can already run — valid, canonical, and accepted by
every other command without being fixed first. To serve it for real:
OWNER_EMAIL=you@example.com OWNER_PASSWORD=a-long-enough-password npm startThat is the whole install. Postgres runs inside the process — the real
thing, compiled to WebAssembly — and keeps its data in ./.fcms. No database to
obtain, no container, no connection string, and a backup is cp -r.
It migrates and provisions itself on boot, so the first run lands on a working site at http://localhost:8080.
The embedded database belongs to one process at a time, and a second one is refused rather than allowed to corrupt it. Already have a Postgres, or outgrown one process? Same command, one variable:
DATABASE_URL=postgres://… npx @forinda/fcms-coreSame schema and same migrations either way, so moving between them is
pg_dump and nothing else. There is a Docker Compose file too, in
install/.
npm install -g @forinda/fcms-cli
fcms dev # preview a site directory locally, no server needed
fcms plan # what publishing would change
fcms apply # publish itplan and apply show you the change before making it, and refuse anything
destructive unless you say --yes.
The same doors, over MCP. Point any MCP client at a linked site directory:
{
"mcpServers": {
"fcms": { "command": "npx", "args": ["-y", "@forinda/fcms-mcp"] }
}
}It reads the credentials fcms login already wrote, and every change it makes
goes through the same validate → diff → classify → gate path as the admin and
the CLI, with an inverse recorded. An agent cannot reach the database, and it
cannot make a change a person cannot see or undo.
The spec and its language, the renderer, the admin with its visual canvas, the CLI, the MCP server for agents, and the install. On top of those, a business that takes bookings has the whole path: availability by appointment or by date range, distance, multi-step booking journeys, deposits, automations that confirm and notify, and visitors who see their own bookings and nobody else's.
Being found is part of that and needs no setup: titles, canonicals, Open Graph,
sitemap.xml with a lastmod per page, llms.txt, JSON-LD from the content
type's own shape, and an automatic 301 when a page moves. Details in
GUIDE.md.
Worth knowing before you rely on it:
- The M-Pesa and messaging providers are written against documented APIs but have never been run against a live account. The product says so where they are used; payment at the counter needs no account at all.
- Plugins have a contract (
@forinda-cms/plugin) but no marketplace. Installing one is a dependency and a deploy, reviewed — not a button. - There is no hosted service. Self-host it, or run it for your clients.
pnpm install
pnpm dev # the engine, with HMR
pnpm verify # typecheck, lint, format, schema, every test — exactly what CI runsThe database suites skip themselves when DATABASE_URL is unset, so this stays
runnable on a laptop with no Postgres. pnpm --filter @forinda-cms/engine seed
loads the reference site in examples/salon.
One calendar-versioned tag publishes the image, the server package and the CLI,
all carrying the same number. RELEASE.md has the detail.
Issues and pull requests are welcome — CONTRIBUTING.md has
the workflow, and .agents/AGENTS.md the framework
conventions. Open an issue before a large change; it saves you writing a patch
the design cannot take.
AGPL-3.0-or-later for the product — the engine, the admin, the renderer and
the fcms CLI. Self-host it, modify it, run it for clients. The one obligation:
if you run a modified version that other people reach over a network, publish
your changes.
Apache-2.0 for the interop surface — @forinda-cms/spec,
@forinda-cms/lang, @forinda-cms/sdk and @forinda-cms/plugin. The file
format, the client and the plugin API are meant to be copied.
Your specs, content, themes and plugins are yours; nothing here claims them.
A commercial licence is available for anyone the AGPL does not suit —
LICENSING.md has the detail, including what the AGPL actually
asks of you (for most people: nothing).