Skip to main content

WitPit

A gamified iOS app that trains quick-wittedness through AI-scored daily challenges, unlimited practice scenarios, and a community voting arena

More screenshots

Progress95%

Short description

WitPit is a native iOS app that helps users build verbal agility and quick thinking through timed wit challenges scored by AI across three dimensions: creativity, relevance, and humor. It features a freemium model with StoreKit 2 subscriptions, a community leaderboard, a structured Academy, and a 22-level XP progression system. The backend is a self-built REST API deployed on Railway, with Sign in with Apple and JWT auth.


Full description

The problem

Quick-wittedness is a learnable skill — but there's no structured way to practice it. Most people freeze when they need a fast, clever response in conversation. WitPit gives them a daily challenge to sharpen that reflex, immediate AI feedback to understand why a response lands, and a community arena to see how they stack up.

What I built

A full-stack product from scratch: native iOS app, REST API, and admin panel. The iOS app is the primary product — a SwiftUI app built with MVVM and the @Observable macro, targeting iOS 17+.

Core features:

  • Daily challenge — one timed (45s) wit challenge per day, AI-scored on creativity, relevance, and humor (1–10 each), with XP awarded and streak tracked
  • Practice mode — unlimited (Pro) or 5/day (free) AI-generated scenarios with full coaching feedback, no persistence
  • Community arena — ranked leaderboard of today's responses with community voting; one vote per response, enforced server-side
  • Wit Academy — 5 structured lessons on timing, wordplay, callbacks, and social reading; lessons 3–5 gated behind Pro
  • Progression system — 22 levels from "Wit Newbie" to "Comedy Deity", XP formula (overall × 10) + (creativity × 2) + (humor × 2), daily streak tracking
  • Freemium / StoreKit 2 — monthly ($4.99) and annual ($34.99) subscriptions; paywall sheet triggered contextually from Practice, Academy, and Settings; entitlements synced on every launch

Technical highlights:

iOS

  • SwiftUI + @Observable for reactive state without @StateObject / @Published boilerplate
  • Two environment objects (AuthState, StoreManager) injected at the app root and consumed anywhere in the tree
  • StoreKit 2 for subscriptions: local JWS transaction verification (no server receipt validation needed), entitlement sync on launch, purchase flow with backend sync on .verified
  • Sign in with Apple via ASAuthorizationAppleIDCredential; identity token sent to backend for server-side Apple public key verification
  • JWT tokens stored in Keychain; APIClient is an actor to avoid data races; 401 responses trigger silent token refresh
  • Client-side daily practice counter (@AppStorage) with date-keyed reset — simple and sufficient for an indie freemium gate
  • Local StoreKit test configuration (WitPit.storekit) for full sandbox purchase testing in Simulator

Backend

  • Express + TypeScript REST API deployed to Railway; Drizzle ORM against Neon PostgreSQL
  • Apple identity token verification using Apple's public keys (JWKS endpoint), audience-checked for both iOS and web clients
  • Refresh token rotation: tokens stored hashed (SHA-256), rotated on each use, revoked on logout
  • Rate limiting on auth (express-rate-limit) and response submission endpoints
  • Admin panel with LLM switcher, prompt editor, user management, arena moderation, and daily challenge override — all DB-backed via a settings table
  • POST /api/premium/activate|deactivate — auth-guarded endpoints that flip is_premium on the user record after StoreKit verification on the client

AI

  • OpenAI API for response scoring and challenge/scenario generation
  • Scoring prompt returns structured JSON with per-dimension scores and a coaching paragraph
  • Fallback scores (6/6/6) on API failure so the user flow never breaks
  • Model and system prompts are runtime-configurable via the admin panel without a deploy

Stack

LayerTech
iOSSwiftUI, StoreKit 2, AuthenticationServices, Observation
BackendNode.js, Express, TypeScript, Drizzle ORM
DatabasePostgreSQL (Neon serverless)
AIOpenAI API
AuthSign in with Apple, JWT (access + refresh), bcrypt
DeploymentRailway (API), Codemagic (iOS CI/CD)
Web clientReact, TypeScript, shadcn/ui, TanStack Query, Vite

What I'm proud of

  • Shipping a complete freemium iOS product end-to-end: ideation → SwiftUI app → backend → StoreKit subscriptions → App Store submission pipeline
  • The StoreKit 2 integration: clean @Observable StoreManager that handles purchase, restore, and entitlement sync in ~80 lines, with no server-side receipt validation complexity
  • The admin panel — a full operator tool that lets me change AI prompts, swap models, manage users, and override daily challenges without touching code
  • Keeping the architecture simple enough to move fast: one Models.swift, one APIClient actor, two environment objects — no over-engineering