Personal Budget Docs
功能与集成

Pro plan status & upgrade checklist

Where the paid plan surfaces today, what the minimal-dashboard cleanup removed, and everything to touch when Pro features ship.

Pro features are planned, not launched. The billing infrastructure (Stripe subscription + lifetime purchase, entitlements, webhooks) is fully built and tested — see billing for the machinery. This page records the current Pro surface after the minimal-dashboard cleanup (September 2026) and everything that needs updating when Pro ships.

What the minimal-dashboard cleanup removed

The app topbar was simplified to only the minimal-dashboard and theme toggles:

  • Topbar Free/Pro plan badge — removed from AppShell (src/components/app/app-shell.tsx), including the admin role badge that showed there on admin pages.
  • isPro prop — dropped from AppShell and all its call sites (dashboard, pro, account, admin routes).
  • LangSwitch in the topbar — removed. The component file stays: the marketing nav, footer and auth card still use it.
  • Plan info remains visible elsewhere (inventory below); the dashboard "logged in as" line is now the main user-facing plan badge.

Badge's pro / free variants are generic color variants, also used for non-plan semantics (goal kinds, budget table, filter counts, admin tables). Do not remove the variants — only plan-specific usages were affected.

Where Pro still surfaces

TouchpointFileBehavior
Sidebar "Pro" nav item + badgesrc/components/app/app-shell.tsxLinks to /app/pro; badge shows on the expanded rail
Pro demo pagesrc/routes/{-$locale}/app/pro.tsxhasProAccess(user.role, ent) gate — free users get a blurred preview + upgrade CTA
Account → current plansrc/features/billing/components/manage-subscription.tsxPlan badge + status; pro → Stripe portal button, free → upgrade link; lifetime variant
Dashboard "logged in as" linesrc/routes/{-$locale}/app/index.tsxPlan badge in full mode only (hidden when minimal dashboard is on)
Pricing pagesrc/features/billing/components/pricing-table.tsxPro card "coming soon"; CTA opens the waitlist dialog, not checkout
Payment-failed bannersrc/features/billing/components/payment-failed-banner.tsxIn-app dunning signal, driven by ent.paymentFailed → Stripe Customer Portal
Admin tablessrc/features/admin/components/user-table.tsx, user-detail-drawer.tsx, src/routes/{-$locale}/admin/feedback.tsxPlan column / badges; feedback isPro derived via hasProAccess (see feedback)

Gating truth: server-side gates are requireProPlan / hasProAccess (src/features/billing/middleware.ts + entitlement.ts) — admins outrank the paywall. Billing UI (plan badges, upgrade buttons) uses ent.plan so it reflects the real subscription, not the role.

Dormant pipeline (built, tested, zero callers)

The purchase pipeline is wired end-to-end but nothing invokes it yet:

  • src/features/billing/plans.ts — plan definitions ($9/mo, $90/yr). Dormant: the pricing page pivoted to a waitlist.
  • src/features/billing/actions.ts — checkout (subscription mode) and checkoutLifetime have no callers.
  • Webhook handling is live and covers the subscription lifecycle, lifetime grant/refund, and dunning (event table in billing).
  • The pro-activated email template exists, wired via hooks.ts (see email).

Price mismatch to resolve at launch: plans.ts defines $9/mo / $90/yr while the pricing-table copy pitches $199 personal / $499 team. Reconcile before taking real payments.

Launch checklist

When Pro features ship, update:

  1. Pricing page — switch the Pro CTA from the waitlist dialog to the real checkout server fn; reconcile prices between the pricing-table copy and plans.ts.
  2. Lifetime — wire checkoutLifetime if you offer a one-time buy (the webhook side is already implemented).
  3. Feature gating — gate new Pro features server-side with requireProPlan / hasProAccess; use ent.plan only for billing UI.
  4. Stripe setup — configure STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET and price IDs (see environment and deploy); create the products/prices and webhook events in the Stripe Dashboard.
  5. Badge spots — decide where plan badges belong now. The topbar no longer shows one; the dashboard "logged in as" line does. Re-add a topbar badge consciously if you want it back.
  6. i18n — extend the billing.* keys in both src/features/i18n/dictionaries/en.ts and zh.ts (structurally identical; zh is typed against en).
  7. Emails — pro-activated fires via hooks.ts (onProActivated); add deactivation / payment-failed hooks as needed.
  8. Tests — extend billing.workers.test.ts / entitlement.node.test.ts for any new transitions.
  9. Docs — update this page and billing whenever the Pro status changes.

On this page