Tour Dash

Every email Tour Dash sends, with a B version of each.

Twenty notification emails and four account emails can reach a user today. Each one is shown here as it ships, next to a rewrite rendered through the same email code, with what changed and what a test would measure. Four notification emails have gone out so far, so most of B should ship as a plain fix, and only seven emails are worth running as real tests.

10 September 2026 Source supabase/functions/_shared/notification-templates.js Names and addresses in the samples are made up Shipped the same evening The bell, too
01

What goes out today

Every notification email is live. Each database trigger and edge function that writes one was checked against the production project, and all 20 keys have a producer installed. Volume is the thing missing.

20
notification emails wired up, plus 4 account emails switched on in Supabase
4
notification emails sent so far: 3 job invites and 1 application
3 of 14
accounts that have never confirmed their email
7
emails where a real A/B test is worth running

Jump to an email:

02

Fixes that apply to every email

None of these need testing. They are errors, and splitting the few sends there are between an error and its correction would only delay the correction.

ProblemWhat it looks likeThe fix
The job title reads as a nounNine of the eleven live listings are titled "Home showings", which is a service type. The templates drop it into sentences, so agents get "Mira Kovacs applied to cover Home showings" and "Home showings is covered".Call the job a showing (lowercase, singular) and name the place: the street in the body, the town in the subject.
Day before month"Friday, 18 September at 9:00 AM". Every listing is in New Jersey."Friday, September 18". Change FMDD FMMonth to FMMonth FMDD in email_when() and send_due_reminders(), and the day order in whenFromParts(). The two formatters were checked to agree, so change both in one commit.
Subjects that hold back the factsMost subjects name the job type, which is the same on nearly every job. From the inbox list you cannot tell one showing from another, or whether an invite pays.Put what the reader decides on in the subject: where, when, and the amount when money is involved. Drop ".00" from whole dollars.
Preview text that repeats the subjectThe preview line is the first sentence of the body, which usually restates the subject word for word.Write a separate preview line for each email that adds the next fact.

One problem is a bug in how email is sent, not copy, and a second claim made here turned out to be wrong.

03

Can this be tested yet?

Not with confidence. Telling a 40% response rate from 55%, at the usual 95% confidence and 80% power, takes about 170 recipients in each version, or 340 sends of a single email. Tour Dash has sent four. A test on any one email would run for months at today's volume and still be noise.

So the order is: ship section 02 and every email marked "Fix, no test" to everyone now, build the test plumbing once so it is ready, then switch tests on as volume arrives. Until a version passes about 170 sends, read the results as a check that B does no harm, not as a winner.

PieceWhereWhat it does
A variant columnnotifications.variantSet in send-notification before rendering, by hashing the user id with the test name. The same person always gets the same version, across emails and resends.
B templatesNext to templatesKeyed the same way. The renderer picks by variant and falls back to A when an email has no B, so only emails under test change.
Attributable clicksButton linksAdd ?n= and the notification id, so the app can record which email a visit came from. Tag each Resend send with the key and variant so delivery events split the same way.
Outcome, not opensQueries on existing tablesApple Mail loads images on its own for privacy, so open rates partly count machines. Each test measures something the database already records, inside a fixed window after the send.
04

The test queue

In the order worth running, highest likely volume and clearest outcome first. Every test compares B with A after the section 02 fixes, so it measures the idea rather than the typo.

EmailWhat B triesSuccess meansWindow
1. A job sent to youPay, town and day in the subjectThe invited agent responds24 hours
2. New applicationTown and day in the subject, a named buttonThe application is approved or declined24 hours
3. Welcome (agent account)One first step: post a showingFirst job posted7 days
4. Confirm your email addressSubject says what confirming gets themAddress confirmed24 hours
5. How did it go?Tap a number to rateReview written7 days
6. Your money is on its wayThe review becomes the buttonReview written by the covering agent7 days
7. Nobody can book you yet"One step left" framingPayouts switched on7 days
05

For the agent who posted the job

Seven emails, one of which B retires. Most of them ask this agent to decide something, so the subject has to carry enough to decide from.

06

For the agent covering the job

Ten emails. This agent is usually on the move, so the date, time and address do most of the work.

07

Leads

Two emails for agents who sell a referral lead.

08

Accounts and sign-in

The welcome comes from the notification system. The other four are Supabase Auth templates generated by supabase/email-templates/build.mjs.

09

What shipped the same evening

Everything on this page went live on 10 September, the seven test ideas included. With four emails sent, a test would not have finished for months, so B went to everyone and the test plumbing in section 03 was not built. The frames above are the review as it was written. What went live differs from B in these places.

EmailWhat shippedWhy
How did it go?One button, "Leave Mira a review", which opens that person's profile. No number buttons.Reviews are written on the profile page, which works today. Filling in a rating from a tapped number needs a route the app does not have yet.
Your money is on its way"Review Dana" opens the agent's profile, with the wallet as a text link.The same profile page, so nothing new was needed.
New application, Not this time"Others can still apply" and "went to someone else", not "other agents".The same emails go out for vendor jobs.
Contact details for the dayThe privacy line talks about contact details in general.The person to call can be the agent rather than the buyer.
Confirm your email addressThe button still says "Confirm email address".Whether confirming also signs someone in depends on the redirect, so the button does not promise it.
Every emailOther job types get their own word ("inspection", "open house", "door opening"), and a title that is not on the service list becomes, for example, "a handyman job".The labels come from src/lib/create-service-schema.ts.

