Turn the client's space book into a much more organized shortlist. Spaces move into the right chapter as client and broker activity happens, while brokers retain control over every change.
Static clickable mockups of the target UX, plus the rules and data model to build it on the current Next.js and Supabase stack.
Every client book uses the same five chapters. A clean, consistent foundation reads as professional to clients and keeps newer brokers from over-customizing. Additional chapters stay off by default and can be revisited later.
Turned on per book. Brokers upload new-to-market spaces here. They stay until the client adds to tour or marks Not A Fit, or the broker moves them to Market Overview after 2 to 3 weeks with no engagement.
The ranked shortlist the broker will submit on, in the 1, 2 and 3 slots. Only a broker can place or rank a space here.
Created the first time a space is added to tour. Each space shows Tour requested, then Toured once the tour happens.
Created on the first Add to Tour or Not A Fit. Holds every space the client hasn't acted on, plus Newly Added spaces the broker moves over.
Created the first time a space is marked Not A Fit. One team mark can be restored by the broker; two marks from different team members closes it. Collapsed at the bottom, never deleted.
Every space belongs to exactly one chapter. No duplicates across chapters.
Chapter placement is derived from recorded client reactions, tours and broker decisions, so brokers don't reorganize the book after every interaction.
A broker can drag any space to any chapter. Each manual move is recorded as an event and reflected in the book.
The broker decides which spaces sit in Newly Added. The "new" badge and count are per viewer: each person sees what's been added since they last viewed the book, not a shared counter that goes stale for the team.
Display numbers reflect the client's priorities: Final Selections ranked 1, 2, 3, then toured spaces in chronological order, then Market Overview, then Not A Fit. Newly Added spaces show a bullet until they're placed. Each space keeps a permanent ID behind the scenes.
Total spaces, toured spaces and final selections. Selecting a number filters the book and the map.
A concise "Since you were here" update and a "Why it's in your book" line. After a tour, capture why a space stood out as a fit or top contender, or why it was worth seeing despite drawbacks. Every explanation ties to recorded notes and client feedback. No match scores, no unsupported reasons.
Client actions apply immediately. Broker moves are published as a change set; once published, the book updates for the whole client team in real time.
When a team member marks Not A Fit, the space moves to Not A Fit and a comment naming who marked it posts to This space and General. That comment always stays. The broker can restore a 1-mark space to Market Overview. A second Not A Fit from a different team member closes it in Not A Fit for good: two negative reviews are enough to record and move on.
Everyone on the client team sees how the others are interacting: feedback, tour adds, Not A Fit marks and the shortlist.


Each phone is live: tap cards, buttons and back arrows to move between screens. Scroll sideways for all seven.
The event log is the source of truth. The current chapter, display numbers and book view are derived from it.
| Requirement | Where it lives |
|---|---|
| Space identity and display number | book_spaces.id (permanent) and display_no (derived from priority order, recomputed on every published change) |
| Book and client-team membership | book_members: book_id, user_id, role (client, broker, admin). The client team reads one shared view of reactions, notes, shortlist and Not A Fit. |
| Events: actor, action, timestamp, affected space | book_events: id, book_id, space_id, actor_id, actor_role, type, payload, created_at. Append-only. |
| Each viewer's last-viewed point | book_members.last_viewed_at, used for the per-viewer New badge and Since you were here |
| Approved change sets with 30-day undo | change_sets: id, book_id, broker_id, published_at, undo_until, undone_at. Each broker event carries change_set_id. Undo writes reversing events; nothing is deleted. |
A space's chapter is set by its latest placement event. A broker's move holds until the client acts on that space again.
| Event | Result |
|---|---|
space_added (newly_added) | Newly Added |
space_added | Market Overview, or the flat list before any engagement |
add_to_tour | Add to Tour | Toured, Tour requested |
tour_completed | Same chapter, Toured |
not_a_fit (1st team member) | Not A Fit, plus an auto comment in This space and General. Broker can restore. |
broker_restored | Market Overview. The comment stays; the mark still counts. |
not_a_fit (2nd distinct member) | Not A Fit, closed. Restore is disabled. |
broker_moved | Chapter the broker chose, on publish |
final_ranked | Final Selections slot 1, 2 or 3 |
Because numbers follow priority, they can change. Notes, comments and emails should reference the space name or permanent ID, not the display number.
| Table | Columns |
|---|---|
book_spaces | chapter (newly_added, final, add_to_tour, market_overview, not_a_fit, null), tour_status, final_rank, display_no, sort_key, added_at |
books | newly_added_enabled, stale_after_days (default 14) |
space_notes | space_id, author_id, kind (tour_note, broker_note), text, visibility. Source for Why it's in your book. |
not_a_fit_reasons | event_id, reason, note. Always shared with the team. |
book_spaces (Not A Fit) | nfit_members (count of distinct client members who marked it, never reset by restore), nfit_closed (true at 2) |
org_settings | custom_chapters_enabled (default false) |
add_to_tour.