This is a piano/instrument practice app that helps musicians decide what to practice. The core problem: "I often don't know what I should practice, and I want the app to help me pick."
- Previous attempt: Flutter — didn't like the developer experience
- New stack: Expo + React Native + NativeWind (Tailwind CSS) + Firebase + TypeScript
- Why Expo over React + Vite + Capacitor: Expo supports a web-first workflow (
npx expo start --web) while providing true native mobile components. This avoids a costly migration later (60-70% UI rewrite) if we started with standard React web and later wanted native mobile. - Why Firebase: Developer is already familiar with Firebase. Firebase offers excellent offline support (built-in Firestore offline persistence), real-time sync, and a mature ecosystem. The existing Flutter project already uses Firebase.
- Development approach: Solo developer with heavy Copilot/AI assistance
- Users: Multi-user with accounts and authentication
- Data: Practice pieces (with PDF sheet music), practice sessions, practice plans
- Offline: Must work offline (practicing without wifi) — Firestore's built-in offline persistence handles this
- File uploads: PDF/sheet music uploads to Firebase Cloud Storage
- UI complexity: Starts simple (lists, cards, buttons), grows to include timers, animations, and eventually PDF annotations
- Mobile look: Should look like a native iOS/Android app (platform conventions)
- Push notifications: Not needed
- App store: Maybe eventually (Android first, iOS later)
- Platform: Android primarily (developer's device), web-first for development
| Layer | Technology | Why |
|---|---|---|
| Framework | React Native (via Expo SDK 55+) | Universal: web + iOS + Android |
| Routing | Expo Router v4+ | File-based, works on web and mobile |
| Styling | NativeWind (Tailwind CSS) | Same Tailwind utility classes |
| UI Components | React Native Paper or Tamagui | Cross-platform native-feeling UI |
| State management | TanStack Query + Zustand | Server state + client state |
| Auth | Firebase Authentication | Email + social login, familiar API |
| Database | Cloud Firestore | NoSQL with built-in offline persistence & real-time sync |
| File storage | Firebase Cloud Storage | PDF/sheet music uploads |
| Build/deploy | EAS Build + EAS Submit | Cloud builds for iOS/Android |
| Testing | Jest + React Native Testing Library | Expo's default test setup |
| Language | TypeScript | Type safety, better AI completions |
Expo fully supports developing and testing entirely in the browser:
- Run
npx expo start --web— app opens in your browser - Develop, debug, and test entirely in the browser
- Use Chrome DevTools, React DevTools — just like standard React web dev
- File-based routing (
app/directory) works identically on web and mobile - When ready for mobile: press
afor Android emulator or scan QR code with Expo Go - Platform-specific code uses
Component.web.tsx/Component.native.tsxfile splits
You don't need an Android emulator or phone until Phase 6 (Mobile Polish).
| Web (HTML) | React Native | Notes |
|---|---|---|
<div> |
<View> |
Generic container |
<p>, <span> |
<Text> |
All text must be in <Text> |
<button> |
<Pressable> |
Touchable element |
<input> |
<TextInput> |
Text input field |
<img> |
<Image> |
Image component |
scrollable <div> |
<ScrollView> |
Scrollable container |
| virtualized list | <FlatList> |
For long lists (performant) |
Tailwind classes are the same via NativeWind: <View className="flex-1 p-4 bg-white">.
- Scaffold Expo project with Expo Router + TypeScript
- Configure NativeWind (Tailwind CSS)
- Set up Firebase project (auth, Firestore, storage)
- Implement login/signup (email + social via Firebase Auth)
- Basic layout shell (tabs, header) — test on web only
- Design Firestore data model (collections: pieces, categories)
- Set up Firestore security rules
- Build CRUD UI for managing practice pieces
- PDF upload and viewing for sheet music (Firebase Cloud Storage)
- Enable Firestore offline persistence for offline support
- Practice timer with start/stop/pause
- Session logging (piece, duration, notes, quality rating)
- Practice history and statistics
- Basic "what to practice" recommendation logic
- Algorithm to suggest what to practice based on:
- Time since last practice
- Difficulty level and mastery progress
- User-defined goals and priorities
- Dashboard with practice overview and suggestions
- Verify Firestore offline persistence works across all features
- Cache PDFs locally for offline sheet music viewing
- Handle edge cases (conflict resolution, stale data indicators)
- Offline-first UX patterns (optimistic updates, sync indicators)
- Test on Android device/emulator
- Platform-specific UI tweaks (
.native.tsxoverrides where needed) - EAS Build for Android APK/AAB
- Optional Google Play Store publish
- PDF annotation support
- Practice reminders/scheduling
- Progress tracking with charts
- iOS support via EAS Build
- Firestore offline persistence: Firestore has built-in offline support — data is cached locally and synced automatically when connectivity returns. This is a major advantage over manual sync solutions.
- Incremental complexity: Start with simple lists and cards. Add animations, timers, and PDF features progressively.
- Platform splits: When mobile needs differ from web, use
Component.web.tsx/Component.native.tsx— Expo auto-picks the right one. - Existing Flutter code: This repo contains a previous Flutter implementation. The Expo rewrite will replace it entirely. Reference the existing code for feature/data model inspiration.
- Firebase project: This repo already has Firebase config (
.firebaserc,firebase.json,firestore.rules). Reuse the existing Firebase project and Firestore rules as a starting point.