Skip to main content

Data model

Cobblr stores everything as records, grouped into kinds, owned by modules. This section is the reference for that structure: the field types a record can carry, how computed values are derived, and how records connect to each other. The friendlier introductions live in Concepts (Modules, Fields); here we name the pieces precisely.

Workspaces are separate databases

Each workspace has its own database. A record in one workspace is not a filtered view of a shared table; it is a row in that workspace's own store, reached through its slug. So a token, a wire, and a query all act within one workspace at a time.

Modules own tables

A module is the unit a workspace is built from, and it owns its own storage. Each module carries a table prefix (inventory_, core_tags_, and so on), so the tables a module writes are its own and the kernel stays out of them. Enabling a module adds its area to the app and its tables to the workspace; turning it off leaves the others untouched.

Some modules are foundational and always on (file storage, locations, tags, notifications). They back every other module, so anything you enable gets them for free. See Modules for which is which.

Kinds and records

A kind is a type of record a module defines. Its id reads as the module name, a colon, and the kind: inventory:part, projects:task, machines:machine, core-locations:location. A module can provide more than one kind (Projects has both projects:project and projects:task).

A record is one row of a kind. When the API resolves a record it returns:

  • id: the record's identifier within its kind.
  • title: the display name, taken from whichever field the kind marks as its title (see field roles).
  • fields: a map of the record's values. Native fields sit at the top level; custom-field values live in a metadata object inside it. Computed and relation values are injected here at read time so a renderer sees them like any other field.

Where to go next