Nomad
Broker tool · Developer preview

The self-organizing book

Client books that sort themselves into five chapters, with AI working quietly underneath. Static clickable mockups of the target UX, plus the data model and rules to build it on the current Next.js and Supabase stack.

5chapters
10screens
4build phases
01

Events in, structure out. AI proposes, the broker approves.

Chapters, not folders

Newly Added, Final Selections, Toured, Reviewed, Not A Fit. Each space is in exactly one, derived from events, never dragged by hand after every tour.

New is per viewer

Newly Added means new to the person looking. Computed from added_at vs. that viewer's opens, not a global flag.

Stable numbers

Each space keeps the number assigned when added. Reordering never renumbers, so "No. 7" in an email stays correct.

Funnel bar

Total, toured, finals. First thing a client sees, and a filter for the list and the map.

AI out of sight

No chatbot. A since-you-were-here line, a why-it's-here line, and broker tools that output a checklist of changes.

Nothing ships unapproved

Every AI-proposed change goes through a broker approve step. 30-day undo via the event log.

02

Desktop

03

Mobile prototype

Each phone is live: tap cards, buttons and back arrows to move between screens. Scroll sideways for all eight.

1 · HomeFunnel, since-you-were-here, chapter chips, Newly Added cards, Compare. Open
2 · Space detailSpec tiles, why-it's-here, actions in the thumb zone. Open
3 · Not A FitReason chips (tappable) that feed ranking. Open
4 · Compare finalsSide by side, figures tied to the listing. Open
5 · MapPins colored by chapter, chip filters. Open
6 · Tour day modeRoute, gut check per stop, voice and photo. Open
7 · ActivityEvent timeline with last-visit marker. Open
Broker · Voice debriefVoice note to proposed changes, approve on site. Open
04

Build notes

Chapter rules (first match wins)

  1. Not A Fit: latest not_a_fit event by the broker or any client viewer, not reversed.
  2. Final Selections: broker set stage = final. A client Top Choice only suggests it.
  3. Toured: linked to a tour whose date has passed, or broker marked toured.
  4. Newly Added: added_at after this viewer's first open of the book and no space_opened event by this viewer, or featured_until in the future.
  5. Reviewed: everything else.

Funnel bar

  • Total = all spaces in the book.
  • Toured = Toured + Final Selections.
  • Finals = Final Selections.
  • Segments: not toured, toured not final, final. Must sum to total.

Schema additions

TableColumns
book_spacesspace_no (int, immutable), stage (enum: none, toured, final, not_a_fit), sort_key (text, fractional index), added_at, featured_until
book_eventsid, book_id, space_id, actor_id, actor_role, type, payload jsonb, created_at. Append-only. Source of truth.
book_viewerslast_seen_at, first_opened_at
not_a_fit_reasonsevent_id, reason (light, layout, location, price, size, building, commute, other), note, share_with_team

Event types

space_added space_opened reaction not_a_fit stage_changed tour_scheduled tour_completed comment proposal_applied undo

AI proposal contract

Command bar and voice debrief share one server route. The model returns structured output only; the server validates every space_id against the book before showing it. Rent and lease economics never go into the prompt.

POST /api/books/:bookId/proposals
{ "mode": "command" | "voice", "input": "text or transcript" }

200 {
  "changes": [
    { "space_id": "uuid", "from": "none", "to": "final", "reason": "Starred by client, toured Oct 14" }
  ],
  "notes":  [ { "space_id": "uuid", "text": "Client concerned about columns", "visibility": "internal" } ],
  "flags":  [ { "space_id": "uuid", "type": "split", "detail": "1 star, 1 not a fit" } ]
}

POST /api/books/:bookId/proposals/:id/apply   { "accepted_ids": [ ... ] }
  writes one stage_changed event per accepted change, inside one transaction

Implementation notes

  • Fractional indexing for sort_key so a drag updates one row.
  • Supabase realtime on book_spaces and book_events so open books update live.
  • Chapter derivation as a Postgres view keyed by viewer, so the client and API agree.
  • Mobile: actions in the bottom third, 44px minimum targets, swipe gestures always paired with buttons, tour mode queues actions offline.
  • Same chapter colors on list, chips and map pins.

Phases

  1. Event log, derived chapters, stable numbers, per-viewer Newly Added, funnel bar.
  2. Since-you-were-here, Not A Fit reasons, Compare Finals.
  3. Command bar, voice debrief, why-it's-here lines.
  4. Tour day mode, team commute, consensus flags.