About
The open-source alternative to Webflow, Framer and WordPress. Agentic self-hosted visual CMS outputting clean static pages. Users, roles, plugins, content, data
A modern website usually means assembling a stack: a headless CMS, a framework, a host, a form service, an analytics vendor, an image CDN — each with its own bill, dashboard, and 2 a.m. outage. Instatic is the opposite bet. One Bun server holds the whole thing — the canvas editor, the content engine, media, auth, forms, plugins, and the publisher — and you run it wherever you like, backed by SQLite or Postgres.
What comes out the other end is the part most builders quietly compromise on: plain semantic HTML and compact CSS, with none of the editor's machinery left behind in the page. No framework runtime, no builder attributes, no div soup. The site loads like a static file because, most of the time, it is one.
**MIT. Self-hosted. Yours.**
## Deploy in one click
Railway is the fastest way to get Instatic live. Pick a template, hit the button, wait about two minutes. That's it. It generates the secret keys, attaches the storage volume, and sets up the health checks on its own. You never open a terminal.
| Provider | Database | Best for | Deploy |
|---|---|---|---|
| **Railway** · *Recommended* | SQLite | A single site — blog, portfolio, small business | [Deploy →](https://railway.com/deploy/instatic-cms-sqlite?referralCode=Zm9bVJ&utm_medium=integration&utm_source=template&utm_campaign=generic) |
| **Railway** | Postgres | Multiple authors, managed backups, room to grow | [Deploy →](https://railway.com/deploy/instatic-cms-postgres?referralCode=Zm9bVJ&utm_medium=integration&utm_source=template&utm_campaign=generic) |
| **Render** | SQLite or Postgres | Teams that prefer Render services, disks, and managed Postgres | [Guide →](docs/deployment/render.md) |
| **Docker / VPS** | SQLite or Postgres | Bring-your-own server, Caddy TLS, custom backup policy | [Guide →](docs/deployment/vps.md) |
SQLite is the right default for most sites. Reach for Postgres when you've got a team of authors or want managed database backups.
### Updating is just a redeploy
When a new Instatic version is available, update by redeploying the latest image. Your database and uploads stay on the attached storage, so the app container can be replaced without rebuilding the site from scratch.
Prefer your own hardware? Instatic is a single Docker image:
```sh
INSTATIC_IMAGE=ghcr.io/corebunch/instatic:latest docker compose -f compose.prod.yml -f compose.sqlite.yml up -d
```
Full guides for VPS, Postgres, HTTPS with Caddy, Render, and backups are in [docs/deployment](docs/deployment/README.md).
## One tool, the whole life of a site
Most tools do one job and hand you off for the rest. You design in one place, build in another, keep content somewhere else, then bolt analytics on from a fourth. Instatic does all of it. Here's what's actually in the box.
### Design
The editor is a real canvas, not a form with a preview pane stapled to it. You put several breakpoint frames side by side and edit them together. Change the desktop and the mobile frame reacts in the same view. When you'd rather work on the real thing, flip to live mode and edit a single full-size page in place.
The part nobody else has: **[Core Framework](https://coreframework.com) is built in.** It's the design-token engine thousands of WordPress pros already use every day, and here it's a core system, not a plugin you install and pray over.
- **Color tokens that generate their own shade scale.** Define one brand color, get the full set of tuned tints and shades automatically.
- **Type scales that are fluid and mathematical.** One ramp that scales with the viewport, instead of forty hand-picked font sizes you have to keep in sync.
- **Spacing scales** so every page and every breakpoint keeps the same rhythm.
- **A utility-class generator** that emits locked, generated classes into one small `framework.css`. No bloat, no duplicate rules, nothing you didn't ask for.
Your whole design system lives as data. Change one token and every page that uses it updates.
### Build
- **Modules** are the building blocks: containers, text, images, buttons, video, lists, links, SVG, forms. Drag them onto the canvas and nest them however you want.
- **Visual Components** are reusable pieces with typed parameters and named slots. A parameter can be a string, number, boolean, color, image, URL, rich text, an enum, or a whole slot of content. Edit the component once and every instance on the site updates. Components that would reference themselves are blocked before they happen, so nothing eats its own tail.
- **Templates** handle the shared chrome. One layout for the whole site, separate layouts per post type, and a real 404 page you design yourself. Content flows into an outlet, so a header and footer get written once and wrap everything.
- **Loops** repeat a layout over a collection: your posts, your pages, your media, or anything a plugin exposes as a source. Give a loop a couple of variants and it alternates between them as it goes. Good for post lists, product grids, galleries.
- **Forms that belong to your CMS.** Build a form out of semantic fields and the submissions land in your own data tables. Instatic can read the fields you placed and create the matching table for you. No third-party form service, no embed, no monthly fee for a contact form.
- **An AI agent that actually edits the page.** Describe what you want and it builds it on the canvas as real, editable nodes, not a screenshot or a wall of code. It writes semantic HTML for structure and CSS for style, through the same import pipeline you use when you paste markup. A 35-tool Site scope builds pages; a 15-tool Content scope edits entries. Bring your own model: Claude, OpenAI, OpenRouter, or local Ollama. Your key, your model, your bill.
- **Imports that hold up.** Paste raw HTML and get editable nodes. Or drop a whole static site — HTML, CSS, images, fonts — and Super Import turns it into pages, style rules, design tokens, and media. Every conflict is shown to you before anything is written, and the entire import is a single undo.
### Manage
- **One content model under everything.** Pages, posts, components, custom collections, and any structured table you invent all live in the same store: `data_tables` and `data_rows`. There's no special-cased "pages" table hiding in a corner. Schemas, raw rows, imports, exports, and form submissions all sit in one consistent place.
- **A Data workspace where you design your own collections.** At `/admin/data` you create custom post types and custom data tables with their own fields, then work the rows in a spreadsheet-style grid: search, sort, filter, bulk publish, bulk export. Custom post types come with a real editorial workflow — draft, scheduled, published — and version history on the published copy. Plain data tables are simple grids you can point at anything: the submissions from a form, a product catalog, a lightweight CRM, a list of testimonials. And every table you build is a content source a loop can render. Define a "Team" table once, loop it onto your about page, done.
- **A content workspace for writing.** A focused surface for posts and collections, plus live mode so authors edit inside the real design of the site instead of a gray textarea.
- **A media workspace that works like a file manager.** Folders and smart folders, bulk operations, usage tracking so you know where a file is actually used, replacement workflows, and pluggable storage adapters when you outgrow local disk.
- **Access control that's real, not decorative.** Roles built from 38 capabilities, token-based sessions, TOTP two-factor with secrets encrypted at rest, account lockout with backoff after repeated failures, and step-up prompts before the dangerous stuff like deleting a user or signing out every device.
- **⌘K for everything.** A fuzzy command palette over the whole admin. Jump anywhere, do anything, without touching the mouse.
- **Drafts stay drafts.** Unpublished edits never leak to a visitor. What you didn't publish, they don't see.
### Analyze
- **A dashboard you arrange yourself.** A 12-column grid of tile widgets you can drag, resize, and rearrange. Add the ones you care about in customize mode, and the layout saves per user. Plugins can ship their own widgets into the same grid.
- **An audit log that doesn't forget.** Every meaningful admin action writes a row: logins, content changes, role edits, plugin lifecycle. It's append-only, so it's a real record of who did what and when, not something anyone can quietly rewrite.
- **Form data that's yours.** Submissions sit in your own tables. Query them, export them, build on them. No vendor in the middle.
The analytics surface today is intentionally operational: dashboard status, audit history, and owned form data instead of third-party visitor tracking.
### Extend
Every CMS has plugins. The difference here is where backend plugin code runs.
An Instatic plugin is a zip package with a manifest. Its server entrypoint runs in a per-plugin worker that hosts a **QuickJS-WASM sandbox**: no filesystem, no environment variables, no network at all unless the site owner grants it, one host at a time. Editor extensions and app-kind admin pages are different: they run in the admin window and require the explicit `editor.code` permission before install.
Through the SDK, a plugin can add:
- HTTP routes and its own admin pages
- Storage and scheduled background jobs
- Loop data sources, so your content loops can pull from anywhere
- Canvas modules — new blocks that show up in the editor
- Media storage adapters and frontend assets
- Lifecycle hooks across install, activation, and beyond
Start with the [plugin system docs](docs/features/plugin-system.md) and the [template plugin](examples/plugins/template/README.md).
## Fast because there's almost nothing to load
A published Instatic page is mostly just a file sitting on disk. No framework to boot, no hydration step, no database round-trip on the common path. The browser pulls down semantic HTML and compact CSS bundles, and it's done. There's barely anything between the visitor and the content, so the pages feel instant.
That speed isn't a setting you tune. It falls out of how publishing works, in three layers you never have to think about:
- **Static pages are baked straight to disk when you publish** and swapped in atomically. Visitors are served a file, not a render.
- **Routes that genuinely change** hit a versioned in-memory cache. Publishing bumps the version, so old entries miss lazily and nobody sees a stale page.
- **The few truly per-visitor parts** are detected automatically and lazy-loaded by a runtime that weighs about 1.1 kB. Smaller than this paragraph.
What comes out the other end is plain HTML and compact CSS, all the way down. Nothing from the editor rides along: no React on your public pages, no editor runtime, no framework in the markup. And because it's just HTML and CSS, nothing holds your site hostage — you can read it, host it anywhere, or take it and leave. Full design: [the publisher](docs/features/publisher.md).
## Quick start
You need [Bun](https://bun.sh) 1.4.1 or newer (`bun upgrade` if yours is older; `bun run dev` refuses an older one because its Vite proxy needs that release to forward the editor's WebSocket). Nothing else. The default dev setup runs on SQLite, so there are no extra services to stand up.
```sh
git clone https://github.com/corebunch/instatic.git
cd instatic
bun install
bun run dev
```
Open `http://localhost:5173`. The first visit walks you through creating your site and your owner account.
Want to see it the way it actually ships? `bun run start` builds the admin and serves it from the Bun server at `http://localhost:3001/admin`.
> **Backups, in one sentence:** back up the database (a Postgres dump or the SQLite file) and the uploads folder, and you've backed up the whole site — [details](docs/deployment/backup-restore.md).
## Who's behind this
We're