Zvessa docs

Blocks

A block is data: { id, kind, props?, children?, visibleTo? }. It is filled in and placed, never coded. Every kind is described once in convex/lib/blocks.ts, and that one list feeds the renderer, the checks, HQ and the AI's prompt, so a new block shows up everywhere.

The full, current list with every prop is in the Catalog (generated).

The blocks by purpose #

All are ready; each needs its engine's kit or setup only where noted.

PurposeKinds
Layoutstack (column or row), card (framed box), divider, switcher (one child at a time under segments, tabs or pills)
Words and mediaheading, text, list, image, stat
Actionsbutton (opens a URL or #page-id)
Data (Collections)records.list (list or board), records.form, records.count, split (shared costs); record views records.composer, records.timeline, records.calendar, records.streak, records.memories, records.prompt, records.stats (Data)
Talk (Spaces)inbox (every conversation in one list), stream (a room, channel or feed), direct, ask and queue (both sides of a support desk or applications), drafts
People (Spaces, Structure)members, invite, units (teams, classes, branches as a tree); invites and referrals invites.code, invites.list, invites.redeem and a general qr (any link, text or page) (People)
Account (Account)account.email, account.password, account.sessions, account.delete: the viewer's own account, on any page
Notifications (Notifications)notify.settings (your own controls), notify.inbox (tap opens the exact page), notify.bell (unread count), notify.send (managers send to members)
Safety (docs/SAFETY.md)safety.queue (moderators' review queue), safety.filters (word filter with a try-it box), safety.blocked (my blocked people), safety.report, safety.block, safety.admin (Zvessa's admins)
Web (docs/WEB.md)web.share (the web address with Copy and Share), hq.web (HQ's Web panel: handle, own domains, pages on the web, embeds)
Feeds (Spaces)feed.timeline (list, cards, grid or stories), feed.composer, feed.profile, feed.people, feed.activity, feed.search, feed.saved, feed.sources
Reviews (Spaces, docs/REVIEWS.md)reviews.summary (average, count, a bar per star, aspects, Write a review), reviews.list (sort and filter), reviews.stars (a small ★ 4.6 (128) line that opens the reviews), reviews.write ("How was it?" stars to tap), reviews.top (subjects ranked), reviews.queue (waiting and reported, managers only)
Money, levels, badges (Ledger)ledger.balance, ledger.send, ledger.give, ledger.history, ledger.leaderboard, ledger.levels, ledger.marks, ledger.grants
Play (Rounds)poll, wheel, game (a live game from blueprint.games), game.screen (its big-screen view)
Game lobby (Quick start, docs/LOBBY.md)poster (one game or link card), posters (a shelf in three sizes), showcase (featured carousel), game.live (games you can join now), game.winners, game.record (your own plays and best), lobby.header (logo, line, coins), lobby.row (a chat-list row that opens the games page), game.frame (one game's play screen on a page)
Time (Time)booking (book a time), scheduled (post later)
Numbers (Events)analytics (charts per day, managers only)
Live (Rooms, Files, Screens)room (group call or stage), call (rings people), media.gallery, media.player, screen.pair, screen.remote
Starters (Templates)hero (page header with picture and buttons), tiles / tile (app-style grid), links / link (services or links with price and action), chats (the chat list), calls.recent (call buttons and recent calls), conversation (one chat with its bar; on the talk.screen page it is every opened chat)
Photo books (Blueprint)photobook.book (cover and pages to swipe, read full screen, Edit book for managers), photobook.shelf (covers of the space's books, plus one per #tag album)
Custom logicminiapp (a sandboxed app from /apps, with a config prop); the public library's miniapps.library (browse, try, add, remix), miniapps.mine (publish and update your apps) and miniapps.review (admins), from the App library kit (Mini-apps)
AI (AI jobs, AI limits)ai.setup ("Connect your AI": paste the Claude key), ai.chat (the builder chat; props placeholder, model, steps), ai.model (model size, streaming, finish pushes), ai.notes (what the AI remembers about you), ai.jobs (latest AI work with Stop), ai.allowance (what the viewer has left today, with a bar), hq.aiUsage (managers: today's use by person, space and bots, and whose key pays)
Sharing (Templates)share.save (save pages or the space, with the list of what's taken out), share.library (browse, preview, add or switch), share.mine (your pieces: publish, update, take out), share.review (admins)
Search (docs/SEARCH.md)search (one box across pages, records, messages, posts, people and files; sources, collection / stream / feed, limit; each person only finds what they could open)
Bots and automations (AI)bots.list (bots and automations with an on/off switch), bots.waiting (actions waiting for you), bots.runs (what happened), bots.run (run one by hand), bots.ask (ask a bot), bots.hooks (webhook addresses, shown once)
HQ (system)hq.proposals, hq.pages, hq.library, hq.styles, hq.access, hq.connections, hq.history, hq.blueprint; with the starters, hq.overview (KPIs), hq.starters (switch template) and hq.navigation (tabs or chat list)

room and call need LiveKit on the server; big media needs R2 (docs/LIVE.md).

Planned: native form fields (date, slider, segmented choice), a calendar, a map, a QR code, a timer and a pay-by-card button.

switcher takes labels (one per child; a missing one uses the child's title), look (segments, tabs or pills) and start. Only the open part is drawn, so the other parts' live data isn't loaded until someone opens them. In Edit mode every part shows, so each can be changed.

Props #

Hiding a block #

visibleTo: ["coach", "parent"] shows the block only to those roles; managers always see everything. The server leaves hidden blocks out of what it sends, so they never reach the device (People).

How blocks are drawn #

src/components/Renderer.tsx holds one small function per kind in RENDERERS. It draws with React Native, so the same code runs on iOS, Android and the web. Every renderer reads its look from useWorkspace() and the helpers in src/lib/workspace.tsx (surface, bodyText, headingText, gap, color) and never writes a colour, font or size of its own. An unknown kind shows a quiet "Unknown block" line instead of crashing.

Kits keep their renderers in their own folder (src/kits/<kit>/) in a *_RENDERERS table (SOCIAL_RENDERERS, LIVE_RENDERERS, LEDGER_RENDERERS). Renderer.tsx looks a kind up in RENDERERS first, then in the kit tables when the block draws; the tables are not spread in when the file loads, because that made an import cycle that crashed the app on start. Kit block descriptions are spread into BLOCKS. Blocks that show live data (records, posts, votes) read it through Convex queries, which update on every device as soon as anything changes.

Adding a block #

  1. Describe it in BLOCKS in convex/lib/blocks.ts: kind, a one-sentence about the AI reads, its props (type, required, about) and whether it holds children.
  2. Draw it: add a renderer to RENDERERS in src/components/Renderer.tsx (or to your kit's own *_RENDERERS table, added to the lookup list in kitRenderer). Put anything bigger than a few lines in its own component file. If it has an icon, use <Icon name="…" /> (Device).
  3. Cross-check it if it points at another part of the blueprint (a collection, a stream, an app): add the check to the walk in checkBlueprint (convex/lib/blueprint.ts), so a broken reference is refused with a readable message.
  4. Regenerate the catalog: npm run docs.

HQ and the AI pick the block up from the list; nothing else changes.

Good blocks #