Never miss another exam date.
A beautifully minimal mobile app to track upcoming exams, set smart reminders, and keep all your resources in one place.
| Feature | Description |
|---|---|
| 📋 Watchlist | Pin exams you care about and see a "Next Up" hero card with a live countdown |
| 🔍 Explore All Exams | Browse, search, and filter exams by category (UPSC, SSC, Banking, Railways, etc.) |
| ⏰ Smart Reminders | Schedule notifications at customizable offsets — 1 week, 1 day, 1 hour before, or any custom value |
| 📄 Resource Links | One-tap access to syllabus PDFs, previous year papers, and official websites |
| 🌗 Dark & Light Themes | A pure black/white theme system with persistent preference |
| 🚀 Onboarding Flow | Smooth first-launch experience — enter your name, pick exams, and get started |
| 📱 Skeleton Loading | Polished loading states with animated skeletons while data loads |
| 📊 Analytics Sync | Anonymous device-level usage synced to Supabase for growth insights |
| Layer | Technology |
|---|---|
| Framework | React Native via Expo (SDK 54) |
| Navigation | React Navigation (Bottom Tabs) |
| Database | Supabase (PostgreSQL + Row Level Security) |
| Local Storage | AsyncStorage for watchlist, preferences, and offline state |
| Notifications | expo-notifications with custom scheduling |
| Fonts | Google Fonts — Instrument Sans & DM Mono |
| Animations | React Native Reanimated + Gesture Handler |
ExamTracker/
├── App.js # Root — fonts, providers, tab navigation
├── src/
│ ├── components/
│ │ ├── ExamDetailSheet.js # Full-screen exam detail modal
│ │ ├── RichText.js # Markdown-style content renderer
│ │ ├── SkeletonCard.js # Loading skeleton for exam cards
│ │ ├── SkeletonWatchCard.js # Loading skeleton for watchlist cards
│ │ ├── ThemeSwitch.js # Dark/light mode toggle switch
│ │ ├── TimerBlocks.js # Countdown timer UI (block layout)
│ │ └── TimerInline.js # Countdown timer UI (inline layout)
│ ├── context/
│ │ ├── AppContext.js # Global state — exams, watchlist, user
│ │ └── ThemeContext.js # Theme provider (dark/light colors)
│ ├── lib/
│ │ └── supabase.js # Supabase client initialization
│ ├── screens/
│ │ ├── AllExamsScreen.js # Browse & search all exams
│ │ ├── CalendarScreen.js # Calendar view of exams
│ │ ├── OnboardingScreen.js # First-launch onboarding flow
│ │ ├── SettingsScreen.js # Notification & theme preferences
│ │ └── WatchlistScreen.js # Pinned exams with "Next Up" hero
│ └── utils/
│ ├── notifications.js # Notification scheduling & management
│ ├── time.js # Date/time formatting helpers
│ └── urlUtils.js # URL validation & linking helpers
├── supabase/
│ ├── schema.sql # Full database schema with RLS policies
│ ├── migration.sql # Incremental migration scripts
│ └── seedingdata.sql # Sample exam data for development
├── assets/ # App icons, splash screens, animations
└── android/ # Android native project (EAS Build)
- Node.js 18+ (LTS recommended)
- npm or yarn
- Expo Go on your phone, or an Android/iOS emulator
git clone https://github.com/ipmen-in/ExamTracker.git
cd ExamTracker
npm installCreate a .env file in the project root:
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here- Create a new project at supabase.com
- Open the SQL Editor and run
supabase/schema.sqlto create tables with RLS policies - (Optional) Run
supabase/seedingdata.sqlto populate sample exam data
npx expo startScan the QR code with Expo Go or press a for Android emulator / i for iOS simulator.
npx expo run:androidNote: Full notification scheduling with channels requires a custom dev client or standalone build — Expo Go has limitations.
Security model:
categoriesandexamsare read-only for all app users — onlyservice_rolecan modify datauserscan only read/update their own row (matched bydevice_idheader)- Exam images stored in a public read-only Supabase Storage bucket
| Package | Purpose |
|---|---|
@supabase/supabase-js |
Database client |
@react-navigation/bottom-tabs |
Tab-based navigation |
react-native-reanimated |
Smooth animations |
react-native-gesture-handler |
Swipe & gesture support |
react-native-safe-area-context |
Safe area inset handling |
@react-native-async-storage/async-storage |
Persistent local storage |
expo-notifications |
Local push notifications |
expo-image-picker |
Image selection |
| Key | Type | Description |
|---|---|---|
watchlist |
string[] |
Array of pinned exam IDs |
notification_prefs |
number[] |
Minutes-before values, e.g. [10080, 1440, 60] |
notification_ids |
object |
Scheduled notification IDs keyed by exam ID |
userName |
string |
User's display name from onboarding |
onboardingComplete |
"true" |
Whether onboarding has been completed |
theme |
"dark" | "light" |
Preferred color scheme |
deviceId |
string |
Persistent UUID for analytics |
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a branch —
git checkout -b feat/your-feature - Make your changes — test on both Android and iOS
- Add migrations — any DB changes go in
supabase/migration.sql - Open a PR with a clear description
- GitHub Actions CI (lint, typecheck, build)
- End-to-end tests for onboarding & notification flows
- Exam sharing via deep links
- Study timer / Pomodoro integration
- Push notification support via Supabase Edge Functions
This project is licensed under the MIT License — see the LICENSE file for details.
Built with ❤️ by Team IPMen