How it works, Settings and Profile, brought into the language the rest of the
app now speaks. All three were built early and left alone: stacks of white cards in a narrow
column, describing a product with a quarter of the features it has today. Two of them also
told people things that were not true. Rebuilt as hairline sections with rails, with every
number computed from the code that charges it.
Scope /how-it-works, /settings, /profile and /profile/:id, both account typesStatus Committed to main as 202dba2, 5e42f8d and 3e0418e, and deployed to tour-dash.pages.dev on 2026-09-05
01
How it works
Five identical cards in one column, describing four features, on a product that
now runs three marketplaces and nineteen kinds of work.
Before. Four steps and a single fee example, in five boxes of the same weight.
Six sections with a contents rail, divided by hairlines rather than boxed. The rail is the only navigation on a page that is otherwise all reading.
A side toggle. The page opens on your own side and lets you read the other one. An agent choosing between two applicants is looking at a decision those applicants also see a screen for, and now they can read it.
Both catalogues in full, the nine agent service types and the ten trades grouped by moment, read from SERVICE_TYPES and PROVIDER_TRADES so the page cannot drift from the app.
Three kinds of deal. Job, lead and referral compared by who pays, when the money moves and what we take. Below sm the four columns stack as blocks, because a table that clips with no affordance is worse than no table.
The fee curve, read at five prices, from splitForPrice, and the lead curve at four from leadSplit. The taper is now visible instead of asserted from one example.
Where the money sits. Escrow on a job, the 72-hour lead dispute window, why a referral is tracked and not held, Stripe payouts gating a booking, and the wallet's three directions.
A map of the app, filtered by side, plus the public job board at /jobs.
Two steps that existed in the app and were mentioned nowhere here: sending a job straight to named people, and receiving one that way.
Both catalogues, generated from the same constants the posting flows read.The taper, at real prices. Nothing here is typed in; every figure is computed.
Phone. Both fee tables fit the 342px column with nothing clipped.The vendor side. Six steps instead of five, and the app map drops the pages a vendor does not have.
02
Settings
Here the design problem and the honesty problem were the same problem. The page
looked like a settings page while almost nothing on it did anything.
Before. This form collected a card number and a CVV into React state, saved nothing, and showed "Card added successfully!".
The card form is gone.stripe-checkout already creates and reuses a Stripe customer for the payer, so the card genuinely lives at Stripe and there was never anything here to save. The section says that instead.
The support form is gone. It thanked you and dropped the message. SUPPORT_EMAIL is null until there is an inbox, and the section says so rather than pretending.
Three notification switches are gone. Nothing sends email, SMS or push. In-app notifications are real, and are described.
Eight sections became eight better ones, grouped in the nav into Your account and Policies and help. Below md the row scrolls the section you picked back into view instead of leaving it off the left edge.
Privacy and terms were two-paragraph scaffolding. They now describe what this app does: what is held, what Stripe holds instead, who can see an address, and when contact details are exchanged.
Fees stopped duplicating How it works. The rule and the anchor stay here; the full tables are one link away.
The card shells came off. Sections are a heading, a hairline and blocks. PayoutSetup keeps its card, because it is the one interactive surface on the page.
After. No card fields, and the section explains where the card actually is.Dark. Same tokens, no second design.
Still open. The cancellation terms are unchanged in substance, and nothing
in the code enforces them: there is no refund logic behind the 24-hour rule or the 50% fee.
They read as policy on the page and are a manual process behind it.
03
Profile
A header card, two stat tiles and a reviews panel, with every credential
rendered as the same grey pill.
Before. Brokerage, licence, key and MLS board as one undifferentiated pill row, and the score said twice within one screen.
The person is the subject. Their name is the h1, not "My profile", with the avatar beside it and insurance and lockbox access as marks under the title.
Facts are separated by kind in a rail: rating and finished jobs, then trade, coverage, turnaround, rate and licence for a vendor, or brokerage and licence for an agent, then MLS boards as the list they are.
The score is said once.
The stat tiles are gone. Earnings sit in the rail and link to the wallet, which is the ledger those figures have to agree with.
An agent can hire a vendor from their profile. The wizard already deep-links on trade and provider, so the button opens straight on the job form with that person chosen. Leave review steps down to outline beside it, keeping one accent on the surface.
Reviews are a list, and both empty states say what produces the first review rather than "No reviews yet" alone.
On a phone the rail sits between About and Reviews, placed explicitly in the grid rather than reordered, so a screen reader gets the same order the eye does.
After. One accent on the surface, and it is the action the page exists for.Phone. The facts come before the reviews, which is the order the decision is made in.
04
How it was verified
Headless Chrome over CDP against /demo, which makes no Supabase
requests.
Check
Result
Widths
390, 768, 1280 and 1440. scrollWidth equals clientWidth at every one, and no table is wider than its column.
Themes
Light and dark on all three pages.
Both sides
Agent and vendor, on How it works and on Profile.
The hire link
Lands on /hire?trade=listing-photography&provider=… with the trade and person set.
Console
Clean on all three.
Types and build
tsc --noEmit clean, npm run build succeeds.
05
Open questions
There is no support inbox.SUPPORT_EMAIL in Settings.tsx is one constant away from a working section.
The cancellation policy is not enforced anywhere in code.
The nine agent service types are still Title Case — "Home Showings", "Pick Up Placement", "Admin Tasks" — against the locked sentence-case convention. They sit beside the ten sentence-case trades on How it works, where the mismatch is now visible. Changing them touches every screen that renders a service type.