Implement subscription-based AI access with 250 generations/month at $5/month or $50/year. Changes: - Backend: Stripe service, payment routes, webhook handlers, generation tracking - Frontend: Upgrade page with pricing, payment success/cancel pages, UI prompts - Database: Add subscription fields to users, payments table, migrations - Config: Stripe env vars to .env.example, docker-compose.prod.yml, PRODUCTION.md - Tests: Payment route tests, component tests, subscription hook tests Users without AI access see upgrade prompts; subscribers see remaining generation count.
7.6 KiB
Kaboot Payment Feature Implementation Plan
Overview
Add Stripe subscription payments to allow users to pay for AI access (kaboot-ai-access). Users get 250 AI generations per month for $5/month (or yearly equivalent).
Pricing Model
- Monthly: $5/month for 250 AI generations
- Yearly: $50/year for 250 AI generations/month (save ~17%)
- Grace Period: 1 day after failed payment before revoking access
- Refund Policy: 7-day money-back guarantee
Implementation Checklist
Phase 1: Backend Infrastructure
-
1.1 Add Stripe dependency to server
npm install stripein server directory- File:
server/package.json
-
1.2 Add environment variables
STRIPE_SECRET_KEY- Stripe secret keySTRIPE_WEBHOOK_SECRET- Webhook signing secretSTRIPE_PRICE_ID_MONTHLY- Monthly price IDSTRIPE_PRICE_ID_YEARLY- Yearly price ID- Files:
.env.example,docs/PRODUCTION.md
-
1.3 Database migration - Add subscription and generation tracking
- Add
stripe_customer_idto users table - Add
subscription_status(none, active, past_due, canceled) - Add
subscription_idfor Stripe subscription ID - Add
subscription_current_period_endfor billing cycle - Add
generation_countfor current period usage - Add
generation_reset_datefor when to reset count - Create
paymentstable for payment history - File:
server/src/db/schema.sql
- Add
-
1.4 Create Stripe service
- Initialize Stripe client
- Create/retrieve customer helper
- Create checkout session helper
- Create customer portal session helper
- File:
server/src/services/stripe.ts
-
1.5 Create payments routes
POST /api/payments/checkout- Create Stripe Checkout sessionPOST /api/payments/webhook- Handle Stripe webhooks (raw body)GET /api/payments/status- Get subscription & generation statusPOST /api/payments/portal- Create customer portal session- File:
server/src/routes/payments.ts
-
1.6 Implement webhook handlers
checkout.session.completed- Activate subscription, set generation quotacustomer.subscription.updated- Sync status changescustomer.subscription.deleted- Mark as canceledinvoice.payment_failed- Set past_due statusinvoice.paid- Reset generation count on renewal- File:
server/src/routes/payments.ts
-
1.7 Update AI access middleware
- Check subscription status OR existing group membership
- Check generation count against limit (250)
- Increment generation count on AI use
- Return remaining generations in response
- Files:
server/src/middleware/auth.ts,server/src/routes/ai.ts(or equivalent)
-
1.8 Register payments router in main app
- File:
server/src/index.ts
- File:
Phase 2: Frontend - Upgrade Page
-
2.1 Create UpgradePage component
- Pricing card with monthly/yearly toggle
- Feature comparison (Free vs Pro)
- CTA button triggering Stripe Checkout
- Trust signals (secure payment, money-back guarantee)
- File:
components/UpgradePage.tsx
-
2.2 Create PaymentResult component
- Success state with confetti
- Cancel/return state
- File:
components/PaymentResult.tsx
-
2.3 Add routes to App.tsx
/upgraderoute/payment/successroute/payment/cancelroute- File:
App.tsx
-
2.4 Create payments API service (integrated in UpgradePage)
createCheckoutSession(planType: 'monthly' | 'yearly')getSubscriptionStatus()createPortalSession()- File:
services/paymentsApi.ts
-
2.5 Update UI to show generation usage
- Show remaining generations in preferences/header
- Show upgrade CTA when generations low or user is free tier
- Files: Various components
-
2.6 Add upgrade prompts in AI generation flow
- When user tries AI generation without access
- When user is low on generations
- Files: Components using AI generation
Phase 3: Production Updates
-
3.1 Update docker-compose.prod.yml
- Add Stripe environment variables to backend service
- File:
docker-compose.prod.yml
-
3.2 Update PRODUCTION.md documentation
- Add Stripe configuration section
- Add webhook setup instructions
- Add Stripe Dashboard product setup
- File:
docs/PRODUCTION.md
-
3.3 Update setup-prod.sh script (not needed - manual env config)
- Prompt for Stripe keys during setup
- File:
scripts/setup-prod.sh
Phase 4: Testing
-
4.1 Test with Stripe test mode
- Use test API keys
- Test card: 4242 4242 4242 4242
-
4.2 Test webhook locally
- Use Stripe CLI:
stripe listen --forward-to localhost:3001/api/payments/webhook
- Use Stripe CLI:
-
4.3 Test full payment flow
- Checkout → Success → Access granted → Generations work
-
4.4 Test generation limits
- Verify count increments
- Verify block at 250
- Verify reset on renewal
Database Schema Changes
-- Add subscription fields to users table
ALTER TABLE users ADD COLUMN stripe_customer_id TEXT UNIQUE;
ALTER TABLE users ADD COLUMN subscription_status TEXT DEFAULT 'none';
ALTER TABLE users ADD COLUMN subscription_id TEXT;
ALTER TABLE users ADD COLUMN subscription_current_period_end DATETIME;
ALTER TABLE users ADD COLUMN generation_count INTEGER DEFAULT 0;
ALTER TABLE users ADD COLUMN generation_reset_date DATETIME;
-- Payments log table
CREATE TABLE IF NOT EXISTS payments (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id),
stripe_payment_intent_id TEXT,
stripe_invoice_id TEXT,
amount INTEGER NOT NULL,
currency TEXT DEFAULT 'usd',
status TEXT NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_payments_user ON payments(user_id);
Environment Variables
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_... # or sk_live_... for production
STRIPE_WEBHOOK_SECRET=whsec_... # From Stripe Dashboard or CLI
STRIPE_PRICE_ID_MONTHLY=price_... # Monthly plan price ID
STRIPE_PRICE_ID_YEARLY=price_... # Yearly plan price ID
API Endpoints
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/payments/checkout |
Required | Create Stripe Checkout session |
POST |
/api/payments/webhook |
Stripe Sig | Handle Stripe webhook events |
GET |
/api/payments/status |
Required | Get subscription & generation status |
POST |
/api/payments/portal |
Required | Create Stripe Customer Portal session |
Stripe Dashboard Setup
- Create Product: "Kaboot AI Pro"
- Add Monthly Price: $5.00/month
- Add Yearly Price: $50.00/year
- Copy Price IDs to environment variables
- Set up Webhook endpoint:
https://your-domain.com/api/payments/webhook - Subscribe to events:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.paidinvoice.payment_failed
Generation Tracking Logic
- On subscription activation: Set
generation_count = 0,generation_reset_date = period_end - On each AI generation: Increment
generation_count - Before AI generation: Check
generation_count < 250 - On
invoice.paid(renewal): Resetgeneration_count = 0, updategeneration_reset_date - Return
remaining_generations = 250 - generation_countin API responses
Notes
- Existing
kaboot-ai-accessgroup users (via Authentik) get unlimited access (grandfathered) - Subscription users get 250 generations/month regardless of Authentik group
- Both access methods are valid - check either condition in middleware