Why two packages: Nafeesa + Annie are gifted Brand Previews so Rothstein can run the full 8-stage process end-to-end without giving away the farm. Same workflow, same emails (gifted-aware via {ifGifted}…{endif} in templates), smaller deliverables. Future paying clients flip the 🎁 Gifted checkbox off and the Pro deliverable seed + Pro outreach template are used.
The 8-Stage Pipeline
1 · Leadname on radar
→
2 · Outreachemail sent
→
3 · Discoveryform back
→
4 · Pre-Prodplan locked
5 · Shoot WeekT-7 to T-0
→
6 · Postedit / retouch
→
7 · Deliverydrafts + final
→
8 · Closeoutreview / referral
At Each Stage — what you owe vs what you need
1 Lead
Owe:30 sec research (IG, brokerage)
Need:Nothing — she doesn't know you yet
→ Send outreach email · move card
2 Outreach
Owe:Patience · 1 nudge at 3d · 1 call at 7d
Need:Discovery form submission
→ Form arrives · move card
3 Discovery
Owe:Read form 2× · build brandProfile · list gaps · propose 3 shoot dates
📝 Google Form
"Brand Discovery Questionnaire"
built via Apps Script under pvme2013@gmail.com
→
🧠 brandProfile
per-client object on each card
voiceTriangle · feelingTriangle · locationVibe · fixGoal
→
📧 Templates
interpolate {brandVoice}, {locationVibe}, etc.
→
📤 mailto:
opens default mail client
activity log auto-records
Why not Gmail API directly: No OAuth on the dashboard. mailto: matches the existing PVME pattern (Send Proofs, Pre-Shoot Reminders in the Headshot module). Works on every device including iPhone. The compromise: the dashboard can't auto-detect replies — Rothstein clicks ✓ Mark reply received to flip the card to ✓ Replied. Future upgrade path: Gmail OAuth in a Supabase Edge Function once active client count crosses ~10.
Repeats her fix-goal · honest upsell to Brand Pro for gifted clients
10
Closeout / Testimonial Request
Closeout
Asks for Google review + tag + referral
11
Just Touching Base
any
Generic blank canvas for one-off notes
Gifted-aware branching: Templates 4 / 5 / 6 / 8 use {ifGifted}…{else}…{endif} blocks so the same template renders Brand Preview language (1 outfit, 1 location, 4 deliverables) for gifted clients and full Brand Pro language for paying ones. Form-driven: Templates 4 / 5 / 6 / 8 / 9 pull from each client's brandProfile — her own words from the discovery form become the engine.
Template picker behavior: Already-sent templates are hidden from the dropdown by default (toggle "Show N already-sent templates too" to reveal for resends). When every stage-relevant template has been sent, the picker shows a green "all sent" badge instead of an empty list.
Email reply detection — the mailto: workaround
Card chip
Days since last send
Card border
Suggested action
📤 Sent today / Nd ago
0–2
neutral
Wait — give her the polite window
📬 Awaiting reply · Nd
3–5
amber
Consider sending Discovery Form Nudge
🚨 No reply Nd
6+
red
Call her or write a personal note (template #10)
✓ Replied
—
green
Move to next stage step
How sent emails are tracked: Clicking 📧 Open in Email appends 📧 Opened template "Label" to the client's notesLog. emailStatus(client) walks the log to find the most recent send. When Rothstein clicks ✓ Mark reply received, it appends ✓ Reply received from email@… — if that timestamp is more recent than the last send, the card flips to ✓ Replied.
60-second auto-refresh: A setInterval(60_000) re-renders cards so day counters and urgency tags stay current without a reload. Skipped while a modal is open (don't clobber edits).
⚖️ Checks & balances — guardrails before any email goes out
Client communication is the product. Nothing fires without a deliberate click. Three guards stand between an idea and an outgoing email.
🛂 Guard 1 — Pre-Send Confirmation Dialog
Clicking 📧 Open in Email no longer fires mailto: directly
Opens a confirm dialog showing:
• Recipient name + email
• Template number + label
• Substituted subject line
• Expandable full body preview
• Cancel / Send buttons
Last chance to catch a wrong client, wrong template, or wrong tone
⚠️ Guard 2 — Validation Warnings
The dialog surfaces issues before send:
• Template uses {brandVoice} but brandProfile is empty
• Template uses {shootDate} but no shoot date set
• Template uses {deliveryDate} but no delivery date set
• Template uses {openGapsList} but no open gaps
• Out-of-sequence detection via TEMPLATE_PREREQS graph
Each warning shows next to ⚠️ Heads up; you can override but must look it in the eye first
🛡 Guard 3 — Stage-Advance Guards
checkStageAdvance(client, newStage) runs on:
• Drag-drop between Kanban lanes
• Next Steps CTA "Move to X" buttons
Triggers a confirm dialog if:
• Skip-forward: jumping more than 1 lane in a single drop
• Backwards move: from a later stage to an earlier one
• Unfinished critical steps: enumerates what's still incomplete in the current stage
Cancel keeps state intact; Confirm logs the move to activity
TEMPLATE_PREREQS — which template should come before which
Template
Should typically follow
Why
3 · Discovery Form Nudge
1 Promo Outreach or 2 Initial Outreach
Can't nudge if outreach didn't go out
4 · Discovery Recap
1 Promo Outreach or 2 Initial Outreach
Recap echoes the form — assumes she filled it after outreach
5 · Pre-Production Plan
4 Discovery Recap
Pre-prod builds on the brand-anchor confirmation the recap establishes
6 · Shoot Day Confirmation (T-1)
5 Pre-Production Plan
T-1 confirms the plan she signed off on
8 · Revision Confirmation
7 Draft Delivery
Can't confirm revisions without drafts
9 · Final Delivery
7 Draft Delivery
Final assumes the draft + revision cycle happened
10 · Closeout / Testimonial
9 Final Delivery
Asks for a review of files that have been delivered
Override philosophy: Every warning is overridable. You're the strategist; the guards are decisions made loud, not decisions made for you. Sometimes you legitimately want to send Pre-Prod before Recap (e.g., the recap content is folded into a phone call instead). The system says "you sure?" — you say "yes" — it logs and moves on.
💬 Email Thread — per-client conversation record
Until Gmail OAuth ships (deferred until 10+ active clients), the dashboard can't read your inbox. Until then, replies are captured by pasting her actual email text into a dedicated box on her card. This preserves the full conversation permanently with the client, regardless of whether the mailto: send happened from the dashboard or from your mail client directly.
📋 Paste-her-reply box
Blue-tinted prominent textarea at the top of the Email Thread section
Date picker (defaults to today)
💾 Save reply button — pushes incoming entry to thread + logs activity + flips card chip to ✓ Replied
"Mark Reply Received" button on the email status panel now SCROLLS + FOCUSES this box so capturing the actual text is the obvious move, not just a metadata flag
📜 Thread display
Newest first; chronological scroll back through every exchange
Outgoing entries (gold-tinted): template label, subject, collapsible body
Incoming entries (blue-tinted): full reply text shown inline, × button to remove a stray paste
When you want strategic help drafting a response, copy her pasted text from the thread + drop in a Claude conversation
Why the dashboard stores rendered bodies on outgoing entries:{firstName}, {brandVoice} etc are substituted at send time. The thread preserves what she actually received, not the template skeleton. Useful when you re-read the conversation 3 months later and want to know what exactly went out.
🅿️ Parking Lot view — accountability at a glance
Third view button alongside Kanban / List. Built for one question: "Where's the ball right now?" A future assistant scanning the board should be able to answer it without opening any card.
🎯 Waiting on YOU
No email sent yet (need to send outreach)
She replied — your move (next step text included)
Sorted by urgency: overdue (red) → warn (amber) → fresh (green); alphabetical within tier
Classify logic:classifyClient(client) calls emailStatus(). No email yet → you (fresh). Reply marked received → you (with next-step text). Outgoing pending → her (with urgency tier). Closeout clients are excluded — they're done, not in flight.
📁 Project folders — each client linked to a local directory
Every client card connects to a local folder under a single parent. Consolidated on 2026-06-16 from ~/Documents/Projects/{Client} Realtor Branding Project/ (mixed with other projects) into ~/Documents/Projects/Realtor Project/ — the dedicated parent for the productized branding business.
🗂 Folder structure
~/Documents/Projects/Realtor Project/ — parent for all branding clients
Nafeesa Bashir-James/ — full name as subfolder
Annie Rushing/
Each subfolder holds: Client Notes · Shot List · Script · Locations · Wardrobe · Contracts-Releases · Final Deliverables · Pricing Notes · README.md
client.folder field = subfolder name (e.g., "Nafeesa Bashir-James")
Combined: full path shown in the modal's 📁 Project Folder block
Three actions: 📋 Copy path · 🌐 Browser view (file://) · 📂 Show in Finder ⓘ (instructions)
Finder workflow: copy path → ⌘⇧G in Finder → ⌘V → Enter
Why not auto-open Finder: browsers can't open Finder windows directly for security reasons. The copy-path + toast notification + ⌘⇧G shortcut workflow is the most reliable cross-browser path. After the first open, the folder appears in Finder's Recent Folders for one-click reopens.