clave docs

Site source

A site's files live in git. You clone the repository, edit it, and push.

Git is the source of truth for what a site is made of. It is git rather than an upload API for one reason: the build sandbox needs credentials that reach one site and nothing else, and a git credential is per repository by nature.

Two repositories

A site has two repositories, and the split is what lets a post go live alone.

Repository Holds Address
source the site's code and design https://api.heyclave.party/git/<site id>.git
content the site's posts https://api.heyclave.party/git/<site id>.content.git

The build mounts the content repository at src/content/, so the two can never hold one file. Every surface takes one tree: a path under src/content/ routes itself to the content repository.

A batch that crosses the two repositories is refused. Two commits in two repositories are not one change.

The content repository takes an allowlist of formats. "Not code" is what it has to promise, and a denylist promises only "not the code we thought of".

Files you may not change

Clave maintains some files and freezes them: package.json, the lockfiles and .npmrc. A push that changes one is refused, by the API and by the pre-receive hook.

The reason is the build. A site that edits its own dependency list builds against a tree that the file does not describe.

astro.config.mjs is not frozen. A site that wants another integration adds it itself.

Where a file may go

What a site may hold is gated by where the file goes, not by one list of formats.

public/ must never take a format that runs script. That directory is served from the site's own hostname, and an upload link that writes into it travels over chat.

Three ways a file arrives

  1. A push, for anything in the tree.
  2. The API, with PUT /v1/sites/{id}/assets/{path} for a file the agent already holds, POST /v1/sites/{id}/photos for a stock photo, and POST /v1/sites/{id}/uploads for a link the owner uses.
  3. An upload link, which the owner opens in a browser and drops a file on. The link is bound to one site, it expires, it has a slot count, and each file has a byte cap.

One daily allowance covers all three. Read Site source.

Drafts of posts

A post marked draft: true never reaches the live site. The filter is in the platform, not in the site's own code: a filter in a page is code an agent may remove, and a draft post on the live site is the one mistake this feature must not make.