Skip to main content

ITW Premium — Expected Output Spec

Status: COMPLETE -- Agent-derived from codebase analysis. Flagged items require founder confirmation. Product: IllustrateTheWord Premium | Price: $9.95/mo ($99.50/yr) | Trial: None URL: illustratetheword.com | Auth: Supabase Auth (email/password + Google OAuth) Codebase: sermon-illustrations/


User State Definition

FieldValue
Productitw_premium (or itw_premium_annual)
Subscription tableuser_subscriptions
AuthSupabase Auth (email + password OR Google OAuth)
Content accessAll 3 tiers: public, free_signup, premium
Library access100% of illustrations (~50,000+)
FavoritesUnlimited
CollectionsUnlimited named collections
Sermon slidesUnlimited downloads
Copy to clipboardYes
LensLinesFull access to tradition-specific perspectives

Access Tier Breakdown

Tier% of LibraryContent TypesRequires
public~18%All historical_illustration + top ~50 per non-premium typeNothing (anonymous OK)
free_signup~68%Majority of the libraryFree account
premium~14%movie_analogy, devotional, lens_perspective, application_point, show_dont_tell_prompt, spiritual_discipline, character_profile, vivid_retelling, tv_analogy + high-quality sermon_illustrationPaid subscription ($9.95/mo)

A. Discovery Paths (Touchpoints 1--8)

How a prospective ITW Premium customer first encounters the product.

Touchpoint 1: Homepage

URL: https://illustratetheword.com/ Component: sermon-illustrations/src/app/page.tsx

Should See:

  • Cinematic video hero (HeroVideo component) with search bar overlay
  • Dynamic count: "50,000+ Sermon Illustrations"
  • "This Sunday" lectionary readings section (auto-detected from RCL calendar)
  • 5 browse category cards: By Topic, By Scripture, By Emotion, By Tradition, By Source Type
  • Recently updated illustrations (6 cards)
  • "Surprise Me" random discovery button
  • Search bar prominent above the fold
  • Footer with links to About, Help, Contact, Pricing, Privacy, Terms

Should NOT See:

  • Aggressive Free vs Premium tier distinction above the fold
  • "Upgrade to Premium" CTA on the homepage
  • Pricing information on the homepage
  • CWA branding in the main content area

CTA -> Destination:

  • Search bar -> /search?q=[query]
  • Browse cards -> /topics, /scriptures, /emotions, /traditions, /sources
  • "This Sunday" -> Lectionary readings with linked illustrations
  • "Surprise Me" -> Random illustration detail page

Notes:

The homepage is a content-first browse experience, not a marketing landing page. A pastor discovers the gate organically when they click a locked illustration.


Touchpoint 2: Topic/Scripture/Emotion Browse Pages (SEO landing)

URL: https://illustratetheword.com/topics/[slug] (and /scriptures/, /emotions/, /traditions/, /sources/) Component: Various under sermon-illustrations/src/app/topics/, scriptures/, etc.

Should See:

  • Page heading with topic/scripture/emotion name
  • Grid of illustration cards matching the filter
  • Each card shows: title, teaser, content type emoji badge, theological tradition badge
  • Cards for ALL tiers visible (public, free_signup, premium) -- no content hidden from browse
  • Pagination for large result sets
  • Search/filter refinement options

Should NOT See:

  • Lock icons or "Premium" badges on cards in the browse grid
  • Any content hidden from the browse listing (all tiers show cards)
  • The gate only appears on the detail page, not the browse page

CTA -> Destination:

  • Click card -> /illustrations/[slug] (detail page where gating occurs)

Touchpoint 3: Illustration Detail Page (Public Tier)

URL: https://illustratetheword.com/illustrations/[slug] (for visibility_tier = 'public') Component: sermon-illustrations/src/app/illustrations/[slug]/page.tsx

Should See:

  • Full illustration content (title, body text, formatted with bold/italic)
  • Metadata: scripture references, topics/themes, emotions, theological tradition badge
  • CopyButton (clipboard) -- available to all logged-in users
  • ShareButton (social sharing)
  • FavoriteButton (heart icon) -- requires login
  • AddToCollectionButton -- requires login
  • PersonalizeButton -- customize for context
  • Related illustrations section (6 cards)
  • Scripture-related illustrations section
  • LensLines for the passage (if applicable)
  • StockPhotos component (contextual images)
  • MovieInfo component (if movie analogy)
  • ChurchWiseAIPromo section at bottom
  • Schema.org structured data

