Tutorial/Overview

Tutorial

any looks like a lot of machinery from the outside — types, properties, parts, datasets, modules, bundles, a catalog. Almost all of it is optional. In the simplest case you create an object and you are done; every further concept is one more thing you can add when you need it. This tutorial adds them in order, one part per level, with a working example at each step.

The four levels

 1. Objects        an object with a name and a description         a notebook
 2. Properties     a type: typed columns on objects of that type    a password manager
 3. Datasets       a table of records inside one object            10 000 emails
 4. Apps           parts, bundles, the sidebar, the catalog         the mailbox as an app

Each level is complete on its own. A space full of plain objects with names is a valid space. A type with three properties and no parts is a valid type. You never have to reach the last level to use the first.

Part You build You learn
1. Objects a notebook of named objects create, read back, subscribe, rename, delete; the universal any group
2. Properties a password manager types, the three ids, kinds and descriptors, choice options, filters on values, one object carrying several types
3. Datasets a mailbox holding 10 000 emails a table inside one object: when to use it instead of many objects, an enforced schema, idempotent import, paging, search, aggregation
4. Apps the mailbox as a sidebar app parts and modules, bundles that converge across devices, miniapp, the usecase catalog

One model, two directions

Seen as a database, the simple things are objects, types and properties, and an app is the complicated construction on top. Seen from the interface, it flips: the simple thing is the app in the sidebar — a wiki, a chat, a contacts directory — and the objects, types and properties inside it are the details. any has to serve both. The levels above are the database direction; Part 4 ends where the interface begins, at the usecase catalog that installs the well-known apps with one call.

The picture to keep in mind

objectInbox typeMailbox partmessages dataset<typeId>_messages carries has owns served by property valuesone group per type property definitionsthe columns modulerecords · editor · chat

An object carries any number of types. Each type contributes its property definitions — the columns the object can hold values for — and its parts: display units a client renders, each owning a dataset that a module serves. The records module serves a dataset whose schema you declare; the editor module serves block documents; the chat module serves messages.

Attaching a type is the closest thing any has to inheritance, and it is deliberately flat. An object inherits columns and behaviour from every type it carries, side by side; types never inherit from each other. Part 4 spells out the rules, and you do not need them before then.

Why it matters. Every one of these levels is a CRDT record in an end-to-end encrypted space on your own device. A type definition, a choice option, a part declaration and the data they govern all sync the same way, so a schema change made offline on one device converges with data written on another without a migration step or a server that sees plaintext.

Before you start

The tutorial assumes a running server and one space, as in the Quickstart. Every example is a curl call against it:

API=http://127.0.0.1:7001/v1
SPACE=$(curl -s -X POST $API/spaces -H 'content-type: application/json' \
  -d '{"name": "Tutorial"}' | jq -r .id)

Keep $SPACE — every part uses it.