Zvessa docs

Data

Two kinds of live data, both kept out of the blueprint: records (things people add, from the Collections engine) and events (things that happened, from the Events engine).

Collections (ready) #

A collection is the shape of a list of things, in blueprint.collections. Products, sign-ups, tasks, bookings, scores and notes are all collections with different fields. No new database table is ever needed. Code: convex/lib/collections.ts, convex/records.ts. Code that writes records must also write text: recordText(data) (convex/lib/search.ts) so search finds them; after upgrading a deployment, run npx convex run kits/search/search:_backfill once.

{ "id": "orders", "name": "Orders", "fields": [
  { "id": "item",   "label": "Item",   "type": "text",   "required": true },
  { "id": "qty",    "label": "How many", "type": "number" },
  { "id": "status", "label": "Status", "type": "choice", "options": ["New", "Packed", "Sent"] }
] }

Field types #

Every value is checked and cleaned on the server before it's saved.

TypeStored asRule
textstringup to 500 characters
longtextstringup to 8,000 characters
numbernumberany finite number; 1,200 is read as 1200
moneynumberlike number; the currency comes with the Ledger engine
datestring2026-10-20 (a time may follow)
choicestringone of options (at least two)
checkboxboolean
emailstringlooks like an email, up to 200
phonestringup to 500
urlstringmust start with https://

Planned: files and images, a person, a link to another record, a place, rich text.

Showing and collecting records #

BlockDoes
records.formAdds a record. fields picks which to ask; defaults (a JSON string) sets values on every new one, like {"status":"New"}.
records.listLists records, newest first. With groupBy naming a choice field, it's a board with one column per option.
records.countHow many records there are.

Record views #

More ways to show and write any collection: a journal, a gratitude log, a habit or workout tracker, a reading list, a team check-in. Described in convex/lib/records/views.ts, drawn by src/kits/records.

BlockDoes
records.composerA question, the chip field's options to tap (a mood), and a button that opens the full-screen writing sheet
records.timelineRecords under month or day headers, with search (words and #tags) and Write
records.calendarA month coloured by each day's chip; tap a day to read or write for it
records.streakDays in a row, the best streak, the total, this week as dots, an optional goal, a nudge until today has one
records.memories"On this day": a week, a month, six months and each year ago; hidden when there are none
records.promptA daily prompt (the same all day), "another one", and Write, which saves the prompt on the record
records.statsInsights over the last N days: days written, records, words, best streak, a bar per chip option

Props name which field plays which part, so they fit any collection: title (text), body (longtext), chip (a choice field, with icons and tones per option), date (the record's day; without one, the day it was written), tags (#tags; ones in the body count too), and field (where the prompt is saved). "none" or "" turns a part off, and a field the collection lacks is simply not drawn. Every word is a prop (question, note, write, placeholder, saved with {streak}, label, shuffle, empty, heading, nudge, done).

Tapping a record opens a reader with Share, Edit and Delete. The writing sheet is a native page sheet: pick a day (never the future), the prompt, the chip options, a title, the body with a word count, #tags and any other fields; Cancel asks before throwing work away.

Server reads in kits.records.views: days, onDays, search and one. They follow the same rule as records.list (hidden behind every block means hidden on the server), so visibleTo: ["owner"] on a page keeps a journal private. Each read looks at the newest 2,000 records; writing goes through records.add, update and remove.

Who can do what #

ActionNeeds
See recordsview
Add a record, change or delete your ownadd
Change or delete anyone'sedit

Each record knows who added it. records.list returns mine and canChange for every row, so a screen shows edit buttons only where they work. The server checks again on every write.

Limits today #

Events #

The Events engine counts what happens in a space, per day and per person (convex/tally.ts, convex/events.ts). It's on once the space has the Analytics or Leaderboards kit.

Planned: the AI reads totals (never raw personal data) to suggest improvements; mini-apps send events through the bridge; sums of values, not only counts. Analytics belong to each space's owner; our own product analytics are separate and never mixed in.