Should NOT See:

  • Any paywall or gate (public tier is fully visible)
  • "Upgrade" messaging on public content

Touchpoint 4: Illustration Detail Page (Free Signup Tier -- Anonymous Visitor)

URL: https://illustratetheword.com/illustrations/[slug] (for visibility_tier = 'free_signup', user NOT logged in) Component: sermon-illustrations/src/app/illustrations/[slug]/page.tsx

Should See:

  • Title and metadata (scripture, topics, emotions, tradition)
  • Teaser / first paragraph of the illustration
  • Content gate: "Sign up free to read this illustration"
  • CTA button: "Sign Up Free" -> /signup
  • Related illustrations visible below the gate
  • Schema.org structured data with partial content

Should NOT See:

  • Full illustration body text
  • CopyButton functional (hidden or disabled)
  • Premium upgrade messaging (this is a free_signup gate, not a premium gate)

CTA -> Destination:

  • "Sign Up Free" -> /signup
  • If coming from a specific illustration: signup redirects back to the illustration after confirmation

Touchpoint 5: Illustration Detail Page (Premium Tier -- Free User)

URL: https://illustratetheword.com/illustrations/[slug] (for visibility_tier = 'premium', user logged in but NOT subscribed) Component: sermon-illustrations/src/app/illustrations/[slug]/page.tsx

Should See:

  • Title and metadata
  • Teaser / first paragraph
  • Content gate with Lock icon: "This is a premium illustration"
  • CTA button: "Unlock with Premium -- $9.95/mo" -> /pricing?checkout=monthly
  • Secondary CTA: "Learn more about Premium" -> /pricing
  • Related illustrations visible below
  • ChurchWiseAIPromo at bottom

Should NOT See:

  • Full illustration body text
  • Aggressive upsell or FOMO language
  • Multiple overlapping CTAs

CTA -> Destination:

  • "Unlock with Premium" -> /pricing?checkout=monthly

Touchpoint 6: Pricing Page

URL: https://illustratetheword.com/pricing Component: sermon-illustrations/src/app/pricing/page.tsx

Should See:

  • Amber gradient hero: "Simple, Transparent Pricing"
  • Monthly / Annual billing toggle (Annual shows "Save X%" badge)
  • Two side-by-side cards:
    • Free ($0/forever): Browse public illustrations, Search by topic/scripture/emotion, 17 traditions, Lectionary calendar, 1 sermon slide/week. CTA: "Get started free" -> /signup
    • Premium ($9.95/mo or $8.29/mo annual): Everything in Free + Unlock all 50,000+ illustrations, Movie analogies/devotionals/application points, LensLines, Unlimited slide downloads, Save and organize favorites, Priority access. CTA: "Subscribe" -> Stripe checkout (or /signup if not logged in)
  • "Most Popular" badge on Premium card
  • "Your Plan" badge if already subscribed
  • "Manage subscription" link if already subscribed -> Stripe portal
  • Checkout cancelled banner (if returning from cancelled Stripe)
  • Auto-checkout trigger if coming from ?checkout=monthly or ?checkout=annual
  • FAQ section with support email link

Should NOT See:

  • A third "free_signup" tier card (two tiers only: Free and Premium)
  • CWA chatbot/voice pricing
  • Complex tier comparison tables

CTA -> Destination:

  • "Get started free" -> /signup
  • "Subscribe" (not logged in) -> /signup?plan=premium
  • "Subscribe" (logged in, not premium) -> Stripe checkout via /api/stripe/checkout
  • "Manage subscription" (premium) -> Stripe Customer Portal via /api/stripe/portal

Touchpoint 7: Signup Page

URL: https://illustratetheword.com/signup Component: sermon-illustrations/src/app/signup/page.tsx

