Monetization Plan
Monetization & Rate Limiting Plan
Overview
Interview Feature: Premium only - uses AI tokens (included in Pro) Other Features: Free with limits, Pro for unlimited + AI
Public pricing (web + app): Four tiers. Free: essential study tools, 3 quizzes/day, ad-supported, no AI interview. Starter $4.99/mo: no ads, unlimited quiz/practice, AI interview — 3 sessions/day, 30 chat/h, 15 evaluate/h. Pro $9.99/mo: 10 sessions/day, 100 chat/h, 50 evaluate/h, offline, smart score. Pro+ $20.99/mo: 30 sessions/day, 300 chat/h, 150 evaluate/h, priority support. Rate limits per tier as above; see DEPLOYMENT-SOP for API defaults.
1. PRICING STRUCTURE
Current Tiers (General Premium)
| Tier | Price | Features |
|---|---|---|
| Monthly | $2.99/mo | Unlimited quizzes, no ads |
| Annual | $19.99/yr | Same + 44% savings |
| Lifetime | $39.99 | Same, forever |
Interview Premium (NEW - AI Feature)
| Tier | Price | Features |
|---|---|---|
| Interview Access | $14.99 | AI Mock Interview (one-time or monthly?) |
Decision Needed: Is Interview $14.99 a one-time unlock, or separate subscription?
2. RATE LIMITING STRATEGY
Mobile App Limits
| Feature | Free Users | Premium Users |
|---|---|---|
| Quiz | 3/day | Unlimited |
| Practice | 3/day | Unlimited |
| Interview | LOCKED | 10/day |
| Speaking/Reading/Writing | Unlimited | Unlimited |
API Rate Limits (Vercel Backend)
| Endpoint | Limit | Window | Notes |
|---|---|---|---|
/api/interview/chat | 100 req | 1 hour | Per user |
/api/interview/evaluate | 50 req | 1 hour | Per user |
| All endpoints | 1000 req | 24 hours | Per user |
Abuse Protection
- Authentication: JWT token from mobile app
- User ID Tracking: Track usage by user ID (from RevenueCat or device ID)
- IP Rate Limiting: Fallback for unauthenticated requests
- Request Validation: Validate all inputs, reject malformed requests
- Cost Monitoring: Alert if token usage spikes
3. IMPLEMENTATION TASKS
Mobile App Changes
Task 1: Gate Interview Tab
File: app/(tabs)/interview/index.tsx
- Check isPremiumUser() before showing interview options
- Show upgrade prompt if not premium
- Add "Interview Premium" product to RevenueCat
Task 2: Add Rate Limit Tracking
File: store/useAppStore.ts
- Add aiInterviewsToday: number
- Add lastAIInterviewDate: string
- Add checkAIInterviewLimit(): boolean
- Add recordAIInterviewUsage(): void
Task 3: Update Paywall
File: app/(tabs)/paywall.tsx
- Add Interview Premium tier option
- Or: Add interview access to existing premium
Task 4: API Client
File: lib/api-client.ts (NEW)
- Create authenticated API client
- Handle rate limit responses (429)
- Retry with exponential backoff
- Cache responses where appropriate
Vercel API (Separate Project)
Task 5: Project Structure
civix-api/
├── api/
│ ├── interview/
│ │ ├── chat.ts # AI conversation
│ │ ├── evaluate.ts # Answer evaluation
│ │ └── complete.ts # Session summary
│ └── health.ts # Health check
├── lib/
│ ├── auth.ts # JWT verification
│ ├── ratelimit.ts # Rate limiting (Upstash)
│ ├── openai.ts # OpenAI client
│ └── prompts.ts # Interview prompts
├── middleware.ts # Auth + rate limit middleware
└── vercel.json
Task 6: Rate Limiting with Upstash
// lib/ratelimit.ts
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: process.env.UPSTASH_REDIS_URL,
token: process.env.UPSTASH_REDIS_TOKEN,
});
export const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(100, "1 h"),
analytics: true,
});
Task 7: Authentication
// lib/auth.ts
import jwt from 'jsonwebtoken';
export function verifyToken(token: string) {
return jwt.verify(token, process.env.JWT_SECRET);
}
export function getUserId(req: Request): string | null {
const auth = req.headers.get('authorization');
if (!auth?.startsWith('Bearer ')) return null;
const token = auth.slice(7);
const payload = verifyToken(token);
return payload.userId;
}
Task 8: Interview Chat Endpoint
// api/interview/chat.ts
import { OpenAI } from 'openai';
import { ratelimit } from '@/lib/ratelimit';
import { getUserId } from '@/lib/auth';
export async function POST(req: Request) {
// 1. Get user ID
const userId = getUserId(req);
if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 });
// 2. Check rate limit
const { success, remaining } = await ratelimit.limit(userId);
if (!success) {
return Response.json(
{ error: 'Rate limit exceeded', retryAfter: 3600 },
{ status: 429, headers: { 'X-RateLimit-Remaining': '0' } }
);
}
// 3. Process request
const { message, context } = await req.json();
// 4. Call OpenAI
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [...context, { role: 'user', content: message }],
max_tokens: 500,
});
return Response.json({
reply: response.choices[0].message.content,
remaining,
});
}
4. ENVIRONMENT VARIABLES
Mobile App (.env)
EXPO_PUBLIC_API_URL=https://civix-api.vercel.app
EXPO_PUBLIC_REVENUECAT_IOS_API_KEY=appl_xxx
EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY=goog_xxx
Vercel API (.env)
OPENAI_API_KEY=sk-xxx
UPSTASH_REDIS_URL=https://xxx.upstash.io
UPSTASH_REDIS_TOKEN=xxx
JWT_SECRET=your-secret-key
ALLOWED_ORIGINS=https://civix.app,exp://
5. COST ESTIMATION
OpenAI API Costs (GPT-4o-mini)
| Usage | Input Tokens | Output Tokens | Cost |
|---|---|---|---|
| 1 interview session | ~2,000 | ~1,000 | ~$0.002 |
| 100 sessions/day | 200,000 | 100,000 | ~$0.20/day |
| 1,000 sessions/day | 2M | 1M | ~$2/day |
Upstash Redis (Rate Limiting)
- Free tier: 10,000 requests/day
- Pro: $0.20 per 100K commands
Break-even
- At $14.99/user, need ~8 interview sessions to cover $0.10 in AI costs
- Very profitable margin
6. SECURITY CHECKLIST
- JWT tokens signed with strong secret
- Rate limiting on all AI endpoints
- Input validation (message length, context size)
- CORS restricted to app origins
- No API keys exposed in mobile app
- Webhook signature verification for RevenueCat
- Request logging for abuse detection
- Cost alerts in OpenAI dashboard
7. IMPLEMENTATION ORDER
Phase 1: Mobile App Gating (Today)
- Add premium check to Interview tab
- Add interview usage tracking to store
- Update paywall with interview tier
Phase 2: Vercel API Setup
- Create Vercel project structure
- Set up Upstash Redis
- Implement rate limiting middleware
- Create interview endpoints
Phase 3: Integration
- Create API client in mobile app
- Wire interview to use API
- Test end-to-end flow
Phase 4: Production
- Set up RevenueCat products
- Configure production environment variables
- Deploy and monitor
Quick Commands
# Create Vercel project
npx create-next-app@latest civix-api --typescript --app
# Add dependencies
npm install openai @upstash/ratelimit @upstash/redis jsonwebtoken
# Deploy
vercel --prod
Ready to implement. Start with Phase 1?