Concepts
The five terms you need to know before writing queries against the Geo API.
Space
A governance container. Two flavors:
- Personal space — owned by one wallet. The wallet controls every edit.
- DAO space — community-governed. Edits go through a proposal/voting flow before being applied.
Every entity lives in at least one space. The space determines who can publish edits and who can vote on them.
Entity
A node in the graph. An entity has:
- An
id(UUID, stored as bytes16 hex on chain) - A
name(text) - An optional
description(text) - Zero or more values — typed property data (
{ property, value, type }) - Zero or more relations — typed edges to other entities
Entities are typeless until you tag them. There's no class-vs-instance distinction the way there is in traditional ORMs.
Type
A tag applied to an entity via a Types relation. To say "this entity is a Project," you create a relation from the entity to the Project type entity using the Types property.
Two important consequences:
- An entity can have multiple types (e.g. both
ProjectandOpen Source). - Types themselves are entities. The "Project" type entity has a name, an ID, and is tagged with the meta-type
Schema Type.
Property
A field definition. Defines:
- The property's name and ID
- Its data type (
Text,Integer,Float,Boolean,Date,URL,Relation, etc.) - Optional metadata (description, format hints)
When you publish a value on an entity, you reference the property's ID:
{
property: "a126ca530c8e48d5b88882c734c38935", // "Name" property
value: { type: "text", value: "Stable Diffusion" }
}
Like types, properties are themselves entities tagged with the meta-type Property.
Relation
A directed edge between two entities, with its own ID and its own type. Unlike values (which are scalar fields on a single entity), relations are first-class graph edges.
A relation has:
id— the relation's own UUIDfromEntityId— the source entity (joined asfromEntityin queries)toEntityId— the target entity (joined astoEntity)typeId— the property that defines what kind of edge this is (joined astypeEntity)
Every type tag is a relation (entity → type, with typeEntity.name = "Types"). Every authored connection is a relation (project → person, with typeEntity.name = "Authors"). Every block attachment is a relation (entity → text block, with typeEntity.name = "Blocks").
This is the part of the model that surprises people coming from SQL — there's no foreign key column. There's an entity with a typed relation pointing somewhere else, and that's how you traverse.
Putting it together
A Project entity in a DAO Space might look like:
Stable Diffusion (entity)
├── values
│ ├── Name: "Stable Diffusion"
│ ├── Description: "Latent diffusion model..."
│ └── GitHub Stars: 68000
└── relations
├── Types → Project (entity → type)
├── Authors → Robin Rombach (entity → person)
├── Authors → Patrick Esser (entity → person)
├── Backed by → Stability AI (entity → organization)
└── Topics → Generative AI (entity → topic)
Each line under values is a value op. Each line under relations is a createRelation op. Each target (Project, Robin Rombach, etc.) is itself an entity with its own ID and its own values/relations.
You're now ready for the Cookbook.