Implementation Note: This page (and the signin page) has two email inputs — the auth form input (data-testid="itw-signup-auth-email") and a newsletter subscription input in the page footer. Always use data-testid selectors for auth form interactions to avoid strict mode violations from the duplicate field.

Should See:

  • BookOpen icon + "Create your free account" heading
  • "Unlock thousands of sermon illustrations" subheading
  • Google OAuth button: "Sign up with Google" (prominent, at top)
  • Divider: "or sign up with email"
  • Email form fields: Name (optional), Email (required), Password (required, min 8 chars), Confirm Password (required)
  • Password visibility toggle (eye icon)
  • Newsletter opt-in checkbox: "Email me this Sunday's top illustrations and new features"
  • Cloudflare Turnstile captcha
  • "Create free account" submit button
  • "Already have an account? Sign in" link -> /signin
  • Common password rejection (20 common passwords blocked)
  • Password mismatch inline validation

Should NOT See:

  • Church name or denomination fields (individual pastor accounts)
  • Credit card fields (free signup)
  • CWA branding
  • Premium pricing information (this is a free account creation)

CTA -> Destination:

  • "Create free account" -> email confirmation sent -> /auth/callback -> homepage (or /pricing?checkout=monthly if came from premium content)
  • "Sign up with Google" -> Google OAuth -> /auth/callback

Touchpoint 8: Email Confirmation

URL: Email inbox -> confirmation link -> illustratetheword.com/auth/callback Component: sermon-illustrations/src/app/auth/callback/ (Supabase Auth callback)

Should See:

  • In email: Supabase default confirmation email with verification link
  • After clicking: redirect to the site, now logged in
  • If came from premium gated content: redirected to /pricing?checkout=monthly to complete premium subscription
  • If came from normal signup: redirected to homepage

Should NOT See:

  • Broken redirect loops
  • Error states (should handle gracefully)

B. Free Experience (Touchpoints 9--13)

What a free logged-in user can do.

Touchpoint 9: Browsing as Free User

URL: Any browse page (topics, scriptures, emotions, traditions, sources, search) Component: Various browse pages

Should See:

  • Full card listings for all illustrations (all tiers show in browse)
  • Full content for public tier illustrations
  • Full content for free_signup tier illustrations (the bulk of the library, ~68%)
  • Premium illustrations show title + teaser but gated on detail page
  • Search works across all tiers
  • Filter works across all tiers

Should NOT See:

  • Lock icons on cards in browse (gate is only on detail page)
  • Reduced search results (all tiers in search)

Touchpoint 10: Favorites Page

URL: https://illustratetheword.com/favorites Component: sermon-illustrations/src/app/favorites/page.tsx

Should See:

  • Heart icon heading + "Your Favorites"
  • Grid of saved illustrations (from user_favorites table)
  • Sorted by quality score (descending)
  • Each card shows same format as browse pages
  • If no favorites: empty state with "Start saving illustrations" prompt

Should NOT See:

  • Premium-only gate on the favorites feature itself (available to all logged-in users)
  • Limit on number of favorites

✅ Verified 2026-04-27: free authed users see /pricing anchor instead of save action. e2e/content-gating.spec.ts FA-075 describe block green across 4 viewports.


Touchpoint 11: Collections Page

URL: https://illustratetheword.com/collections Component: sermon-illustrations/src/app/collections/page.tsx

Should See:

  • Named collections the user has created
  • Ability to create, rename, delete collections
  • Add illustrations to collections from detail pages (via AddToCollectionButton)

Should NOT See:

  • The collections page itself is accessible to all logged-in users (to view existing collections)
  • However, creating a collection and adding to a collection MUST be Premium-only actions — non-Premium users see an upgrade prompt instead

✅ Verified 2026-04-27: non-premium users see /pricing anchor with PRO badge. Pattern is also the model FA-075 mirrored for FavoriteButton.

FLAGGED FOR FOUNDER REVIEW:

Verify that the collections feature is fully implemented and functional. The route exists but completeness needs confirmation.


Touchpoint 12: Lectionary Calendar

URL: https://illustratetheword.com/lectionary Component: sermon-illustrations/src/app/lectionary/page.tsx

