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)

TierPriceFeatures
Monthly$2.99/moUnlimited quizzes, no ads
Annual$19.99/yrSame + 44% savings
Lifetime$39.99Same, forever

Interview Premium (NEW - AI Feature)

TierPriceFeatures
Interview Access$14.99AI 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

FeatureFree UsersPremium Users
Quiz3/dayUnlimited
Practice3/dayUnlimited
InterviewLOCKED10/day
Speaking/Reading/WritingUnlimitedUnlimited

API Rate Limits (Vercel Backend)

EndpointLimitWindowNotes
/api/interview/chat100 req1 hourPer user
/api/interview/evaluate50 req1 hourPer user
All endpoints1000 req24 hoursPer user

Abuse Protection

  1. Authentication: JWT token from mobile app
  2. User ID Tracking: Track usage by user ID (from RevenueCat or device ID)
  3. IP Rate Limiting: Fallback for unauthenticated requests
  4. Request Validation: Validate all inputs, reject malformed requests
  5. 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)

UsageInput TokensOutput TokensCost
1 interview session~2,000~1,000~$0.002
100 sessions/day200,000100,000~$0.20/day
1,000 sessions/day2M1M~$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)

  1. Add premium check to Interview tab
  2. Add interview usage tracking to store
  3. Update paywall with interview tier

Phase 2: Vercel API Setup

  1. Create Vercel project structure
  2. Set up Upstash Redis
  3. Implement rate limiting middleware
  4. Create interview endpoints

Phase 3: Integration

  1. Create API client in mobile app
  2. Wire interview to use API
  3. Test end-to-end flow

Phase 4: Production

  1. Set up RevenueCat products
  2. Configure production environment variables
  3. 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?