Skip to content

feat(billing): pricing redesign — annual plans, Enterprise tier, richer quotas#83

Open
smakosh wants to merge 1 commit into
mainfrom
feat/pricing-redesign-annual-enterprise
Open

feat(billing): pricing redesign — annual plans, Enterprise tier, richer quotas#83
smakosh wants to merge 1 commit into
mainfrom
feat/pricing-redesign-annual-enterprise

Conversation

@smakosh

@smakosh smakosh commented Jun 24, 2026

Copy link
Copy Markdown
Member

What & why

A redesign of Clanker Support's pricing — keeping the bootstrapped constraints intact (paid-only, free self-host, no per-seat fees) while fixing the weak spots in the current Starter $19 / Growth $89 / Scale $299 structure and adding the highest-leverage missing pieces.

Monthly prices are unchanged ($19/$89/$299), so existing Stripe monthly prices keep working and current customers only gain (more generous quotas). Everything advertised still comes from the shared BILLING_TIERS table, so the promise, the enforced reality, and the displayed price never drift.

The plans

Starter Growth ⭐ Scale Enterprise
Monthly $19 $89 $299 Custom
Annual (2 mo free) $190/yr $890/yr $2,990/yr Contract
AI responses/mo 2,000 (hard cap) 12,000 incl. 50,000 incl. Custom
Projects 2 5 20 Unlimited
Seats 3 10 Unlimited Unlimited + SSO
Models Fast All incl. frontier All All + BYO
Branding Badge Badge off White-label White-label

Per-response value now drops as you climb ($0.0095 → $0.0074 → $0.0060), so upgrading is the rational move and overage on Growth makes Scale the obvious step past ~30k/mo.

Changes

Shared model (packages/shared)

  • priceUsdAnnual on every tier (10× monthly); BillingInterval type; UNLIMITED sentinel + isUnlimited() helper
  • Bumped Growth/Scale quotas; ENTERPRISE_TIER display constant (sold, not self-served — no Plan value, resolves to none)

API (apps/api)

  • planPrices(vars, plan, interval) selects monthly vs STRIPE_PRICE_*_ANNUAL; checkout accepts interval (defaults monthly). Overage prices unchanged.
  • New env declared in env.d.ts, .env.example, ploy.yaml

Marketing (apps/marketing)

  • New PricingPlans client island: monthly/annual toggle, Growth highlighted, mental-accounting price framing, Enterprise band, risk-reversal strip
  • Outcome-led masthead copy; new FAQs (annual, money-back guarantee, Enterprise); pricing.md + JSON-LD updated; SALES_EMAIL constant

Dashboard (apps/dashboard)

  • Cadence toggle on the billing screen, threaded through startCheckout(ws, plan, interval, returnTo); cadence-aware prices; unlimited-seat formatting; money-back-guarantee note

Psychology applied

Good-better-best with a pre-anchored "Most popular"; Enterprise anchors high (door-in-the-face); annual default-nudge for cash flow; charm pricing kept; 14-day money-back guarantee kills regret aversion; per-day reframe; 3 tiers + Enterprise to respect Hick's Law.

⚠️ To go live (operator)

  1. Create annual Stripe prices ($190/$890/$2,990) and set STRIPE_PRICE_{STARTER,GROWTH,SCALE}_ANNUAL. Until set, annual checkout returns billing_not_configured (monthly unaffected).
  2. Optionally set NEXT_PUBLIC_SALES_EMAIL (defaults to sales@clankersupport.com).
  3. Validate margins: confirm blended cost-per-response holds ~80% gross margin at each tier's included quota before locking the numbers.
  4. Money-back guarantee is an operational policy (handled via the Stripe portal) — no code enforces refunds.

Test plan

  • pnpm test (all suites, incl. updated billing tests), pnpm lint, pnpm build all green
  • Enterprise stays display-only: planEntitlements("enterprise") === none
  • Existing monthly checkout path unchanged

🤖 Generated with Claude Code

…er quotas

- Add annual billing (10× monthly = two months free) end-to-end: shared
  tiers carry `priceUsdAnnual`; API checkout takes an `interval`; dashboard
  + marketing get monthly/annual toggles
- Bump quotas so unit economics improve up the ladder: Growth 8k→12k
  responses & 8→10 seats; Scale 25k→50k responses, 15→20 projects, and
  unlimited seats (UNLIMITED sentinel + `isUnlimited` for display)
- Add display-only Enterprise "Contact sales" tier (SSO/SAML, DPA, SLA,
  white-glove onboarding, self-host support contract) — anchors the page
- Marketing pricing page: cadence toggle, Growth highlighted, Enterprise
  band, mental-accounting price framing, 14-day money-back-guarantee /
  risk-reversal copy, new FAQs (new client island PricingPlans.tsx)
- Wire STRIPE_PRICE_*_ANNUAL (env.d.ts, .env.example, ploy.yaml); metered
  overage prices unchanged (overage meters monthly regardless of cadence)
- Keep the "promise = enforced reality" contract: every advertised limit
  still comes from the shared BILLING_TIERS table
- Update shared + dashboard tests for the new numbers and call signatures

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@meet-ploy

meet-ploy Bot commented Jun 24, 2026

Copy link
Copy Markdown

✅ All deployments successful!

Project Deployment Branch Preview Commit Preview
llmchat-marketing Ready Preview Preview
llmchat-showcase Ready Preview Preview
llmchat-api Ready Preview Preview
llmchat-dashboard Ready Preview Preview

Deployed with Ploy

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.

2 participants