Should See:

  • RCL (Revised Common Lectionary) calendar
  • Upcoming Sundays with readings
  • Links to illustrations matching each reading's scripture passage
  • Auto-detected current week

Should NOT See:

  • Premium gate on the calendar itself (all tiers can browse the calendar)
  • Premium illustrations that match lectionary readings will still show title/teaser but gate on detail

Touchpoint 13: Sermon Slides

URL: https://illustratetheword.com/slides Component: sermon-illustrations/src/app/slides/page.tsx

Should See:

  • Sermon slide generation/download feature
  • Free tier: 1 slide download per week limit
  • Download button with remaining count

Should NOT See:

  • Unlimited access (that's Premium)

C. Upgrade Journey (Touchpoints 14--17)

The path from free user to Premium subscriber.

Touchpoint 14: Premium Gate Encounter

URL: https://illustratetheword.com/illustrations/[slug] (premium content) Component: sermon-illustrations/src/app/illustrations/[slug]/page.tsx

Should See:

  • Title, metadata, teaser visible
  • Lock icon with "This is a premium illustration"
  • CTA: "Unlock with Premium -- $9.95/mo" -> /pricing?checkout=monthly
  • Related free illustrations visible below (encourage continued browsing)

Should NOT See:

  • Blurred content overlay (content is simply cut off, not blurred)
  • Aggressive "limited time" or FOMO messaging
  • Multiple redundant upgrade CTAs

Touchpoint 15: Pricing Page (Upgrade Intent)

URL: https://illustratetheword.com/pricing?checkout=monthly or ?checkout=annual Component: sermon-illustrations/src/app/pricing/page.tsx

Should See:

  • Same as Touchpoint 6 but with:
  • Ready-to-subscribe banner: "Ready to unlock full access? Compare plans below and click Subscribe when you're ready."
  • Premium card highlighted with pulse animation (animate-pulse-once)
  • Billing toggle pre-set if ?checkout=annual parameter present
  • Auto-checkout may trigger if user is logged in and not premium

Touchpoint 16: Stripe Checkout

URL: Stripe hosted checkout (redirected from /api/stripe/checkout) Component: Stripe hosted checkout page

Should See:

  • Product name: "IllustrateTheWord Premium" (monthly or annual)
  • Price: $9.95/mo or $99.50/yr
  • Email pre-filled from Supabase Auth
  • Card fields, billing address
  • No trial period (immediate charge)
  • Stripe branding

Should NOT See:

  • "CWA" or "ChurchWiseAI" in the Stripe product name
  • Trial badge (there is no trial for ITW)

Touchpoint 17: Post-Checkout Confirmation

URL: https://illustratetheword.com/profile?subscription=success Component: sermon-illustrations/src/app/profile/page.tsx

Should See:

  • Success banner with PartyPopper icon: "Welcome to ITW Premium!"
  • Profile page showing "Your Plan: Premium" badge
  • Favorites count
  • "Manage Subscription" button
  • Email display
  • The entire library is now unlocked

Should NOT See:

  • Welcome modal or guided tour
  • Complex onboarding steps (it's a content library, not a SaaS dashboard)

D. Premium Experience (Touchpoints 18--22)

What a paying Premium subscriber sees and can do.

Touchpoint 18: Premium Content Access

URL: https://illustratetheword.com/illustrations/[slug] (any premium illustration) Component: sermon-illustrations/src/app/illustrations/[slug]/page.tsx

Should See:

  • Full illustration content (no gate, no teaser truncation)
  • CopyButton functional
  • FavoriteButton functional
  • AddToCollectionButton functional
  • PersonalizeButton functional
  • ShareButton functional
  • All metadata, related content, LensLines visible

Should NOT See:

  • Any paywall or upgrade messaging
  • "Premium" indicator on the content itself (content just works)

Touchpoint 19: LensLines

URL: https://illustratetheword.com/lenslines and on detail pages Component: sermon-illustrations/src/app/lenslines/ + LensLineCompactCard

Should See:

  • Tradition-specific perspectives on scripture passages
  • Compact cards embedded in illustration detail pages
  • Full LensLines browse experience

Should NOT See:

  • Access gate (Premium unlocks LensLines content)

Touchpoint 20: Unlimited Sermon Slides

URL: https://illustratetheword.com/slides Component: sermon-illustrations/src/app/slides/page.tsx

Should See:

  • Unlimited slide downloads (no weekly limit)
  • Full access to all slide templates/styles

Touchpoint 21: Profile / Account Management

URL: https://illustratetheword.com/profile Component: sermon-illustrations/src/app/profile/page.tsx

Should See:

  • User display name (from Supabase metadata)
  • User email (with "Change email" form: enter new email -> confirmation link sent to both old and new)
  • Favorites count with link to /favorites
  • Subscription status: "Premium" badge
  • "Manage Subscription" button -> Stripe Customer Portal
  • "Delete Account" section (with "type DELETE" confirmation, destructive action warning)
  • Success banner if just subscribed (?subscription=success)

Should NOT See:

  • Password change on this page (use Supabase password reset flow)
  • Church/denomination settings (not relevant for ITW)

Touchpoint 22: Stripe Customer Portal (Billing Management)

URL: Stripe Customer Portal (via /api/stripe/portal POST redirect) Component: Stripe hosted portal

Should See:

  • Current subscription: ITW Premium ($9.95/mo or $99.50/yr)
  • Cancel subscription option
  • Update payment method
  • Switch between monthly and annual billing (Stripe handles proration)
  • Invoice history

E. Cross-Sell & Ecosystem (Touchpoints 23--24)

Touchpoint 23: ChurchWiseAI Promo on Detail Pages

URL: Any illustration detail page Component: sermon-illustrations/src/components/illustrations/ChurchWiseAIPromo.tsx

Should See:

  • Section titled "Powered by ChurchWiseAI"
  • Subtext: "IllustrateTheWord is part of the ChurchWiseAI family -- AI tools built for pastors, churches, and ministry leaders."
  • Two product cards:
    • PewSearch: "Find Your Church Home" -- "Search Churches" CTA -> pewsearch.com
    • ChurchWiseAI: "Voice Agent & Church Chatbot" -- "See AI Tools" CTA -> churchwiseai.com
  • Bottom bar: "AI voice agent & chatbot for your church -- from $14.95/mo" + "See Plans" -> churchwiseai.com/pricing
  • Compact variant available for sidebar contexts

Should NOT See:

  • Aggressive upsell interrupting content flow
  • "Buy now" or urgency language
  • This section should feel informational, not sales-y

URL: All pages (global footer) Component: sermon-illustrations/src/components/layout/Footer.tsx

Should See:

  • ITW branding
  • Links to About, Help, Contact, Privacy, Terms, Pricing
  • Ecosystem mention (PewSearch, ChurchWiseAI)

F. Lifecycle Events (Touchpoints 25--30)

Touchpoint 25: Payment Failed

URL: Email + in-app Component: Stripe webhook handler + profile page

Should See:

  • Stripe retry attempts (3 retries over ~7 days)
  • Email notification (Stripe default or custom) with link to update payment
  • In-app: profile page should show subscription status reflecting payment issue

Should NOT See:

  • Immediate content lockout on first failure (grace period during Stripe retries)

FLAGGED FOR FOUNDER REVIEW:

No custom payment failure email or in-app banner exists. Stripe defaults handle retries. Recommendation: add a custom email and profile banner for past_due status.


Touchpoint 26: Subscription Cancelled

URL: Profile page after cancellation Component: sermon-illustrations/src/app/profile/page.tsx

Should See:

  • Subscription status changes from "Premium" to "Free" (after billing period ends)
  • Access to premium content revoked (detail pages show gate again)
  • Saved favorites preserved (titles visible, premium content shows teaser only)
  • Collections preserved
  • "Subscribe" button reappears on pricing page

Should NOT See:

  • Data deletion (soft delete pattern -- all user data retained)
  • Aggressive "come back" messaging

FLAGGED FOR FOUNDER REVIEW:

No custom cancellation email exists. Recommendation: send empathetic cancellation email (data retained, access ends at period, welcome back anytime, no hard feelings).


Touchpoint 27: Re-subscription

URL: /pricing Component: sermon-illustrations/src/app/pricing/page.tsx

Should See:

  • Standard pricing page with Subscribe CTA
  • Same Stripe checkout flow as initial subscription
  • After re-subscribing: all old favorites and collections immediately accessible again
  • Premium content unlocked again

Should NOT See:

  • Welcome email treating them as a new user (detect re-subscription)

Touchpoint 28: Annual Billing Switch

URL: Stripe Customer Portal Component: Stripe hosted portal

Should See:

  • Option to switch from monthly ($9.95) to annual ($99.50/yr -- save ~17%)
  • Stripe handles proration automatically
  • No disruption to access during switch

Touchpoint 29: Email -- Weekly Lectionary (Newsletter)

URL: Email inbox Component: MailerLite or custom email system

Should See:

  • "This Sunday's top illustrations" if opted in during signup
  • Links to relevant illustrations for upcoming lectionary readings
  • Gentle reminder of premium content available
  • Unsubscribe link

FLAGGED FOR FOUNDER REVIEW:

Verify the newsletter is actually sending. The signup checkbox opts into MailerLite, but the actual email cadence and content need confirmation.


Touchpoint 30: Account Deletion

URL: /profile Component: sermon-illustrations/src/app/profile/page.tsx (delete section)

Should See:

  • "Delete Account" section at bottom of profile
  • Warning text explaining consequences
  • Requires typing "DELETE" to confirm
  • Cancel active subscription first (if applicable)
  • After deletion: signed out, redirected to homepage

Should NOT See:

  • Easy one-click deletion (requires deliberate confirmation)

Playwright Test Hints

// Touchpoint 1: Homepage loads with illustration count
test('homepage shows illustration count', async ({ page }) => {
await page.goto('https://illustratetheword.com');
await expect(page.getByText(/\d+,000\+ Sermon Illustrations/)).toBeVisible();
});

// Touchpoint 4: Free signup gate on free_signup content
test('anonymous user sees signup gate on free_signup illustration', async ({ page }) => {
// Navigate to a known free_signup illustration
await page.goto('https://illustratetheword.com/illustrations/[known-free-signup-slug]');
await expect(page.getByText('Sign up free')).toBeVisible();
await expect(page.getByRole('link', { name: /sign up/i })).toHaveAttribute('href', '/signup');
});

// Touchpoint 5: Premium gate on premium content
test('free user sees premium gate on premium illustration', async ({ page }) => {
// Login as free user first
// Navigate to a known premium illustration
await expect(page.getByText('This is a premium illustration')).toBeVisible();
await expect(page.getByRole('link', { name: /unlock with premium/i })).toBeVisible();
});

// Touchpoint 6: Pricing page shows both tiers
test('pricing page shows Free and Premium cards', async ({ page }) => {
await page.goto('https://illustratetheword.com/pricing');
await expect(page.getByText('$0')).toBeVisible();
await expect(page.getByText('$9.95')).toBeVisible();
await expect(page.getByTestId('itw-pricing-billing-monthly')).toBeVisible();
await expect(page.getByTestId('itw-pricing-billing-annual')).toBeVisible();
});

// Touchpoint 7: Signup page has all required fields
test('signup page has name, email, password, Google OAuth', async ({ page }) => {
await page.goto('https://illustratetheword.com/signup');
await expect(page.getByTestId('itw-signup-auth-google')).toBeVisible();
await expect(page.getByTestId('itw-signup-auth-email')).toBeVisible();
await expect(page.getByTestId('itw-signup-auth-password')).toBeVisible();
await expect(page.getByTestId('itw-signup-auth-newsletter')).toBeVisible();
});

// Touchpoint 18: Premium user sees full content
test('premium user sees full illustration content', async ({ page }) => {
// Login as premium user
// Navigate to premium illustration
await expect(page.getByText('This is a premium illustration')).not.toBeVisible();
// Full content should be rendered
});

// Touchpoint 21: Profile page shows subscription status
test('profile page shows Premium badge for subscriber', async ({ page }) => {
// Login as premium user
await page.goto('https://illustratetheword.com/profile');
await expect(page.getByText('Premium')).toBeVisible();
await expect(page.getByText('Manage Subscription')).toBeVisible();
});