Skip to main content

Pre-Dashboard Onboarding Wizard — Expected Output Spec

Why this spec exists

On 2026-05-25 Anthony (founder's nephew, IT professional) signed up for a free trial and described the existing onboarding as "a huge list of things to do for a free trial." The current SetupGuide.tsx renders an 8-required-step checklist inline above the empty dashboard on /admin/[token]/#home — the customer sees TODOs before they ever see an AI working.

Industry benchmarks (2026): >10-step wizards drop completion 30–50%; blank-state dashboards lose 84% of users in session 1; the top-quartile time-to-WOW is 2–5 minutes (knowledge/processes/seo-traffic-strategy-2026.md, see the SaaS onboarding research synthesis from the May 26 design proposal).

This spec defines the pre-dashboard guided wizard that replaces the long inline checklist for first-time customers. It ends at the customer interacting with their own AI agent — the "Meet Your Agent" reveal — and only then drops them into the dashboard.

Core UX promise

From magic-link click to hearing your own AI in under 10 minutes. Six short steps. Skip anytime. We'll do it for you if you'd rather (Phase 4 concierge fork).

The wizard is the FIRST surface the customer sees after the magic link. The existing dashboard-inline SetupGuide still exists for post-wizard finer tweaks (Pro Website hero images, FAQs, sharing) but is no longer the first impression.

The 6-step journey

#Step idTitleTypeForm componentWhat saves itEst. time
1welcomeWelcomestatic + concierge forkn/aClick "Let's go" or "Train it for me ($99)"30s
2church-profileYour churchreuse ChurchProfileFormChurchProfileForm"Save profile"2 min
3what-to-expectWhat visitors will hearreuse WhatToExpectFormWhatToExpectForm"Save"3 min
4office-hoursYour hoursreuse OfficeHoursFormOfficeHoursForm"Save hours"1 min
5theologyYour traditionreuse TheologySettingsTheologySettings"Save tradition"30s
6meet-your-agentMeet your AI agentNEW MeetYourAgentStepn/a"Take me to my dashboard"2 min

Total target time: ~9 minutes. Each step's estimate is displayed on its own header so the customer can pace themselves.

Step 1 — welcome (the concierge fork)

Layout

┌─────────────────────────────────────────────────────────────┐
│ ChurchWiseAI •━━━━━━━━━━━━━━━━━━━━━━• Step 1 of 6 │
│ │
│ │
│ Welcome, Pastor John. │
│ │
│ Your AI agent for Grace Community is almost │
│ ready. We'll be done in about 9 minutes. │
│ │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────┐ │
│ │ [Let's set it up │ │ [Train it for me │ │
│ │ together — 9 min] │ │ — $99 setup] │ │
│ │ │ │ │ │
│ │ You answer 5 short │ │ Send us your church │ │
│ │ questions. We do the │ │ website + a sermon. │ │
│ │ rest. Free for 14 days. │ │ Agent ready in 24h. │ │
│ └──────────────────────────┘ └──────────────────────┘ │
│ │
│ Skip — let me explore the dashboard first │
└─────────────────────────────────────────────────────────────┘

Behaviors

  • B1.1 — Greeting interpolates {member_name || 'there'} and {church_name} from the premium_churches row.
  • B1.2 — "Let's set it up together" advances to Step 2 + sets setup_current_step='church-profile'.
  • B1.3 — "Train it for me ($99 setup)" — Phase 4 wires this to Stripe + intake form. In Phase 2, the button renders as a disabled "Coming soon" pill with copy "We're launching this in the next few days — for now, please reach out at hello@churchwiseai.com." (The DRAFT button is present in the DOM but disabled, so Phase 4 can swap behavior without re-cutting the layout.)
  • B1.4 — "Skip — let me explore the dashboard first" sets setup_current_step='skipped' and navigates to /admin/[token] (the legacy dashboard, where the inline SetupGuide still renders for completeness).
  • B1.5 — No header chrome (no marketing nav, no chat widget) — bare wizard shell only. Reuses LayoutShell forceBare pattern.

