Sign inSign up

labsatquicko/silo

By labsatquicko

•Updated 4 days ago

A minimal, customizable and portable headless CMS available as a single binary

Image
Content management system
0

146

labsatquicko/silo repository overview

⁠silo

A small, standards-based headless CMS. Define your collections in JSON Schema. You get an admin UI with generated forms, a REST API, and data you can move anywhere.

silo is one TypeScript process on Bun⁠, with six runtime dependencies. It keeps content as plain JSON documents in SQLite or in flat files, it serves its own React admin UI, and each moving part sits behind an interface you can replace. There is no proprietary field language, query language, or file format in it. What silo stores, your other tools can already read.

⁠Quick start

⁠Docker
docker run -p 8090:8090 -v silo_data:/data labsatquicko/silo

The image is on Docker Hub⁠ as labsatquicko/silo, and on the GitHub registry as ghcr.io/org-quicko/silo. Every release is tagged with its version, :latest points at the newest one, and each tag carries both an amd64 and an arm64 image, signed with Sigstore and carrying build provenance. Deployment⁠ has the two commands that check them. To build it yourself instead:

docker build --pull -t silo .
docker run -p 8090:8090 -v silo_data:/data silo
⁠First run

On the first start of an empty instance, silo makes a root API key and prints it one time, to the console. Store it. You need it to connect the admin UI.

Open http://localhost:8090⁠, add the server with its URL and that key, and you can create a collection, fill in a generated form, add entries, mint more keys, upload media, and move data between instances.

If you lose every key, mint a new one against the data directory. No server has to be running:

silo keys create --preset root --label recovery

⁠Concepts

TermWhat it is
InstanceOne data directory with one instance_id. Everything below is inside it.
ProjectA named container, for example a tenant or an application.
EnvironmentA named container inside a project, for example prod or staging.
CollectionA name and a JSON Schema document, identified by (project, environment, name).
EntryA JSON document in a silo envelope: a ULID id, a rev, a seq, and UTC timestamps.
VariableA name declared once in a project, valued per environment, and put into each {{NAME}} an entry holds.
API keyA key with explicit claims. silo has no users and no sessions.

Projects and environments are plain string containers with no metadata of their own. All three of projects, environments and collections are keyed records, so you can rename any of them, and the claims that name them follow.

Entries are documents. silo does not map a schema to tables. Every write is validated against the collection's schema, and there is no way to turn that off. A read is not validated, so a schema can never make stored data unreadable.

A collection keeps its schema while it holds entries. To change the fields, delete the entries first, or export them and import them into a new collection. The access setting, the search fields and the labels stay editable at any time, because they do not decide whether an entry is valid. A later release will allow a schema change over existing data, with a plan that states what happens to those entries.

Names that start with _ belong to silo. API keys, for example, live in the reserved _system/_system scope as a _keys collection. silo stores them exactly like your own content, which is why every storage driver and the export engine handle them with no special code.

⁠Features

  • One process, one data directory. No database server, no cache, no queue, and no search cluster. SQLite comes from the runtime. Media goes to local disk by default. The server hosts the admin UI itself, and compiles to a standalone binary.
  • Standard formats. JSON Schema draft 2020-12⁠ for collections, validated in full by Ajv 2020. Plain JSON for entries. REST over HTTP for transport. ULIDs for ids, RFC 3339 UTC for timestamps, tarballs for archives, the S3 API for media, and TOML plus environment variables for configuration.
  • Generated admin UI. The admin reads a collection's schema and draws the form. A construct no form can draw becomes a raw JSON editor for that part only. x-silo-* keywords in a schema control how the admin renders and protects a collection.
  • Search and filters. Text search at three reaches: one collection, one environment, or everything the key can read. The filter is a small JSON AST over RFC 9535⁠ JSONPath, and the admin's filter builder writes that same AST. All of it goes in the URL, so a filtered view is a link you can send.
  • Claims, not roles. An API key carries explicit claims, with a wildcard available per segment. Access is deny by default, and a key can mint only keys its own claims already cover.
  • Safe concurrent writes. PUT and DELETE on an entry take the revision you expect, as If-Match. A mismatch is a 409, so two admin tabs cannot overwrite each other in silence.
  • A media library. Local disk, or any S3-compatible bucket. Folders, tags, a type filter, and a check that refuses to delete an asset an entry still references. Where the library keeps its bytes is configurable from the admin.
  • Per-environment values. A variable holds the one string that has to differ between staging and prod. Declare the name once in the project, value it in each environment, and silo puts the value into each {{NAME}} on the way out.
  • Portable data. One command exports every project, environment, schema, entry, and media file, and one command imports it again. Name a project, an environment or a single collection to move only that, and choose whether the media files travel with it. The filesystem driver's on-disk layout is the export format, so an fs-backed instance is a live backup you can copy with cp, replicate with rsync, or review in git. You can also pull an export straight from another running silo.
  • An MCP server. Point Claude Code, Codex, Cursor or Claude Desktop at /api/mcp with an API key and the model gets silo's tools: browse projects and schemas, read, search, create and update entries. Every tool is one API route called with that key, so the key's claims decide what the model may do.
  • Replaceable parts. Storage is SQLite, flat files, or your own driver. Media is local disk or any S3-compatible bucket (AWS S3, MinIO, Cloudflare R2, DigitalOcean Spaces). The admin UI is an ordinary client of the public API, so you can extend it, fork it, or write your own.

Tag summary

Content type

Image

Digest

sha256:f52db63aa…

Size

42.6 MB

Last updated

4 days ago

docker pull labsatquicko/silo