Underneath the copy:

VerifiedResult
A real sendA probe job invite for the demo account went through the trigger, the function and Resend, and Resend reports it delivered. The subject named the sender, the $25 pay, Clifton and Fri, Sep 18. The probe row was deleted afterwards.
Notices already sentThe two real notices sent earlier in the day were replayed through the new renderer. Both rendered and answered "already sent", so nobody was mailed twice.
The functionsAll three redeployed with their JWT settings unchanged. The webhook still refuses an unsigned request, and the cancel function answers its preflight.
Odd inputA missing address, a missing date, the old day-first date, a vendor title and a 2 out of 5 review all produce a readable subject.

Still open: the rating link and the test plumbing are unbuilt. The in-app notices were left out of this pass and cleaned up afterwards, in section 10.

10

The bell, cleaned up the same way

The in-app notices had the same problems as the emails, so they got the same treatment later that evening. Each one now has a short title, one sentence that names the person, the job and the street, and a link to where the next step is. The bell cuts a message off after two lines, so the date only goes in where it changes what somebody does.

NoticeBeforeAfter
New applicationMira Kovacs applied to cover Home showings.Mira Kovacs applied for your showing at 412 Ridgewood Ave.
A counter-offerMira Kovacs will cover Home showings for $65.00.Mira Kovacs will take your showing at 412 Ridgewood Ave for $65. You posted $45.
You're bookedYou're booked for Home showings. It's on your calendar.Dana Whitfield booked you for the showing at 412 Ridgewood Ave on Fri, Sep 18.
Job sent to youDana Whitfield sent you Home showings.Dana Whitfield sent you a $40 showing at 412 Ridgewood Ave on Fri, Sep 18.
Not this timeThe agent went with someone else for Home showings.The agent chose someone else for the showing at 412 Ridgewood Ave.
Job called offThe agent called off Home showings. Your application closed with it.The showing at 412 Ridgewood Ave was called off, and your application closed with it.
Tomorrow at 5:00 PMTitled "Tomorrow: Home showings". You are covering Home showings Friday, 18 September at 5:00 PM.You are covering Dana Whitfield's showing at 412 Ridgewood Ave. Opens that day on the calendar.
Who to callTitled "Contact details for the day". The agent added who to contact for Home showings.The agent added who to contact for the showing at 412 Ridgewood Ave on Fri, Sep 18. Opens that day on the calendar.
Your showing is coveredTitled "Your booking is confirmed". Mira Kovacs is covering Home showings.Mira Kovacs is covering your showing at 412 Ridgewood Ave on Fri, Sep 18. Opens that day on the calendar.
Your cover pulled outTitled "A contractor withdrew". The contractor withdrew from Home showings at 412 Ridgewood Ave. The job is open again and the full amount is on its way back to your card.Mira Kovacs withdrew from your showing at 412 Ridgewood Ave. It is open again, and $55 is going back to your card.
Booking cancelledTitled "A booking was cancelled". The agent cancelled Home showings at 412 Ridgewood Ave.Dana Whitfield cancelled the showing at 412 Ridgewood Ave. You are paid $27.50 for holding the slot.
How did it go?Leave Mira Kovacs a review for Home showings. Opened the calendar.Leave Mira Kovacs a review for the showing at 412 Ridgewood Ave. Opens Mira's profile, where the review is written.
Your money is on its way$44.50 for Home showings has been released to you.$44.50 for the showing at 412 Ridgewood Ave has been released to you.
New reviewTitled "You have a new review". Same message.Dana Whitfield left you 5 out of 5.
Finish setting up payoutsTitled "Nobody can book you yet". Payouts are not set up on your account, so agents cannot book you. It takes a few minutes.Agents cannot book you until payouts are set up. It takes a few minutes.
Welcome to Tour DashPost a job when you need one covered, or take one that suits your day. Opened the home screen you were already on.Post a showing you need covered, and agents nearby can apply. Opens the page for posting one.
Your lead soldCarey Dunn bought your Montclair, NJ lead. The payout is yours once the 72-hour dispute window closes. No link.Carey Dunn bought your Montclair, NJ lead. The $36 payout is yours once the 72-hour dispute window closes. Opens the wallet.
Lead payout on holdTitled "A lead was disputed". Payout is on hold until it is looked at.The buyer of your Montclair, NJ lead opened a dispute, so the payout is on hold until it is reviewed.
VerifiedResult
Every trigger, against a real listingAn invite, two applications (one a counter-offer), a booking, a decline, a contact change, a reminder sweep, a completed job, a released payment and a review ran inside one transaction that was then rolled back. All eleven notices came out as in the table above. The notice count was 26 before and after, the contact row kept its original name, and no email request was left queued.
The edge functionsType-checked, then redeployed with their JWT settings unchanged. The webhook still refuses an unsigned request, and the cancel function answers its preflight.
The apptsc on tsconfig.app.json passes with the demo change.

The 26 notices already in people's bells keep their old wording. They were written before this change, and most of them came from this week's testing.

11

Not covered here