Steps 2–5 — data collection (reuse existing forms)

Each step renders inside a StepShell component that provides:

  • Top-left logo + step indicator Step N of 6 + estimated time
  • Progress bar (N/6 filled)
  • Center: the reused form component
  • Bottom-right: [Save & continue →] (the form's existing save button)
  • Bottom-left: Skip this step (sets the step as skipped, advances to next)
  • Top-right: Skip — take me to my dashboard (sets setup_current_step='skipped', hard exit)

Save discipline

  • Every form save updates premium_churches.setup_current_step = '<next-step-id>' and setup_resumed_at = now() server-side BEFORE returning success to the client.
  • If the customer closes the tab mid-step, returning to /admin/[token] redirects them back to /admin/[token]/welcome with the saved step pre-selected.
  • Required fields enforced by the form components themselves (see existing spec at pro-website-setup-wizard.md §B5).

Vertical-aware copy

VerticalProvider.wizardCopy (NEW context field) supplies per-vertical labels:

VerticalStep 2 titleStep 3 titleStep 4 titleStep 5 title
churchYour churchWhat visitors will hearYour hoursYour tradition
funeralYour funeral homeWhat families need to knowYour hoursYour tradition (denomination context)
vetYour clinicWhat pet owners will hearYour hours(skip — no theological lens)
local_businessYour businessWhat customers will hearYour hours(skip)

For verticals that skip Step 5, the wizard renders 5 steps total. Step indicator shows Step N of 5 for those.

Step 6 — meet-your-agent (the WOW reveal)

Layout

┌─────────────────────────────────────────────────────────────┐
│ ChurchWiseAI ●━━━━━━━━━━━━━━━━━━━━━━● Step 6 of 6 │
│ │
│ │
│ Pastor John, meet Grace's AI receptionist. │
│ │
│ Your agent is trained on Grace Community's beliefs, │
│ service times, and visitor experience. Try it now. │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────┐ │
│ │ 💬 Chat with your agent │ │ 📞 Call your number │ │
│ │ │ │ │ │
│ │ [Embedded chat widget │ │ +1 (xxx) xxx-xxxx │ │
│ │ pre-loaded with their │ │ │ │
│ │ live data] │ │ [Copy number] │ │
│ │ │ │ │ │
│ │ Try: "What time is │ │ Voice plans only — │ │
│ │ Sunday service?" │ │ hidden for chat- │ │
│ │ │ │ only customers. │ │
│ └──────────────────────────┘ └──────────────────────┘ │
│ │
│ [Take me to my dashboard] │
└─────────────────────────────────────────────────────────────┘

Behaviors

  • B6.1 — Greeting interpolates {contact_name} + {church_name} + {vertical_term} (e.g., "AI receptionist" for churches, "intake assistant" for funeral homes, "front desk" for vets).
  • B6.2 — Chat card always present for any plan with chat enabled (Starter Chat, Pro, Suite, Pro Website). Renders ChatWidget in inline mode (not floating). Pre-seeded with the customer's church_id so the agent answers using their data.
  • B6.3 — Voice card present only for plans with voice (Starter Voice, Pro Voice, *_both, Suite). Voice card hidden for chat-only plans; chat card spans full width when voice is hidden.
  • B6.4 — Phone number resolved from church_voice_agents.twilio_phone_number (or telnyx_phone_number for new provisions). If voice agent is not yet provisioned (e.g., still in 24h Telnyx setup window), the voice card renders a "Your number arrives by email when ready" placeholder with [Notify me] button.
  • B6.5 — "Take me to my dashboard" button sets setup_current_step='complete' and navigates to /admin/[token]. The dashboard renders normally with the inline SetupGuide's celebration card AND OptimizationTips (the post-wizard finer tweaks).
  • B6.6 — Confetti animation fires once on first arrival at this step (framer-motion confetti, dismissible by clicking anywhere). Persisted in localStorage.cwai-wizard-confetti-shown=true so it doesn't repeat on re-entry.
  • B6.7Skip — take me to my dashboard (top-right) is hidden on Step 6 because the user is already at the destination — the only forward action is "Take me to my dashboard."

Redirect logic on /admin/[token]

Server-side, in the page component:

GET /admin/[token]:
load premium_churches row for token
if premium.setup_current_step is null:
redirect 302 → /admin/[token]/welcome
if premium.setup_current_step is one of (church-profile, what-to-expect, office-hours, theology, meet-your-agent):
redirect 302 → /admin/[token]/welcome (wizard resumes at saved step)
if premium.setup_current_step in ('complete', 'skipped'):
render dashboard normally (existing behavior unchanged)

A ?bypass=true query param skips the redirect (useful for QA + the "Skip" actions in the wizard which set state before navigating away).

DB schema

Migration 2026-05-26-premium-churches-setup-current-step.sql:

ALTER TABLE premium_churches
ADD COLUMN IF NOT EXISTS setup_current_step text NULL,
ADD COLUMN IF NOT EXISTS setup_resumed_at timestamptz NULL;

COMMENT ON COLUMN premium_churches.setup_current_step IS
'Pre-dashboard wizard cursor. NULL = never started (force-redirect to wizard). '
'One of: welcome, church-profile, what-to-expect, office-hours, theology, '
'meet-your-agent, complete, skipped. complete/skipped are terminal — '
'the customer is no longer force-redirected.';

COMMENT ON COLUMN premium_churches.setup_resumed_at IS
'Last time the wizard saved progress. Used for the 3-email recovery sequence '
'(immediate / +24h / +7d) when a customer abandons mid-wizard.';

Backfill: existing customers (i.e., setup_completed = true OR there are dashboard activity rows) are set to setup_current_step='complete' so they are never redirected to the wizard.

Save & continue later — recovery emails

When setup_resumed_at has been older than 24h AND setup_current_step is not in ('complete', 'skipped'), the lifecycle cron sends a "Pick up where you left off" email with a deep link /admin/[token]/welcome. Three emails total: +24h, +3d, +7d. After +7d the cron stops nagging and the customer is left alone.

(Lifecycle email plumbing already exists at src/app/api/cron/lifecycle-emails/route.ts — this spec just defines a new trigger condition.)

What this spec does NOT cover (deferred)

  • Concierge fork ($99 setup) full wiring — Phase 4. This spec only requires the disabled-button placeholder.
  • WiseAI Agency /business/[token] bridge — Phase 5. The wizard works for /admin/[token] plans (church, funeral, vet) only in Phase 2.
  • Pastor + tone slider — deferred. The agent uses default tone tied to the picked theological lens. A future spec can add tone customization inside the existing AgentPersonality form on the Training tab.
  • Pro Website hero photo upload — stays in the post-wizard inline SetupGuide (Pro Website plans still use the existing 8-step Pro Website wizard there).
  • Embed widget snippet display — stays on the dashboard Home tab share card.
  • Pastor View vs Tech View dashboard toggle — Phase 3.
  • Per-step analytics events — wire after first founder walkthrough confirms the step set is final (don't bake events into a moving target).

Acceptance criteria (Given/When/Then)

Wizard rendering

  1. Given premium_churches.setup_current_step IS NULL AND token matches an active row, when GET /admin/[token] runs, then HTTP 302 redirect to /admin/[token]/welcome and the wizard renders at Step 1.
  2. Given setup_current_step='theology', when GET /admin/[token] runs, then redirect to /admin/[token]/welcome and the wizard opens directly at Step 5 (theology).
  3. Given setup_current_step='complete', when GET /admin/[token] runs, then no redirect — the dashboard renders normally.
  4. Given setup_current_step='skipped', when GET /admin/[token] runs, then no redirect — dashboard renders + inline SetupGuide visible.

Step progression

  1. Given the wizard is at Step 2 (church-profile), when the customer fills the form and clicks "Save profile", then setup_current_step updates to what-to-expect server-side BEFORE the client receives success, and the wizard advances to Step 3 client-side.
  2. Given the wizard is at any step 2–5, when the customer clicks "Skip this step" at the bottom-left, then setup_current_step advances to the next step (the skipped step's form data stays whatever it was — usually empty), but the form is NOT marked complete.
  3. Given the wizard is at any step 1–5, when the customer clicks "Skip — take me to my dashboard" (top-right), then setup_current_step='skipped' and HTTP redirect to /admin/[token]?bypass=true.

Vertical-aware copy

  1. Given a cwa_starter_chat plan with vertical='funeral', when the wizard renders Step 2, then the title is "Your funeral home" not "Your church".
  2. Given vertical='vet', when the wizard renders, then Step 5 (theology) is absent from the step list and the indicator reads Step N of 5 not Step N of 6.

Meet Your Agent (Step 6)

  1. Given a chat-only plan, when Step 6 renders, then the Voice card is absent from the DOM and the Chat card spans the full row width.
  2. Given a voice-or-both plan with a provisioned twilio_phone_number, when Step 6 renders, then the Voice card displays the number, a Copy number button, and a "Try calling now" hint.
  3. Given a voice-or-both plan WITHOUT a provisioned phone yet, when Step 6 renders, then the Voice card shows the "Your number arrives by email when ready" placeholder with a Notify me button (no-op in Phase 2 — Phase 4 wires a real notification preference).
  4. Given the customer arrives at Step 6 for the first time, when the page mounts, then a confetti animation fires once and localStorage.cwai-wizard-confetti-shown is set to true.
  5. Given the customer arrives at Step 6 a second time (e.g., refreshes), when the page mounts, then no confetti.
  6. Given the customer clicks "Take me to my dashboard" on Step 6, then setup_current_step='complete' server-side and the browser navigates to /admin/[token] (no redirect-back-to-wizard loop).

Embedded chat reveal

  1. Given Step 6 renders the Chat card, when the customer types "What time is your service?" and submits, then the agent responds using THIS customer's church_id data (verified by intercepting the /api/chatbot/stream request and asserting church_id in the payload).

Recovery emails

  1. Given setup_resumed_at is 24h old AND setup_current_step is not terminal, when the lifecycle-emails cron runs, then a "Pick up where you left off" email is sent (template covered by a separate flow spec under knowledge/flows/onboarding-wizard-recovery.md — to be added in the same PR).

Regression hazards (what to verify in the Playwright spec)

  • Redirect loop — if Step 6 sets state correctly but the redirect logic on /admin/[token] doesn't match the terminal state, customers loop back into the wizard forever. Test 15 covers.
  • Cross-vertical breakage — change to VerticalProvider's wizardCopy must not regress existing dashboard tab labels (the same provider drives both). Test the funeral and vet variants of every step.
  • Form save partial state — if a form save updates DB but the server response races the client step advance, the customer might see Step 2 finish but the redirect logic thinks they're still on Step 2 → infinite loop on refresh. Server MUST update setup_current_step BEFORE the response returns.
  • Pro Website wizard collision — the old pro-website-setup-wizard.md 8-step spec runs INLINE on /admin/[token]/#home AFTER this wizard completes. Verify the dashboard SetupGuide does NOT auto-pop on first visit if our wizard just completed (would feel like a second tax).

Change-management rules

  • When premium_churches.setup_current_step enum gains a new value (e.g., Phase 4 adds concierge-purchased), update §"Redirect logic" in the SAME PR and add the enum to the DB column comment.
  • When VerticalProvider.wizardCopy adds a new vertical, add a row to the §"Vertical-aware copy" table here.
  • When the Meet Your Agent step gains a new action (e.g., "Share your number with your office" SMS test), add an acceptance criterion AC18+ here BEFORE writing the Playwright assertion.

End of spec. This document is the test target for e2e/onboarding-wizard.spec.ts and the expected-output contract for every wizard feature built in Phase 2.