Tour Dash
Systems map · 25 August 2026

How it fits together

The companion to Where it stands. Four views of the same product: the stack it runs on, the loop a job travels through, the data model underneath, and the automation that runs without anyone pressing a button. Green is built and working. Amber is partly built. Grey dashed is not connected yet.

Views Stack · Loop · Data · Automation Drawn from The live codebase
01

The stack

Four layers. The top one is what a demo shows you; the three below it are the reason the demo is not a mockup. Read it top to bottom — a click in the browser travels all the way down and back.

Built and running Built, but incomplete Not connected yet
Interface
React · TypeScript · Tailwind. Runs in the agent's browser.
12 screens
Dashboard, map search, listings, applications, calendar, wallet, profile, settings
Design system
Locked light and dark themes, one accent, validated contrast
Query cache
Deduplicates requests and refreshes data the moment it changes
Map rendering
Mapbox pins, radius overlay, basemap follows the theme
HTTPS · signed session token on every request
Edge
Cloudflare's global network. Serves the app close to the user.
Static hosting
Versioned deploys, instant rollback to any previous build
Global CDN
The app is cached worldwide, not served from one machine
Deep links
Any URL loads directly — verified, not assumed
Custom domain
Still on the platform's default address
Postgres wire protocol · WebSocket for live updates
Platform
Supabase. The database, the rules around it, and the automation inside it.
Authentication
Real accounts and sessions, with profile creation on sign-up
Postgres
7 related tables — the system of record
Row-level security
Access rules live in the database, enforced even if the app is bypassed
Triggers
4 automations that fire on data change, not on a button
Radius search
Distance filtering runs server-side across the whole table
Realtime
New listings arrive without a refresh
File storage
Avatars and listing photos, owner-write and public-read
Email delivery
On the built-in mailer, rate-limited. Needs a real provider before public sign-up
Outbound service calls
External services
Third parties the product depends on.
Mapbox
Basemap tiles and address geocoding on every listing posted
Payment provider
None connected. The largest remaining build
Email provider
Needed for sign-up confirmation and password reset
Licence verification
Licence numbers are collected but checked against nothing
02

The loop a job travels through

Left column is what a person sees. Right column is what the system does on its own the moment they act — the part that is invisible in a demo and expensive to build. Every green step below runs against the live database today.

1
Listing agent
Posts a showing
The form changes shape by job type — an open house asks for expected attendees and the hosting agent; a walkthrough asks for punch-list items. Nine job types, each with its own fields.
System does
  • Geocodes the address to coordinates so it can be found by distance
  • Writes the listing with its type-specific fields stored alongside
  • Pushes it live to everyone already looking at the map
2
Showing agent
Finds it nearby
On a live map with a search radius, or as a filtered list. Header search works across both, and the filters and the map stay in sync.
System does
  • Runs the distance calculation inside the database across every listing
  • Returns only what is inside the radius — the browser never sees the rest
  • Joins each result to its poster's profile and rating in the same query
3
Showing agent
Applies
One action. The listing agent does not have to be online, or in the app, for it to register.
System does
  • Writes the application against the listing
  • A database trigger notifies the listing agent — the app is not involved
  • The pending count on the poster's listing card updates
4
Listing agent
Reviews applicants and approves one
Each applicant appears with their profile, star rating and completed-job count. This is the decision the whole product exists to support.
System does — four writes, one action
  • Marks the application approved
  • Creates the appointment, linked to both parties
  • Flips the listing to filled so nobody else can apply
  • A trigger notifies the agent who won the job
5
Both agents
The job appears on both calendars
With directions that open the real property address in Maps, and a contact action that dials or emails the actual person on the record.
System does
  • Serves each side only the appointments they are a party to
  • Renders month, agenda and stats views from the same records
!
Missing link
The job is done — and nothing happens
There is no way to mark an appointment complete, so no earnings are ever credited and no money ever moves. The wallet below is fully built and simply never receives anything. This is one small build sitting behind one commercial decision: who holds the funds, and what is the platform's cut.
What should happen here
  • Either party marks the job complete, the other confirms
  • Funds release to the showing agent, minus the platform fee
  • An earning is credited and the completed-job count increments
  • Payout reaches a real bank account
6
Both agents
They review each other
Reachable today, because reviews were built independently of the payment step. Reputation is what makes the next match easier — it is the compounding asset in a marketplace.
System does
  • Writes the review with a rating and comment
  • A trigger recalculates the recipient's average rating and review count
  • The new rating appears wherever that agent is shown to others
03

The data model

Seven tables. Across the top is the lifecycle of a job — a listing becomes an application, an application becomes an appointment. In the middle is the account every record keys back to. Along the bottom are the records the system produces as a by-product: reputation, money, and alerts. Every table carries its own access rules, marked RLS.

listings RLS id pk poster_id fk service_type title · price lat · lng · address status open|filled applications RLS id pk listing_id fk applicant_id fk message status pending|… applied_at appointments RLS id pk listing_id fk application_id fk poster_id fk provider_id fk scheduled_date · time profiles RLS id pk — the account name · email · phone brokerage_name license_number not verified rating · review_count completed_jobs zip_code · radius_location reviews RLS id pk reviewer_id fk reviewee_id fk rating · comment created_at transactions RLS id pk user_id fk type earning|payment|… amount · status no earnings written yet notifications RLS id pk user_id fk type · title message · read created_at listing_id application_id poster_id applicant_id poster_id · provider_id reviewer_id · reviewee_id user_id user_id

Two things are worth pointing at on this diagram. The licence number on the profile is collected and never checked against any authority — a policy decision, not an oversight. And transactions is the only amber table: it is fully built and correctly wired, but nothing has ever written an earning into it, because nothing marks a job complete.

04

What runs without anyone pressing a button

These live inside the database rather than in the app. That distinction matters commercially: they cannot be skipped, cannot be forgotten, and keep working no matter how a record was created — through the app, through an integration, or by an administrator.

on_auth_user_created
The moment an account is created, a full profile is built from the sign-up details — brokerage, licence, phone, service radius. No half-registered accounts.
on_application_created
Applying to a listing notifies the listing agent. Fires on the data, so it works whether the application came from the app or anywhere else.
on_application_approved
Approving notifies the agent who won the job — and only when the status actually changes, so re-saving a record never sends a duplicate.
on_review_created
A new review recalculates that agent's average rating and review count on the spot. Reputation can never drift out of sync with the reviews behind it.
nearby_listings( )
Distance filtering as a database function. "Within 15 miles" is answered across the entire table by the server — the difference between working at fifty listings and working at fifty thousand.
Row-level security · all 7 tables
Who may read or write each row is enforced by the database itself. An agent cannot reach another agent's transactions or edit someone else's listing even if they bypass the interface entirely.
05

Reading all four together

Everything in the loop is green except one link — and that link is not blocked by engineering. It is blocked by a decision about who holds the money.

The stack is complete and running. The data model is built and protected. The automation is in place. The loop carries a job from posting through matching, scheduling and reputation without a person in the middle. What is missing is the settlement step and the two services behind it — payments and email — and both of those wait on answers rather than on time. Those answers are set out in Where it stands.