What is mdlake?
The ideas behind mdlake in plain words - workspaces, the lake, documents, media, drafts and published content, the GitHub mirror, sites built from a locked lake commit, the builder plugin, roles and tokens. Read this first.
On this page
mdlake has two parts that share one store of content. Editors write in the CMS. Developers generate websites from that content with the builder. This page explains the words you will meet everywhere else in the guide. Each idea is explained once here and linked from the pages that use it.
The one rule behind everything: content is knowledge, not pages. The CMS never decides what becomes a page. It keeps documents and files. A site, built later by a developer, decides which documents become which pages.
Workspace
A workspace is everything that belongs to one client or one project: its documents, its media, its people, its settings and its lake. Editors only see the workspaces they are members of. Admins see all of them.
Every workspace has a name (shown in the editor) and a short name, also called the slug, such as acme. The short name becomes the name of the Git repository and cannot be changed later. See Create a workspace.
The lake
The lake is the published content of a workspace, stored as plain Markdown files in a Git repository. Git is the source of truth for published content. That has three practical effects:
- Content is never locked inside the CMS. Anyone with access to the repository can read it, clone it and back it up.
- Every publish is a Git commit with an author and a message, so you get a full history.
- Sites and AI tools read the lake directly, with no CMS between them.
A lake looks like this:
_manifest.json overview of all published documents, rebuilt on every publish
services/
fleet.md one document
leasing.md
about/
our-story.md
assets/
01M5YPMN8B3Q6VX0T4HDK2RZCE.json description of one image or file
01M5YPMQ3W9DAT7F1GHJ5KXN0B.md text of a PDF or Word file, for AI toolsThe CMS also keeps a SQL database. It holds drafts, the edit locks, users, the publish queue and an index for search. The database is not the truth for published content: it can be rebuilt from the repository.
Note
The lake is Markdown only. It holds no HTML, no layout and no page structure. The lake format describes every field.
Documents
A document is one piece of knowledge: a service description, a team member, an FAQ entry. Each document has:
- an ID, a 26-character code like
01M5YPMJRG2SN2C75GJWV9DAWF, that never changes; - a title and a short summary, which is plain text;
- tags, a list of short words used to group and find documents;
- a body written in Markdown.
In the repository a document is one .md file with a small block of settings, called frontmatter, at the top:
---
id: 01M5YPMJRG2SN2C75GJWV9DAWF
title: Fleet services
summary: What we offer fleet customers and how a first project runs.
tags: [services, fleet]
status: published
created: 2026-10-01T09:12:00Z
updated: 2026-10-20T14:03:00Z
---Editors never see this block, file names or paths. Folders and file names only decide where the file lands in Git, and they can change at any time without breaking anything, because everything links by ID.
Links by ID
A link from one document to another is stored as lake://<id>. A link to an image or file is stored as asset://<id>. When an editor renames or moves a document, every link to it still works. A site resolves these links when it is built. See Writing documents.
Media
Media are the images and files of a workspace: JPEG, PNG and WebP images, and PDF, Word, PowerPoint and Excel files. They live in the media library. Each item has an ID too, and a description: alt text, caption, tags, rights and, for images, a focal point.
Two details matter later:
- Alt text is required for images. Until an image has alt text, it cannot be used in a document or published.
- Binary files are not stored in Git. When media is published, the file itself is copied to a public storage container, and a small JSON file next to the documents (
assets/<id>.json) describes it, including its public address. Sites read that address from the JSON file.
Media can be published in two ways. By default a file is in the lake automatically while a published document uses it. A file set to always is in the lake whether or not a document uses it, so that sites can use it directly. Files in a top-level folder named Brand, or tagged brand, are always included. See The media library.
Drafts and published
Everything an editor does is a draft first. Drafts are saved automatically in the database, as you type. Nothing reaches the lake until someone presses Publish.
| State | What it means |
|---|---|
| Draft | Only in the CMS. Not in the lake. |
| Published | The latest published version is in the lake. |
| Published, with unpublished changes | The lake has an older version. Your newer edits are only in the CMS. A small dot in the document tree and a count on the home page show this. |
Publishing writes the document, and the media it uses, to the lake as one Git commit. Unpublishing removes the file from the lake and keeps the draft. See Publishing.
Because published content can end up on public websites, the editor shows a short note the first time you publish in a workspace: “Published content can be used on public websites built from this workspace. Drafts stay private.”
The GitHub mirror
The CMS keeps one bare Git repository per workspace on its own disk. That is the working store, and it works with no Git host at all. To give developers, the builder and backups a normal remote, the CMS can mirror every publish to a private GitHub repository named lake-<short name>. The CMS only pushes and never overwrites what is on GitHub. See Connect GitHub.
Sites
A site is a website or web app that a developer generates from a lake with the builder. Sites bind to lake content by ID or by collection. They never copy text into code. When an editor fixes a typo and publishes, the site can pick up the fix without a developer touching any code.
By default a site is a snapshot. A file named lake.lock in the site pins the exact lake commit the site is built from. Publishing in the CMS does not change a snapshot site. A developer moves the lock on purpose, after reviewing what changed, with the refresh-content skill. This is what makes builds repeatable: the same commit always gives the same site.
A site can also be live, which follows the newest lake commit on every build. It is the right choice for sites where editors publish continuously, such as documentation, and it cannot use generated copy.
The kit keeps a clone of the lake inside the site, in .mdlake/lake, at the locked commit. Builds read from that clone, never from the CMS. See How sites work.
The builder plugin
The builder is a plugin for Claude Code, the AI coding assistant that runs in a terminal. It contains:
- skills, which are guided workflows such as
check-lake,plan-site,scaffold-siteandrefresh-content; - a ruleset, the agency’s conventions, which is copied into every site as
CLAUDE.md; - a template and a kit (
@mdlake/site-kit), the engine of a generated site; - a hook that blocks edits to files the tools own;
- a small MCP bridge, which lets Claude Code look at the lake through the CMS.
Skills stop and ask a developer for approval at the points that matter, such as the plan and design before anything is built. See Install the builder.
Roles
There are two roles:
| Role | What they can do |
|---|---|
| Admin | Everything an editor can do in every workspace, plus: create workspaces, invite people, change roles, manage tokens and the GitHub connection, import Markdown folders, and see AI usage. Developers are admins. |
| Editor | Work in the workspaces they are a member of: write, organise, upload media, publish, use the trash. Editors can also invite other editors to their own workspaces. |
Accounts are passwordless. People sign in with an emailed link, or with a passkey, which is the fingerprint, face or device PIN already on their computer or phone. There is no password to set, forget or leak. See Users and invites.
Workspace tokens
Sites and AI tools do not sign in as people. They use a workspace token: a long secret string, created by an admin, that belongs to one workspace and can only read. A token has a scope:
- Published content sees only what has been published. Use it for developers and AI tools.
- Published content and drafts also sees drafts, for a preview server that only editors can reach.
Production builds do not need a token at all. They read the lake from Git. See Workspace tokens.
How it fits together
- An editor writes documents and uploads media in the CMS. Everything is a draft.
- The editor presses Publish. The CMS commits Markdown to the workspace’s repository and mirrors it to GitHub.
- A developer runs the builder against the lake. The site records the lake commit in
lake.lock. - The site is built and deployed. It shows the content as of that commit.
- Later, editors publish more. A developer reviews the changes with
refresh-content, approves them, and the lock moves to the new commit.
What’s next
- Editors: Writing documents.
- Admins and developers: Install the CMS.
- Developers: Install the builder, then How sites work.
- Unknown word? See the Glossary.
