Skip to content

feat(paywall): in-panel upgrade UI with Stripe Checkout and auto-activation - #26

Merged
PAMulligan merged 1 commit into
mainfrom
feature/paywall-upgrade-ui
Aug 15, 2026
Merged

feat(paywall): in-panel upgrade UI with Stripe Checkout and auto-activation#26
PAMulligan merged 1 commit into
mainfrom
feature/paywall-upgrade-ui

Conversation

@PAMulligan

Copy link
Copy Markdown
Contributor

Closes #10.

What

The full conversion surface for free users in the side panel:

  • Persistent "Upgrade" entry point — quiet pill in a new shared PanelHeader (used by SetupPage + ScorePage), plus entry points in the settings Plan row (with free-quota display) and the shared ProUpsell card
  • PaywallPaywallModal on a new accessible Dialog primitive (focus trap, Escape, aria-modal, focus restore): five benefit rows, keyboard-navigable monthly/annual selector ($5/mo, $50/yr, both prices equally visible, honest Stripe caption), and checkout/waiting/success/error states
  • Over-quota promptOverQuotaNotice bound to the locked AI state: friendly copy + reset timing + upgrade CTA for free users; reset timing only (no CTA) for over-quota Pro users
  • Checkout flowbilling.ts client + checkout-store.ts state machine: creates the session, opens Stripe Checkout in a new tab, polls the claim endpoint (4s→10s backoff, 10-min give-up with a manual-activation fallback), auto-activates the minted license; the existing entitlement storage sync then flips every surface to Pro with no reload. Pending sessions persist and resume on panel reopen.
  • Pinned extension ID — manifest "key" gives a stable chrome-extension:// origin for the backend CORS allowlist (survives CWS publishing)
  • Pro users never see any upgrade surface

Testing

  • 458 tests green (new suites for plans, billing client, checkout state machine, and all paywall components; free/over-quota/Pro states covered)
  • Lint, typecheck, and production build pass
  • Verified end-to-end against staging: headless Chromium with the built extension → Upgrade → Stripe test-card payment → webhook → claim → activate → panel flips to Pro without reload, Upgrade pill disappears
  • Visual QA in light and dark themes

🤖 Generated with Claude Code

…vation

Adds the conversion surface for free users (closes #10):

- Persistent "Upgrade" pill in a new shared PanelHeader (SetupPage +
  ScorePage), plus upgrade entry points in the settings Plan row and the
  shared ProUpsell card (promoted from SubscoresPage)
- PaywallModal on a new accessible Dialog primitive (focus trap, Escape,
  aria-modal): benefit list, monthly/annual selector ($5/mo, $50/yr),
  checkout/waiting/success/error states, no dark patterns
- OverQuotaNotice bound to the locked AI state: reset timing + upgrade
  CTA for free users, reset timing only for Pro
- Checkout flow: billing client for /billing/checkout + /billing/session
  claim polling with backoff and give-up fallback, persisted pending
  session resumed on panel mount; activation flips all surfaces to Pro
  via the existing entitlement storage sync, no reload needed
- Pins the extension ID via manifest "key" so the chrome-extension://
  origin is stable for the backend CORS allowlist
- Pro users never see any upgrade surface; component tests cover free,
  over-quota, checkout, and Pro states (458 tests green)

Verified end-to-end against staging: test-card payment -> webhook ->
claim -> activate -> panel flips to Pro without reload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PAMulligan
PAMulligan merged commit d218df3 into main Aug 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build paywall and upgrade UI in the side panel

1 participant