Journal

September 26, 2026 · 2 min read

How this site is made

A blog, its studio and its server, built from Foldkit Plus packages: what each part owns, and where to read the code.

This blog is the demo of Foldkit Plus, a set of packages for Foldkit applications. Everything you can do here, from writing a post to building this page from blocks, runs on a few ideas, and the posts on this blog explain them one at a time.

Three applications, one server

The demo is three Foldkit applications:

  • the studio’s posts, at /, where posts are written, scheduled and published;
  • the studio’s pages, at /pages, where pages like the home page are built from blocks;
  • the site, at /site, which is what a visitor reads.

Each is one state machine: a Model, a union of the Messages that can happen, and one update that turns a Model and a Message into the next Model. Nothing on screen is kept anywhere else.

All three talk to one server. On a developer’s machine, pnpm dev runs it in Node. In this published demo it runs in your browser tab: the same server code, over SQLite compiled to WebAssembly, with its database saved in your browser. Nothing you write leaves your browser, and ?reset in the address starts afresh.

Who owns what

Most bugs in an interface come from two places that believe different things about one fact. So each package here starts by naming the owner of a fact:

  • A post’s published text is the server’s. The client keeps a copy in its Model, which foldkit-remote fills, and may throw away and ask for again.
  • A draft is kept beside the published row, never in it, so a visitor cannot read unfinished work. That is foldkit-cms.
  • A page is data: a document of blocks stored in a field, which foldkit-composition checks and foldkit-builder edits.
  • The search and the tab of the studio’s list are the application’s own, and the address only shows them, through foldkit-mirror. The open post and the builder’s panel are the editor’s and the builder’s, and the address asks them through their Messages. Either way, a reload comes back to them.
  • The look belongs to the views: foldkit-mixins attaches styles to named parts of a view, with no stylesheet to keep in step.

Sit in another chair

The studio has three chairs. Wren is a writer, who can write and save but not publish. Edda is an editor, who can publish. A visitor sees only the site. Switching chairs shows a rule every package keeps: what you may do is decided by the server, not by which buttons are drawn. If a writer asks to publish anyway, the server refuses.

Read the code

The whole demo is in the repository under examples/cms: the studio in app.ts, pageApp.ts and their views, the site in siteApp.ts and siteView.ts, and the server in server.ts. The Code link at the top of this site goes there.

← More from the blog