Install
No MySQL. No Composer. Drop Forma on a host with PHP 8.1+, pdo_sqlite, and rewrite support.
Source on GitHub
Latest release
git clone https://github.com/Alta-forma/forma-cms.git
cd forma-cms
chmod -R 775 database uploads feeds
php -S localhost:8787 router.php
Open /admin, log in with admin / admin, and change them immediately under Settings → Access.
DreamHost: point the document root at the folder that contains
index.php. Keep
database/ and
uploads/ when you redeploy code. Use Settings → Server to write
.htaccess (Authorization header passthrough is included — DreamHost FastCGI strips it otherwise). Full notes: the
DEPLOY.md in the repo.
Update
After Forma 0.2.0, existing sites update in the admin: Settings → Forma core → Update Forma core. That installs the latest GitHub Release only — never main.
- Does not touch
database/, uploads/, feeds/, fallback/, .htaccess, or license secrets
- Takes an app-file backup first; Rollback is on the same screen
- Download new installs from Releases, not “Code → Download ZIP”
AltaForma publishes with ./tools/release.sh after bumping version.php. Checklist: RELEASE.md.
Admin
The admin is htmx + CodeMirror — sections load into the main pane without a SPA rebuild.
- Pages — HTML/Twig or Markdown, META block for slug + SEO
- Blog — Markdown posts, RSS/JSON feeds
- Podcasts — episodes + iTunes-compatible feed (license unlock)
- Uploads — media library; image fields use Browse / Upload pickers
- Snippets — reusable HTML via shortcodes
- Settings — site, SEO, server, Forma core, Access, backup
Pages & blog
Full HTML documents are served as-is (great for marketing pages). Fragments get a minimal shell. Blog posts are Markdown with publish dates — unpublished posts 404 on purpose.
META block
<!--META
slug: /docs
title: Docs
seo_title: Forma Docs
seo_description: …
-->
Snippets
This docs chrome is snippet-driven so you can reuse nav and footer everywhere:
[[site-head]] — fonts + shared CSS tokens
[[site-header]] — sticky nav / menu
[[site-footer]] — footer links
Edit them under Admin → Snippets. Twig is optional inside snippet bodies if you need site config variables.
SEO
Settings → SEO covers sitewide defaults; pages/posts override per document.
- Auto
/robots.txt and /sitemap.xml (including images)
- Open Graph / Twitter, favicon, default share image
- JSON-LD (Person / Organization / LocalBusiness)
- Redirects manager
- Health score for missing titles, descriptions, images
Podcast
Forma itself is free. Podcast RSS (iTunes-compatible show + episodes) is a $39 one-time unlock.
Buy Forma Podcast — $39. After Stripe emails the key, paste it under Settings → General. Local/dev: FX-DEV-LOCAL.
AI connectors & Agent API
Settings → Access has three clear ways in: an admin login for you, OAuth for compatible AI chatbots, and scoped Bearer API keys for Cursor, scripts, and ChatGPT Actions.
Grok, ChatGPT, Claude, Perplexity
For a remote MCP connector, paste one URL. Forma publishes OAuth discovery, registers the client, and asks you to sign in and approve Site editor access — no token copying.
https://your-site.com/api/v1/mcp
The chatbot grant can read and update content, upload media, update public identity and SEO, and use rollback. It cannot delete, change accounts, import backups, read backups, alter security, or update Forma core. Access tokens last one hour and renew through rotating refresh tokens.
Cursor, scripts, and Actions
Create an API key under Settings → Access when the client cannot do browser-based OAuth. Discover the full API map first:
curl -H "Authorization: Bearer fx_…" \
https://your-site.com/api/v1/help
DreamHost-safe alternate header: X-Forma-Token. Separate read, write, delete, media, settings, backup, podcast, and rollback scopes keep each key as narrow as the job allows.
One last-known-good site
Before the first Agent API or MCP write, Forma protects one rollback point. Settings → Access shows Put it back while edits are pending. After checking the public site, This looks good moves the safe point forward.
Important: rollback is one safety point, not revision history. New orphan uploads can remain after restore. Never mark a site good until a human has checked the public result.
Site packages
Settings → Backup → Download site package, or GET /api/v1/export/site.
manifest.json # format_version + schema_version
data.json # portable content
database/forma.db # SQLite snapshot
uploads/ # media
Future Forma versions migrate using schema_version. Packages newer than the running app are rejected.
Remote & Cursor MCP
Subscription chatbots use the hosted Streamable HTTP endpoint at /api/v1/mcp. Paste the URL and let OAuth handle the credential. The remote tool list is intentionally limited to the non-destructive Site editor surface.
Cursor can use the local MCP wrapper with a scoped API key. Start with formax_help, then pages, posts, snippets, media, SEO, and rollback tools.
export FORMA_X_URL=https://your-site.com
export FORMA_X_TOKEN=fx_…
php tools/formax.php help
php tools/formax.php site
ChatGPT Custom GPT Actions use the public /api/v1/openapi.json contract with a Bearer API key when remote MCP is unavailable.
Screenshots
Live Forma admin — Blog, Podcast, Uploads, Snippets, Cache, and Server.