Understanding the substrate
The substrate is a datastore for one person's digital life: messages, mail, calendar events, people, tasks, notes, media. One graph of typed entities behind one API. It is the system of record personal software builds on, instead of every app keeping its own silo.
The problem it answers is fragmentation. Every question that crosses two apps ("what did Alex ask me before this meeting?") is an integration project, because nothing shares identity, nothing shares change notification, and nothing offers a safe way for semi-trusted automation to write.
The design borrows deliberately from Kubernetes, the most battle-tested answer to "many semi-trusted programs cooperating over shared typed state":
- the substrate is the API server: typed objects, declared validation, an ordered change feed;
- every application and integration is a controller: it watches, decides, and writes back through the same public API;
- behavior lives in declarations (entity types, states, mappings, functions), not in bespoke endpoints. The write API is seven generic mutations, forever:
put,patch,delete,link,unlink,merge,split; - a closure of those declarations installs and uninstalls as one unit, an extension, which is how a provider integration or an automation reaches the graph without a substrate code change.
Everything on these pages builds one running example: a to-do list.
Substrate and teild
Two words, used precisely. Substrate is the protocol, the service, and
the implementation: the typed graph, the API, the primitives these pages
describe. teild is the parent, the organization level above it. That
split shows up in one visible place: groups are named under the org's
domain, tasks.teild.dev, people.teild.dev, while the product and
protocol vocabulary, in the docs, the CLI (ssctl), and the service, is
"substrate".
Six words
Like Kubernetes, the whole system is rules about a handful of primitives.
| Term | Meaning |
|---|---|
| Tenant | One person's fully isolated dataset, with its own Postgres schema and its own tokens. The service holds many; the data inside one is strictly single-person. |
| Group | A DNS-named namespace of entity types owned by one authority: people.teild.dev, tasks.teild.dev. Groups namespace names; they never partition the graph. |
| Entity type | The definition of one thing the graph can hold: its properties and its edges. A type belongs to exactly one group, and its full name is <type>.<group> (task.tasks.teild.dev). |
| Entity | One instance of an entity type, and the only thing there is. Tasks, people, tokens, and type declarations are all entities. Its identity is the full triple (group, type, id). |
| Property | A named, typed value slot on an entity: title, dueAt. Declared on the entity type, validated on every write. |
| Edge | A named, directed relationship from one entity to another, and the only way one entity points at another. Declared on the entity type it points from. |
The map
The pages ahead, in reading order:
- Data model: the envelope, identity, groups, property types, traits, and validation that govern every entity and every write, on one page.
- Schema: schema as entities: the declarable resources, the apply verb, admission, and how a schema evolves without breaking the data underneath it.
- Projection: how a dozen source records describe one subject: entity mappings, per-property ownership, and the merges that join what belongs together, reversibly.
- API: the API (REST, filters, pagination, mutations, errors, versioning, and tokens), GraphQL and search, and the changelog and watch stream every write lands in.
- Extensions: extensions as installable capability closures, the functions and SDK they ship, the agents that run an LLM loop over the graph, and the catalog of what ships today.
- Tools: the ssctl command line and the web console.
- Reference: the built-in entity types, group by group.
Next: the data model, the one shape everything reads and writes as.