Demo Prospect — Expected Output Spec
Purpose
This spec defines, per vertical (church / funeral / vet), exactly what a scrape-and-provisioned cold-outreach demo MUST contain and MUST NOT show. It is the acceptance gate for campaign readiness — if code or data does not match this spec, the demo is NOT campaign-ready.
The prospect flow is: cold email → /p/[token] click → demo page → chatbot interaction → booking CTA.
Vertical Matrix
| Vertical | Landing template | Chatbot endpoint | Booking CTA |
|---|---|---|---|
| church | /s/[vanity_slug] (BrandSalesChatbot + UnifiedTemplate) | /api/chatbot/demo | Book a walkthrough → cal.com |
| funeral | /preview/[slug] (ServiceBusinessTemplate, FuneralPreview) | No chatbot on preview | Book a demo → /funeralwiseai/book |
| vet | /preview/[slug] (ServiceBusinessTemplate, VetPreview) | No chatbot on preview | Book a demo → /vetwiseai/book |
Touchpoint 1: Cold Email Received
State: outreach_contacts.status = 'provisioned' or 'sent'
Should See (all verticals):
- Personalized greeting using the pastor's or director's first name (NOT "Hi there" or "Hi Pastor,")
- Organization name in the subject line and body
- Link to
/p/[token]— full token, not truncated - CASL-compliant footer with physical address (125 Concession Street, Ingersoll, ON)
- Unsubscribe link
/api/outreach/unsubscribe/[unsubscribe_token] - Church/organization vertical matching the recipient (Baptist church gets church email, not funeral home copy)
Should NOT See:
- Template artifacts:
{{,${,null,undefined,[CHURCH_NAME],[PASTOR_NAME] - Placeholder pastor name "Pastor," (empty first name fallback must render "Hi Pastor,")
- Dead links (any
<a href>returning non-2xx) - Truncated
starter_kit_tokenin the/p/URL — must be the full token string
Success Criteria:
- All
<a href>links return HTTP 200 (or 302 to a 200) /p/[token]→ redirects to correct demo page (see Touchpoint 2)/api/outreach/unsubscribe/[token]→ HTTP 200
Touchpoint 2: /p/[token] Click-Through Redirect
Route: src/app/p/[token]/route.ts
Should See (church vertical):
- HTTP 302 redirect to
/s/[vanity_slug]?ref=outreach_[token]&email_variant=[A|B|C] outreach_contacts.pro_website_clicked_attimestamp stamped (DB write — NOT checked here, but expected)
Should See (funeral / vet vertical):
- HTTP 302 redirect to
/preview/[slug]?ref=outreach_[token]
Should NOT See:
- Redirect to
/pro-website(marketing page) — this is the failure mode when the token is truncated - Redirect to any 404 or error page
- Missing
ref=outreach_*param in the destination URL
CRITICAL — Token truncation bug discovered 2026-05-20:
The SKILL.md example uses a shortened token prefix (sprint1-71bf6b91e0) for display. The actual
starter_kit_token stored in outreach_contacts is the full string (e.g.
sprint1-71bf6b91e0c148f1bedc4ab1eaae0b5a-6a393fed780b862b). The /p/[token] route does an exact-match
lookup — a shortened token returns no match and falls through to the /pro-website fallback.
Always pass the full token when running click-through verification.
Success Criteria:
demo-verify click-through --token <full_token>exits with code 0 (SHIP)- Final URL contains
/s/(church) or/preview/(funeral/vet) - Final URL contains
ref=outreach_[full_token]
Touchpoint 3: Demo Page Loads (Church Vertical — /s/[slug])
Route: src/app/s/[slug]/page.tsx
Should See:
- HTTP 200
- Page title = organization name (not "ChurchWiseAI" or blank)
- Page loads at scroll position 0 (not anchored to chatbot)
- Inline chatbot widget (BrandSalesChatbot) visible in body
- Floating FAB (AI Assistant button) visible
- Trust strip with three links:
- "How our AI stays safe" →
/ai-safety - "HEAR protocol" →
/hear - "Book a walkthrough" →
https://cal.com/john-moelker/churchwiseai-demo
- "How our AI stays safe" →
- Zero console errors from own-origin scripts
- Zero CSP violations
- Zero network failures for own-origin assets
Data quality MUST (per demo-prep scorecard thresholds):
what_to_expectJSONB: ≥ 10 keys — FOUNDER REQUIREMENTcustom_staff: ≥ 4 entries with real names + titles (NOT placeholder "Visiting FUMC Folder:" as a name)custom_ministries: ≥ 4 entriesbeliefs: ≥ 3 entries with denomination-appropriate theological content- At least one pastoral staff member with a real name in
custom_staff tradition_familymatches the actual denomination (Reformed ≠ Arminian, Anglican ≠ Baptist)- At least 3 FAQ entries in
church_knowledge_basefor the church
Should NOT See:
- Empty hero (blank section with no image, no video, no slideshow)
- Any lorem ipsum, placeholder, or scraped-raw text used verbatim as content
- Wrong tradition content (e.g. Baptist church showing Catholic liturgical language)
- Broken booking CTA (dead cal.com link)
UNRESOLVED DATA GAPS observed 2026-05-20:
Even score=100 demos in the current batch have logo_url=null, featured_video_url=null,
hero_slideshow_keys=null. The founder's stated quality bar includes all dashboard fields
populated. This spec sets these as MUST items pending founder confirmation in the interview.
Conditional:
- IF
tradition_familyis Reformed/Calvinist: chatbot beliefs response must reference Reformed theology (TULIP, covenant, sovereignty), NOT generic evangelical or Arminian language - IF
tradition_familyis Catholic: response must reference sacraments, Magisterium - IF
tradition_familyis Anglican/Episcopal: response must reference Book of Common Prayer, creeds
Links:
- "Book a walkthrough" →
https://cal.com/john-moelker/churchwiseai-demo - Trust strip →
/ai-safety,/hear
Success Criteria:
demo-verify url <demo_url>exits with code 0 (SHIP)- All 11 structural checks PASS (HTTP, scroll, widget, FAB, trust strip, console, CSP, network)
- All chat scenarios PASS (memory, scroll lock, email guard)
demo-prep audit <church_id>score ≥ 80 (GO)
Touchpoint 4: Chatbot Interaction (Church Vertical)
Endpoint: /api/chatbot/demo or /api/chatbot/stream with demo mode
Should See:
- Chatbot responds to "What time are your services?" with a specific time (NOT "I don't know" or generic fallback)
- Chatbot mentions the church name within the first or second response
- Chatbot is denomination-aware — Reformed answer for Reformed church, Catholic answer for Catholic church
- Chatbot asks for email address before attempting to send information ("What's your email address?")
- Memory across turns: follow-up question references content from turn 1
- Scroll lock: typing in chatbot does not scroll the page
- Response delivered within 8 seconds (latency acceptable for demo)
Should NOT See:
- "I don't have specific information about..." for basic questions (service times, beliefs)
- "GENERIC" classification from
demo_prep_issues.chatbot_classification— this means the chatbot answered generically, not with church-specific data - Any banned phrases (absolute confidentiality promises, clergy-penitent privilege claims)
- Chatbot attempting to send email without asking for address first
Success Criteria:
demo-verify url <demo_url>(with chat scenarios) PASS on all 6 chat checksoutreach_contacts.demo_prep_issues.chatbot_classification = 'SPECIFIC'(not 'GENERIC')outreach_contacts.demo_prep_issues.chatbot_validated = true
Touchpoint 4b: Demo Lead Capture — Local-Business Demos (2026-06-11)
When a LOCAL-BUSINESS prospect (plumber/roofer/vet/etc. — /s/[slug] →
HomeServicesDemo) interacts with their demo, the interaction is CAPTURED as a
demo lead and the FOUNDER is alerted immediately. Three capture surfaces:
| Surface | Write path | Lead source |
|---|---|---|
| Smart Quote Wizard | POST /api/local-business/demo-lead (public, rate-limited) | form |
Demo chat (capture_lead_demo / book_quote_demo tools) | /api/chatbot/demo → handleBusinessDemo persists in-tool | chatbot |
Browser voice call (LocalBusinessProspectCoordinatorAgent.capture_lead) | POST /api/voice/local-business-lead with is_demo: true | voice |
Must:
- Every captured demo lead lands in
local_business_leadstaggedmetadata.is_demo = true(jsonb marker — there is no is_demo column) - An internal founder alert email fires on capture (via
@/lib/internal-notificationssendEmail, defaults to john@churchwiseai.com) with business name, capture surface, contact, need, and a deep link to/founder/[token]/growth/demo-leads - The GCC surface
/founder/[token]/growth/demo-leads(API/api/founder/growth/demo-leads) lists all demo leads newest-first, paginated - The founder alert is best-effort: a send failure NEVER blocks the lead write or changes the prospect-facing response
Must NOT:
- The real (unsold) business owner must NEVER be notified for a demo lead — suppressed at create, dedupe-upgrade, AND the call-end flush (
/api/voice/local-business-call-completedis_demo guard) - The demo UX must never wait on, or surface, the capture write (wizard POST is fire-and-forget; chat tool failures are swallowed)
Touchpoint 5: Demo Page — Funeral / Vet Vertical (/preview/[slug])
Route: src/app/preview/[slug]/page.tsx
Should See:
- HTTP 200
- Correct template rendered: FuneralPreview (for funeral), VetPreview (for vet)
- Organization name in heading
- Booking CTA visible and linked to the correct vertical:
- Funeral: →
/funeralwiseai/book - Vet: →
/vetwiseai/book
- Funeral: →
- "Share with Board" button present
- Deep-link to
/onboardfor activation
Should NOT See:
- Church template rendered for a funeral home (wrong vertical)
- Chatbot widget (preview pages do NOT have a chatbot — by design)
- Indexed by search engines (page must have
noindexmeta tag) - Page accessible after 30-day TTL (preview_expires_at check)
Success Criteria:
- HTTP 200, correct template, booking CTA present and linked correctly
demo-verify url <preview_url>structural checks pass (chat scenarios skipped — no chatbot expected)
Demo-Prep Scorecard Reference
The demo-prep audit tool scores each prospect 0–100 across four modules:
| Module | Weight | FAIL condition |
|---|---|---|
| address | 25 | No street address resolvable for the church |
| content | 35 | No entries in church_knowledge_base for this church |
| lens | 20 | tradition_family null, wrong, or mismatched to denomination |
| scorecard | 20 | No pastoral staff; beliefs null; chatbot classification = GENERIC |
| Score | Verdict | Action |
|---|---|---|
| ≥ 80 | GO | Demo-ready for campaign send |
| 50–79 | HOLD | Run enrich --apply, re-audit before send |
| < 50 | NO-GO | Manual review required; do NOT send |
Campaign-Level Quality Bar Summary
For a church demo to be campaign-ready ALL of the following must be true:
demo-verify url <demo_url>— 11 structural checks PASS (exit code 0)demo-verify url <demo_url>— all chat scenario checks PASS (exit code 0)demo-verify click-through --token <full_token>— PASS (redirects to/s/, not/pro-website)demo-prep audit <church_id>— score ≥ 80 (GO)outreach_contacts.demo_prep_issues.chatbot_validated = trueoutreach_contacts.demo_prep_issues.chatbot_classification = 'SPECIFIC'what_to_expect≥ 10 keys — FOUNDER REQUIREMENTcustom_staff≥ 4 real staff entries (not placeholder text as a name)beliefs≥ 3 denomination-appropriate entries- Tradition-appropriate voice and lens confirmed
Current campaign cohort (as of 2026-05-20):
- Total outreach_contacts with tokens: 100 (all church vertical — no funeral/vet prospects provisioned yet)
- Status distribution: provisioned=89, sent=10, clicked=1
- GO (≥80): 11 (11%) — all 11 have
sent_atset; these are the emails already sent - HOLD (50–79): 26 (26%)
- NO-GO (<50): 63 (63%)
DRAFT NOTE
This spec was drafted by a Demo Integrity Auditor agent (2026-05-20) from:
- Live Supabase query results against
outreach_contactsandpremium_churches demo-verifytool output on 4 demos (Cornerstone Baptist, Mimico Baptist, St. Stanislaus Kostka, full click-through)demo-prep audittool output on 1 NO-GO prospect- Reading
demo-verify/SKILL.md,demo-prep/SKILL.md, andexpected-output-methodology.md
Founder interview required to confirm:
- Logo/video/hero_slideshow as hard MUST vs. soft WANT
- Whether the 10-key
what_to_expectbar is firm or adjustable - Minimum staff count (draft says ≥4; founder confirmation needed)
- Whether funeral/vet demo pages require a live chatbot or preview-only is acceptable
- Whether click-through token truncation in SKILL.md examples should be fixed