PUL-24: add Lite plan (₹1,999/mo, analytics only, no WhatsApp) - #16
Merged
Conversation
A new tier below Go/Plus: every analytics module, no WhatsApp surface at all. Unlike Go/Plus (which differ only in message volume), Lite is a different kind of plan, so it's enforced end to end rather than just listed on the pricing page: - src/lib/billing/usage.ts: PlanId widened to include "lite"; planMessageLimit returns 0 for it unconditionally (no "usable Lite subscription that can still send," unlike Go's past_due grace window); new planIncludesWhatsApp / hasWhatsAppPlan for the page/route gate below. - src/proxy.ts: WHATSAPP_PAGES (campaigns, flows, abandoned-checkouts, order-confirmations, menu, inbox, whatsapp-cloud-pilot, assistant) redirect a Lite account to Settings -> Billing with an upgrade prompt; WHATSAPP_API (/api/whatsapp*, /api/whatsapp-cloud*, /api/ai/chat) returns 402 for both a session and an API key. The assistant is gated as a whole -- its value is inseparable from the WhatsApp actions it proposes. - Sidebar: WhatsApp-only items stay visible for Lite (not hidden) with a lock icon, and link straight to the upgrade prompt -- discoverable, not disabled with no explanation. - SubscriptionBanner no longer fires for Lite: its 0 message limit is by design, not an unpaid/inactive subscription, and the existing "Add a subscription" copy would have been actively wrong for an account that already has one. - Marketing: PLANS/ANALYTICS_MODULES/WHATSAPP_MODULES in lib/marketing/plans.ts drive /pricing and the landing page's three-tier cards; copy rewritten off the old "every tier, every feature" framing. - Billing plumbing widened for the third plan id: checkout route + Razorpay plan-id env var, Settings billing card, invoices/webhook routes, export/invoice.ts, openapi.ts. - Migration widens the profiles/billing_invoices plan check constraints to allow 'lite' (already applied to production). Verified end to end against a real account switched to Lite: sidebar lock icons, direct-URL redirect to the upgrade prompt, 402 on a WhatsApp API route, and the existing AI-summary widget surfacing the new error message cleanly through its own retry UI. Needs a real Razorpay Plan (RAZORPAY_PLAN_ID_LITE) before checkout can actually charge for this plan -- flagged separately before creating anything in the live Razorpay account. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/proxy.tsredirects WhatsApp pages (WHATSAPP_PAGES) to/settings?section=billing&upgrade=whatsappfor a Lite account, and returns 402 on WhatsApp API routes (WHATSAPP_API_PREFIXES, covering/api/whatsapp*,/api/whatsapp-cloud*,/api/ai/chat), for both a session and an API key.planMessageLimitinsrc/lib/billing/usage.tsreturns0for Lite unconditionally, same backstop every real send site already checks.SubscriptionBannerno longer misfires "subscription isn't active" for a Lite account that has a perfectly valid, paid subscription that just doesn't include WhatsApp./pricingand the landing page rewritten for a three-tier story; DB migration widens theplancheck constraints (already applied to production).Follow-up (not blocking)
Needs a real Razorpay Plan object (
RAZORPAY_PLAN_ID_LITE) before checkout can actually charge for Lite — a live-account action, flagged to the founder separately rather than created without confirmation.Test plan
npm run typecheck/npm run lint— cleannode scripts/check-openapi.mjs— all 42 routes still documentedplan='lite': sidebar lock icons + redirect on click, direct-URL navigation to/inboxredirected server-side,/api/whatsapp/chatsreturned 402, Billing card correctly shows "Lite · Active · ₹1,999/mo", the existing AI-summary widget on an analytics page surfaced the new error message cleanly through its own retry UI/products,/dashboard) confirmed unaffectedCo-Authored-By: Claude Sonnet 5 noreply@anthropic.com