Skip to main content

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

VerticalLanding templateChatbot endpointBooking CTA
church/s/[vanity_slug] (BrandSalesChatbot + UnifiedTemplate)/api/chatbot/demoBook a walkthrough → cal.com
funeral/preview/[slug] (ServiceBusinessTemplate, FuneralPreview)No chatbot on previewBook a demo → /funeralwiseai/book
vet/preview/[slug] (ServiceBusinessTemplate, VetPreview)No chatbot on previewBook 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_token in 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_at timestamp 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
  • 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_expect JSONB: ≥ 10 keys — FOUNDER REQUIREMENT
  • custom_staff: ≥ 4 entries with real names + titles (NOT placeholder "Visiting FUMC Folder:" as a name)
  • custom_ministries: ≥ 4 entries
  • beliefs: ≥ 3 entries with denomination-appropriate theological content
  • At least one pastoral staff member with a real name in custom_staff
  • tradition_family matches the actual denomination (Reformed ≠ Arminian, Anglican ≠ Baptist)
  • At least 3 FAQ entries in church_knowledge_base for 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_family is Reformed/Calvinist: chatbot beliefs response must reference Reformed theology (TULIP, covenant, sovereignty), NOT generic evangelical or Arminian language
  • IF tradition_family is Catholic: response must reference sacraments, Magisterium
  • IF tradition_family is Anglican/Episcopal: response must reference Book of Common Prayer, creeds
  • "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 checks
  • outreach_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:

SurfaceWrite pathLead source
Smart Quote WizardPOST /api/local-business/demo-lead (public, rate-limited)form
Demo chat (capture_lead_demo / book_quote_demo tools)/api/chatbot/demo → handleBusinessDemo persists in-toolchatbot
Browser voice call (LocalBusinessProspectCoordinatorAgent.capture_lead)POST /api/voice/local-business-lead with is_demo: truevoice

Must:

  • Every captured demo lead lands in local_business_leads tagged metadata.is_demo = true (jsonb marker — there is no is_demo column)
  • An internal founder alert email fires on capture (via @/lib/internal-notifications sendEmail, 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-completed is_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
  • "Share with Board" button present
  • Deep-link to /onboard for 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 noindex meta 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:

ModuleWeightFAIL condition
address25No street address resolvable for the church
content35No entries in church_knowledge_base for this church
lens20tradition_family null, wrong, or mismatched to denomination
scorecard20No pastoral staff; beliefs null; chatbot classification = GENERIC
ScoreVerdictAction
≥ 80GODemo-ready for campaign send
50–79HOLDRun enrich --apply, re-audit before send
< 50NO-GOManual 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:

  1. demo-verify url <demo_url> — 11 structural checks PASS (exit code 0)
  2. demo-verify url <demo_url> — all chat scenario checks PASS (exit code 0)
  3. demo-verify click-through --token <full_token> — PASS (redirects to /s/, not /pro-website)
  4. demo-prep audit <church_id> — score ≥ 80 (GO)
  5. outreach_contacts.demo_prep_issues.chatbot_validated = true
  6. outreach_contacts.demo_prep_issues.chatbot_classification = 'SPECIFIC'
  7. what_to_expect ≥ 10 keys — FOUNDER REQUIREMENT
  8. custom_staff ≥ 4 real staff entries (not placeholder text as a name)
  9. beliefs ≥ 3 denomination-appropriate entries
  10. 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_at set; 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_contacts and premium_churches
  • demo-verify tool output on 4 demos (Cornerstone Baptist, Mimico Baptist, St. Stanislaus Kostka, full click-through)
  • demo-prep audit tool output on 1 NO-GO prospect
  • Reading demo-verify/SKILL.md, demo-prep/SKILL.md, and expected-output-methodology.md

Founder interview required to confirm:

  • Logo/video/hero_slideshow as hard MUST vs. soft WANT
  • Whether the 10-key what_to_expect bar 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