Skip to main content

Acceptance Spec — Tuesday Prep Pack signup on the Prep Desk

Why (one paragraph)

The funnel's owned-audience asset is the email list, not YouTube subs (strategy.md §1, §6). The Tuesday Sermon Prep Pack is the lectionary-keyed weekly email; the prep-desk pages are its natural capture surface (the hub, not the Short, captures email). PR #896 shipped the section with a deliberate component seam where this form belongs. This spec fills it.

Component

src/components/sermons/TuesdaySignup.tsx'use client', self-contained, no props required.

Expected output (Pastor Ruth test)

An inline signup block:

  1. Copy: "The Tuesday Sermon Prep Pack" + "Next Sunday's text, prepped, in your inbox every Tuesday. Free."
  2. Form: one email field (type=email, required, labeled for a11y) + one submit button (.btn-gold).
  3. Submit: posts JSON { email, tag: 'tuesday_prep_pack', source: 'sermonwise' } to /api/newsletter — the public capture endpoint that writes email_subscribers and syncs MailerLite via tagToGroup(). No page reload (client fetch via postJsonWithFallback). NOTE: /api/mailerlite/subscribe is the secret-gated cross-property proxy (x-ml-proxy-key) and is NOT browser-callable; it shares the same tagToGroup() map, so the new tag works there too for sister-site callers.
  4. MailerLite routing: tag tuesday_prep_pack → group tuesday-prep-pack (id 190107266612987702) in src/lib/mailerlite-groups.ts.
  5. Success state: form replaced by "You're in — see you Tuesday." No reload.
  6. Error state: inline message, form still usable, button re-enabled.
  7. CASL note under the form: "Unsubscribe anytime."
  8. Placement: prep-desk episode pages — below the discussion prompt, above the footer cross-links. Prep-desk index — below the "What's on the desk each week" card, above the footer.

Non-goals

  • No MailerLite automation/campaign is created or activated by code — founder-gated, done in the MailerLite UI.
  • No double opt-in flow changes; whatever the group/account is configured for applies.
  • No name field, no church field — email only (lowest-friction capture).

Edge cases

  • Already-subscribed email → still shows success (endpoint returns alreadySubscribed: true; copy stays "You're in — see you Tuesday.").
  • JS network failure → error state, never a silent no-op (three-tier transport in postJsonWithFallback).
  • Component renders identically with or without a youtubeVideoId on the episode.

Verification gate (evidence-or-nothing)

  • pnpm lint (touched files) + pnpm build green.
  • Deployed-URL check: form visible on /prep-desk and /prep-desk/matthew-13-the-sower (sermonwise.ai host); submit a test email; observe success copy without reload; subscriber appears in MailerLite group tuesday-prep-pack.