A comprehensive mobile application for learning and practising mathematics, powered by OpenAI GPT-4o. Built with React Native and Expo, it covers everything from Arithmetic Foundations through Complex Analysis with AI-generated lesson content, adaptive quizzes, and camera-based homework solving.
- App Walkthrough
- System Architecture
- Tech Stack
- Local Development Setup
- Deployment & Publishing
- Monetization Strategies
The app has four main tabs accessible from the bottom navigation bar:
[ Home ] [ Learn ] [ Quiz ] [ Saved ]
A Settings tab provides theme and app-preference controls.
The landing screen is a dashboard that surfaces the most useful information at a glance.
| Section | Description |
|---|---|
| Header | Greeting + Settings gear icon |
| Scan Card | Large CTA to photograph a math problem |
| Stats Row | Problems solved, accuracy %, streak (sourced live from SavedContext) |
| Topic Cards | Quick-access chips for algebra, calculus, geometry, etc. |
| Recent Scans | Last 5 AI-analysed problems with thumbnails |
Scan flow:
- Tap the camera card →
expo-image-pickeropens the device camera or photo library. - The selected image is sent to OpenAI GPT-4o vision via
services/openai.ts → analyzeMathImage(). - The model returns a structured response: problem type, step-by-step solution, difficulty rating, and tips.
- Result is displayed in a rich card and auto-saved to AsyncStorage via
SavedContext.
Three-tab layout for structured self-study.
- Search bar filters across all 17 courses and their lesson titles.
- Level filter chips: All · Beginner · Intermediate · Advanced · Expert.
- Each Course Card shows: title, level badge, lesson count, estimated hours.
- Tap to expand → full lesson outline with individual lesson rows.
- Tap any lesson row → navigates to the Lesson Detail Screen.
- Curated "core" lessons flagged as
isKey: trueinlearnData.ts. - Per-course horizontal grouping with a "See all" shortcut.
- Search and course filter controls.
- Hero banner with overall % complete and lessons studied count.
- Per-level progress bars (Beginner → Expert).
- Per-course completion rows (tracks which lessons have been viewed).
17 Courses available:
| # | Course | Level | Lessons | Hours |
|---|---|---|---|---|
| 1 | Arithmetic Foundations | Beginner | 10 | 8h |
| 2 | Pre-Algebra | Beginner | 12 | 10h |
| 3 | Algebra I | Beginner | 14 | 12h |
| 4 | Geometry | Intermediate | 14 | 11h |
| 5 | Algebra II | Intermediate | 16 | 13h |
| 6 | Pre-Calculus | Intermediate | 14 | 12h |
| 7 | Trigonometry | Intermediate | 12 | 10h |
| 8 | Statistics & Probability | Intermediate | 14 | 12h |
| 9 | Calculus I | Advanced | 16 | 14h |
| 10 | Calculus II | Advanced | 16 | 14h |
| 11 | Discrete Mathematics | Advanced | 14 | 12h |
| 12 | Linear Algebra | Advanced | 16 | 14h |
| 13 | Differential Equations | Advanced | 14 | 13h |
| 14 | Multivariable Calculus | Advanced | 16 | 15h |
| 15 | Real Analysis | Expert | 14 | 16h |
| 16 | Abstract Algebra | Expert | 14 | 16h |
| 17 | Complex Analysis | Expert | 12 | 15h |
Navigated to by tapping any lesson in the Learn section.
Three inner tabs:
| Tab | Content |
|---|---|
| Learn | AI-generated overview paragraph, key concepts (4-6 cards), formulas with notation, and a summary |
| Examples | 3 fully worked examples with numbered step-by-step breakdowns and highlighted final answers |
| Practice | 3 practice problems; each has a "Show Hint" toggle and a "Reveal Solution" toggle |
Content generation flow:
- Screen mounts → checks AsyncStorage for cached content (
lesson_content_v1_{lessonId}). - Cache hit → renders immediately (zero API cost).
- Cache miss → calls
generateLessonContent()→ GPT-4o returns structured JSON. - Content cached, then rendered.
- Refresh button (↻) in header → clears cache, regenerates fresh content.
The quiz lobby with multiple entry points.
Stats Banner — live stats from quiz history:
- Average score %, total quizzes, total correct answers, best score %.
History Panel — toggle via clock icon:
- Last 8 results with grade letter (A+ → F), mode, topic, score, time, date.
- "Clear all" button with destructive confirmation.
Quiz Modes:
| Mode | Questions | Time | Description |
|---|---|---|---|
| Quick Quiz | 5 | Untimed | Mixed topic warm-up |
| Topic Quiz | 10 | Untimed | Pick any of 10 topics |
| Daily Challenge | 8 | Untimed | Same set for all users each day (seeded RNG) |
| Timed Sprint | 10 | 30s/Q | Countdown per question |
Quiz by Topic — 10 topic chips: Arithmetic, Algebra, Geometry, Trigonometry, Calculus, Statistics, Number Theory, Linear Algebra, Pre-Calculus, Discrete Math.
By Difficulty — 3 cards (8 questions each): Easy (green) · Medium (amber) · Hard (red).
The in-quiz experience.
- Header: Quit button · Question counter (3/10) · Topic badge · Timer.
- Progress bar: Animated fill keyed to current question index.
- Question card: Difficulty badge, subtopic label, question text.
- Option buttons (A–D):
- Before answer: neutral styling, tappable.
- After answer: correct = green highlight + ✓ icon; selected-wrong = red + ✗; unselected options dimmed.
- Explanation card: Shown immediately after answering with a lightbulb icon and full explanation text.
- Next / See Results CTA: advances or finishes.
- Timed Sprint: countdown changes green → amber (≤10s) → red (≤5s); auto-submits on zero (recorded as "Timed out").
Full post-quiz debrief.
- Grade circle: Large coloured ring showing letter grade and percentage.
- Stat chips: Correct · Wrong · Time taken · Accuracy.
- Action row: Try Again · New Quiz · Home.
- Answer Review: Full collapsible list of every question:
- Coloured left border (green = correct, red = wrong).
- All 4 options shown with correct/wrong colouring.
- Explanation box with topic and difficulty badges.
- "Timed out" badge where applicable.
Grade scale:
| Grade | Range | Colour |
|---|---|---|
| A+ | 95–100% | Emerald |
| A | 85–94% | Green |
| B | 75–84% | Teal |
| C | 60–74% | Amber |
| D | 50–59% | Orange |
| F | 0–49% | Red |
Library of all previously scanned problems.
- Grouped by date (Today / Yesterday / date).
- Each card shows: thumbnail, topic tag, difficulty, solution preview.
- Tap card → full solution detail view.
- Swipe-to-delete / "Clear all" option.
- Appearance: Light / Dark / System theme toggle (persisted).
- Notifications: (UI only — extend with
expo-notifications). - About: App version, feedback link.
math-homework-helper/
├── app/
│ ├── _layout.tsx # Root layout — providers + Stack navigator
│ ├── (tabs)/
│ │ ├── _layout.tsx # Tab bar configuration
│ │ ├── index.tsx # Home / Scan screen
│ │ ├── learn.tsx # Learn hub (3 tabs)
│ │ ├── quiz.tsx # Quiz lobby
│ │ ├── saved.tsx # Saved scans library
│ │ └── settings.tsx # App settings
│ ├── lesson.tsx # Lesson detail (AI-generated content)
│ ├── quiz-session.tsx # Active quiz screen
│ └── quiz-results.tsx # Post-quiz results & review
│
├── components/
│ ├── ProblemCard.tsx # Saved scan card component
│ ├── QuizModeCard.tsx # Quiz mode selection card
│ ├── SectionHeader.tsx # Reusable section heading
│ ├── StatCard.tsx # Stats display card
│ └── TopicCard.tsx # Topic selection card
│
├── constants/
│ ├── Colors.ts # Theme colour tokens
│ ├── data.ts # Static app data (topics, sample content)
│ ├── learnData.ts # 17 courses × lessons data model
│ └── quizData.ts # 120 questions, quiz modes, helpers
│
├── context/
│ ├── ThemeContext.tsx # Light/dark theme + colour tokens
│ ├── SavedContext.tsx # Saved scans CRUD + AsyncStorage
│ └── QuizHistoryContext.tsx # Quiz results history + stats
│
├── services/
│ └── openai.ts # GPT-4o API calls (vision + lesson gen)
│
├── assets/images/ # Icons, splash screens
├── .env # EXPO_PUBLIC_OPENAI_API_KEY
├── app.json # Expo config (bundle IDs, icons, splash)
├── package.json
└── tsconfig.json
┌─────────────────────────────────────────────────────────┐
│ React Context Layer │
│ │
│ ThemeContext ──► colour tokens to every screen │
│ SavedContext ──► saved scans array + AsyncStorage │
│ QuizHistoryContext ──► history[] + stats + AsyncStorage│
└─────────────────────────────────────────────────────────┘
│
┌─────────────▼─────────────┐
│ expo-router (Stack) │
│ /(tabs) /lesson │
│ /quiz-session │
│ /quiz-results │
└─────────────┬─────────────┘
│
┌──────────────────▼──────────────────┐
│ services/openai.ts │
│ │
│ analyzeMathImage() │
│ └─ GPT-4o Vision → solution JSON │
│ │
│ generateLessonContent() │
│ └─ Check AsyncStorage cache │
│ └─ Cache miss → GPT-4o text │
│ └─ Store to AsyncStorage │
└──────────────────┬──────────────────┘
│
┌─────────────▼─────────────┐
│ AsyncStorage │
│ quiz_history_v1 │
│ saved_scans_v1 │
│ lesson_content_v1_{id} │
│ pending_quiz_result │
└───────────────────────────┘
quiz.tsx (lobby)
│ router.push('/quiz-session', { mode, topic, difficulty, count })
▼
quiz-session.tsx
│ selectQuestions(mode, topic, difficulty, count)
│ └─ filters QUESTIONS[] by topic/difficulty
│ └─ shuffles (daily mode: seeded by YYYYMMDD)
│ commitAnswer(idx) → builds SessionAnswer[]
│ finishQuiz()
│ ├─ addResult(SessionResult) → QuizHistoryContext
│ └─ AsyncStorage.setItem('pending_quiz_result', JSON)
│ router.replace('/quiz-results')
▼
quiz-results.tsx
│ AsyncStorage.getItem('pending_quiz_result')
└─ renders grade, stats, full answer review
- No Redux / Zustand — the app uses React Context exclusively, which is appropriate for this data volume.
- Persistence — all user data (scans, quiz history, lesson cache) lives in
AsyncStorageand is hydrated into Context on app start. - Server state — only OpenAI calls; no backend database. This keeps the architecture simple and fully offline-capable once content is cached.
RootLayout (Stack)
├── (tabs) — Tab navigator
│ ├── index /(home)
│ ├── learn /(learn)
│ ├── quiz /(quiz)
│ ├── saved /(saved)
│ └── settings /(settings)
├── lesson /lesson?lessonId=&courseId=
├── quiz-session /quiz-session?mode=&topic=&difficulty=&count=
└── quiz-results /quiz-results
gestureEnabled: false on quiz-session and quiz-results prevents users from swiping back mid-quiz.
router.replace (not push) is used for quiz transitions to clear the back stack.
| Package | Version | Role |
|---|---|---|
expo |
~55.0.3 | Build toolchain, OTA updates, native module management |
react |
19.2.0 | UI framework |
react-native |
0.83.2 | Cross-platform mobile rendering |
typescript |
~5.9.2 | Type safety |
| Package | Version | Role |
|---|---|---|
expo-router |
~55.0.3 | File-based routing (wraps React Navigation) |
@react-navigation/native |
^7.1.28 | Navigation primitives |
react-native-screens |
~4.23.0 | Native screen containers (performance) |
| Package | Version | Role |
|---|---|---|
@expo/vector-icons |
^15.0.2 | Ionicons icon set |
react-native-safe-area-context |
~5.6.2 | Notch / home-bar safe areas |
react-native-reanimated |
4.2.1 | Fluid animations |
react-native-worklets |
0.7.2 | Reanimated worklet runtime |
expo-splash-screen |
~55.0.10 | Splash screen control |
| Package | Version | Role |
|---|---|---|
@react-native-async-storage/async-storage |
2.2.0 | Key-value persistence |
| Package | Version | Role |
|---|---|---|
expo-image-picker |
~55.0.9 | Camera + photo library access |
expo-file-system |
~55.0.9 | Read image files as base64 |
expo-constants |
~55.0.7 | App config + environment variables |
| Service | Usage |
|---|---|
| OpenAI GPT-4o | Vision: math image analysis; Text: lesson content generation |
Native fetch |
All HTTP calls — no axios dependency |
| Package | Role |
|---|---|
react-native-web |
Render React Native components in browser |
react-dom |
React DOM renderer for web target |
expo-web-browser |
In-app browser for external links |
- Node.js 20+
- npm or yarn
- Expo CLI:
npm install -g expo - iOS: Xcode 15+ with Command Line Tools (macOS only)
- Android: Android Studio with SDK 34+ and a virtual device
git clone https://github.com/your-org/math-homework-helper.git
cd math-homework-helper
npm installCreate a .env file in the project root:
EXPO_PUBLIC_OPENAI_API_KEY=sk-...your-key-here...Security note: The
EXPO_PUBLIC_prefix exposes the key to the client bundle. For production, proxy all OpenAI calls through your own backend API (see §5 below).
# Start Metro bundler
npx expo start
# Run on iOS simulator
npx expo start --ios
# Run on Android emulator
npx expo start --android
# Run in browser
npx expo start --webScan the QR code with Expo Go (iOS/Android) to test on a physical device without a build.
- Replace
EXPO_PUBLIC_OPENAI_API_KEYin.envwith a backend proxy URL (never ship raw API keys). - Set a production
bundleIdentifier(iOS) andpackage(Android) inapp.json. - Add privacy policy URL (required by both stores).
- Provide all icon sizes and a 1024×1024 App Store icon.
- Test on real devices (not just simulators).
- Increment
versioninapp.jsonandpackage.json.
Deploy a lightweight proxy (e.g., Vercel Edge Function, Supabase Edge Function, or AWS Lambda):
// api/openai-proxy.ts (Vercel example)
export default async function handler(req, res) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(req.body),
});
const data = await response.json();
res.json(data);
}Then update services/openai.ts to call https://your-api.vercel.app/api/openai-proxy instead of api.openai.com directly.
EAS is the recommended build service for Expo apps. It produces native binaries without needing Xcode or Android Studio locally.
Install EAS CLI:
npm install -g eas-cli
eas loginConfigure EAS:
eas build:configureThis creates eas.json. A typical config:
{
"cli": { "version": ">= 14.0.0" },
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"android": { "buildType": "apk" }
},
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}Build for both platforms:
eas build --platform all --profile productionRequirements:
- Apple Developer Program membership ($99/year)
- macOS with Xcode (or use EAS cloud builds)
Step 1 — Configure app.json:
{
"expo": {
"ios": {
"bundleIdentifier": "com.yourcompany.mathmentor",
"buildNumber": "1",
"supportsTablet": true,
"infoPlist": {
"NSCameraUsageDescription": "Used to photograph math problems for AI analysis.",
"NSPhotoLibraryUsageDescription": "Used to select math problem images."
}
}
}
}Step 2 — Create App Store Connect record:
- Go to appstoreconnect.apple.com.
- My Apps → + → New App.
- Fill in: name ("MathMentor"), bundle ID, SKU, language.
Step 3 — Build & submit:
eas build --platform ios --profile production
eas submit --platform iosEAS will prompt for your Apple ID credentials and automatically upload the .ipa.
Step 4 — Complete the listing:
- Screenshots (6.7" iPhone required, iPad optional).
- App description, keywords, support URL, privacy policy URL.
- Age rating questionnaire.
- Pricing (Free or paid).
Step 5 — Submit for review: Click "Submit to App Review". Typical review time: 1–3 days.
Privacy requirements:
- Declare: Camera access, Photo Library access, internet access (OpenAI).
- Must have a publicly accessible privacy policy page.
Requirements:
- Google Play Developer account ($25 one-time fee)
Step 1 — Configure app.json:
{
"expo": {
"android": {
"package": "com.yourcompany.mathmentor",
"versionCode": 1,
"permissions": [
"CAMERA",
"READ_EXTERNAL_STORAGE",
"INTERNET"
],
"adaptiveIcon": {
"foregroundImage": "./assets/images/android-icon-foreground.png",
"backgroundColor": "#E6F4FE"
}
}
}
}Step 2 — Create Play Console app:
- Go to play.google.com/console.
- Create App → fill in name, default language, app/game toggle, free/paid.
Step 3 — Build & submit:
eas build --platform android --profile production
eas submit --platform androidEAS will upload the .aab (Android App Bundle) directly to Play Console.
Step 4 — Complete the listing:
- Store listing: description, screenshots (phone + tablet), feature graphic (1024×500).
- Content rating questionnaire.
- Target audience (All ages if no adult content).
- Data safety section: declare camera, storage, and internet usage.
- Pricing & distribution: select countries.
Step 5 — Release: Play → Testing → Internal testing → Promote to Production. Initial review: 1–7 days.
Expo supports pushing JS bundle updates without re-submitting to the stores (for non-native changes).
# Install EAS Update
eas update:configure
# Push an update to production
eas update --branch production --message "Fix quiz timer bug"OTA updates are instant and require no store review for JavaScript-only changes.
The most effective model for education apps.
Free tier:
- Unlimited quiz access (all modes and topics).
- 5 AI scan credits per month.
- Access to Beginner and Intermediate courses.
- No ads.
Pro tier ($4.99/month or $39.99/year):
- Unlimited AI scans.
- All Advanced and Expert courses.
- AI-generated lesson content for every lesson.
- Detailed performance analytics and streak tracking.
- Ad-free experience.
Implementation:
- Use
react-native-purchases(RevenueCat SDK) for cross-platform in-app subscriptions. - RevenueCat handles receipt validation, entitlement checks, and subscription management.
npm install react-native-purchasesimport Purchases from 'react-native-purchases';
// Initialize
Purchases.configure({ apiKey: 'appl_...', appUserID: userId });
// Check entitlement
const { customerInfo } = await Purchases.getCustomerInfo();
const isPro = customerInfo.entitlements.active['pro'] !== undefined;Simpler than subscriptions — appealing to users who resist recurring fees.
- "MathMentor Lifetime" — $19.99 one-time purchase unlocks all content forever.
- Lower monthly recurring revenue but higher initial conversion.
Sell Advanced/Expert course bundles as non-consumable in-app purchases:
| Bundle | Price | Contents |
|---|---|---|
| Calculus Pack | $3.99 | Calculus I + II + Multivariable |
| Higher Math Pack | $4.99 | Linear Algebra + Diff Equations + Real Analysis |
| Complete Library | $9.99 | All 17 courses |
If subscriptions underperform, add opt-in or interstitial ads for free users.
- Use Google AdMob via
expo-ads-admoborreact-native-google-mobile-ads. - Show a banner ad at the bottom of the quiz results screen for free users.
- Offer "Remove ads" as a $1.99 one-time purchase.
Avoid intrusive ads in the middle of quiz sessions — this will hurt retention.
Offer institutional licenses for schools and tutoring centres:
- Bulk seat licences (e.g., $2/student/month for 30+ seats).
- Teacher dashboard for tracking student progress (requires a backend).
- White-label option with school branding.
Contact-based sales via a simple landing page with a "Get a quote" form.
- Always show annual price as "X per month" (e.g., "$3.33/month billed annually").
- Offer a 7-day free trial for Pro — most revenue from subscriptions comes from trial-to-paid conversion.
- Surface the paywall after a positive moment (e.g., after completing a quiz with a good grade).
- A/B test pricing: start at $4.99 and test $6.99 — education apps often support higher prices.
| Metric | Conservative | Optimistic |
|---|---|---|
| Monthly Active Users | 5,000 | 20,000 |
| Free-to-Pro conversion | 3% | 6% |
| Pro subscribers | 150 | 1,200 |
| Monthly revenue | ~$750 | ~$6,000 |
| Annual revenue | ~$9,000 | ~$72,000 |
Growth levers: ASO (App Store Optimisation), teacher referral programmes, social media presence, and partnerships with tutoring platforms.
- Fork the repo and create a feature branch.
- Run
npx expo startand verify on both iOS and Android. - Open a pull request with a clear description of the change.
MIT © 2024 Your Name / Your Company