|
| 1 | +# Typelets Mobile App |
| 2 | + |
| 3 | +React Native mobile application for Typelets - a secure, encrypted note-taking platform. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- 🔐 **End-to-end encryption** with master password protection |
| 8 | +- 📱 **Cross-platform** - iOS and Android support via React Native |
| 9 | +- 📁 **Folder organization** with nested folder support |
| 10 | +- ⭐ **Starred notes** for quick access |
| 11 | +- 🗑️ **Trash management** with restore capabilities |
| 12 | +- 🎨 **Theme support** - Light and dark modes |
| 13 | +- 🔄 **Real-time sync** with backend API |
| 14 | +- 📝 **Rich text editing** powered by TipTap |
| 15 | + |
| 16 | +## Tech Stack |
| 17 | + |
| 18 | +- **Framework**: React Native with Expo 54 |
| 19 | +- **Routing**: Expo Router (file-based) |
| 20 | +- **Authentication**: Clerk |
| 21 | +- **Encryption**: AES-GCM with PBKDF2 key derivation |
| 22 | +- **State Management**: React hooks |
| 23 | +- **Storage**: Expo SecureStore |
| 24 | +- **Editor**: TipTap (WebView-based) |
| 25 | + |
| 26 | +## Architecture |
| 27 | + |
| 28 | +### Modular Structure |
| 29 | + |
| 30 | +The app follows a clean, modular architecture: |
| 31 | + |
| 32 | +``` |
| 33 | +src/ |
| 34 | +├── components/ # Reusable UI components |
| 35 | +│ ├── MasterPasswordDialog/ # Password UI (modular) |
| 36 | +│ └── ui/ # Base UI components |
| 37 | +├── screens/ # Main app screens |
| 38 | +├── services/ # API and business logic |
| 39 | +│ └── api/ # Modular API service |
| 40 | +├── lib/ # Core libraries |
| 41 | +│ └── encryption/ # Modular encryption service |
| 42 | +├── hooks/ # Custom React hooks |
| 43 | +└── theme/ # Theme configuration |
| 44 | +``` |
| 45 | + |
| 46 | +### Key Modules |
| 47 | + |
| 48 | +**API Service** (`src/services/api/`) |
| 49 | +- Modular REST API client with authentication |
| 50 | +- Separated concerns: notes, folders, encryption |
| 51 | +- Centralized error handling and pagination |
| 52 | + |
| 53 | +**Encryption Service** (`src/lib/encryption/`) |
| 54 | +- AES-GCM encryption with 250,000 PBKDF2 iterations |
| 55 | +- Master password support with secure key storage |
| 56 | +- LRU cache for decrypted notes (15-minute TTL) |
| 57 | + |
| 58 | +**Master Password UI** (`src/components/MasterPasswordDialog/`) |
| 59 | +- Modular password setup/unlock flows |
| 60 | +- Custom hooks for validation and keyboard handling |
| 61 | +- Optimized for long-running PBKDF2 operations |
| 62 | + |
| 63 | +## Getting Started |
| 64 | + |
| 65 | +### Prerequisites |
| 66 | + |
| 67 | +- Node.js 18+ and npm |
| 68 | +- Expo CLI: `npm install -g expo-cli` |
| 69 | +- For iOS: Xcode and iOS Simulator |
| 70 | +- For Android: Android Studio and Android Emulator |
| 71 | + |
| 72 | +### Installation |
| 73 | + |
| 74 | +1. **Install dependencies** |
| 75 | + ```bash |
| 76 | + npm install |
| 77 | + ``` |
| 78 | + |
| 79 | +2. **Set up environment variables** |
| 80 | + ```bash |
| 81 | + cp .env.example .env |
| 82 | + ``` |
| 83 | + |
| 84 | + Edit `.env` and add: |
| 85 | + ``` |
| 86 | + EXPO_PUBLIC_API_URL=your_api_url |
| 87 | + EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_key |
| 88 | + ``` |
| 89 | + |
| 90 | +3. **Start development server** |
| 91 | + ```bash |
| 92 | + npx expo start |
| 93 | + ``` |
| 94 | + |
| 95 | +4. **Run on device/emulator** |
| 96 | + - Press `a` for Android |
| 97 | + - Press `i` for iOS |
| 98 | + - Scan QR code with Expo Go app |
| 99 | + |
| 100 | +### Building for Production |
| 101 | + |
| 102 | +#### Android (Preview Build) |
| 103 | +```bash |
| 104 | +eas build --platform android --profile preview |
| 105 | +``` |
| 106 | + |
| 107 | +#### Android (Production Build) |
| 108 | +```bash |
| 109 | +eas build --platform android --profile production |
| 110 | +``` |
| 111 | + |
| 112 | +#### iOS (Production Build) |
| 113 | +```bash |
| 114 | +eas build --platform ios --profile production |
| 115 | +``` |
| 116 | + |
| 117 | +## Development |
| 118 | + |
| 119 | +### Linting |
| 120 | +```bash |
| 121 | +npm run lint |
| 122 | +``` |
| 123 | + |
| 124 | +### Type Checking |
| 125 | +```bash |
| 126 | +npx tsc --noEmit |
| 127 | +``` |
| 128 | + |
| 129 | +### Clear Cache |
| 130 | +```bash |
| 131 | +npx expo start --clear |
| 132 | +``` |
| 133 | + |
| 134 | +## Project Structure |
| 135 | + |
| 136 | +### Screens |
| 137 | +- `app/index.tsx` - Folders list (home) |
| 138 | +- `app/folder-notes.tsx` - Notes in a folder |
| 139 | +- `app/view-note.tsx` - View note (read-only) |
| 140 | +- `app/edit-note.tsx` - Edit note with TipTap |
| 141 | +- `app/settings.tsx` - App settings |
| 142 | + |
| 143 | +### API Integration |
| 144 | + |
| 145 | +The app uses a modular API service with automatic authentication: |
| 146 | + |
| 147 | +```typescript |
| 148 | +const { getNotes, createNote, getFolders } = useApiService(); |
| 149 | + |
| 150 | +// Fetch notes with encryption/decryption |
| 151 | +const notes = await getNotes({ folderId: 'abc123' }); |
| 152 | + |
| 153 | +// Create encrypted note |
| 154 | +await createNote({ |
| 155 | + title: 'My Note', |
| 156 | + content: '<p>Content</p>', |
| 157 | + folderId: 'abc123' |
| 158 | +}); |
| 159 | +``` |
| 160 | + |
| 161 | +### Encryption |
| 162 | + |
| 163 | +Master password encryption is handled automatically: |
| 164 | + |
| 165 | +```typescript |
| 166 | +import { |
| 167 | + setupMasterPassword, |
| 168 | + unlockWithMasterPassword, |
| 169 | + hasMasterPassword |
| 170 | +} from '@/lib/encryption'; |
| 171 | + |
| 172 | +// Setup (first time) |
| 173 | +await setupMasterPassword('my-password', userId); |
| 174 | + |
| 175 | +// Unlock (returning user) |
| 176 | +const success = await unlockWithMasterPassword('my-password', userId); |
| 177 | +``` |
| 178 | + |
| 179 | +## Configuration |
| 180 | + |
| 181 | +### EAS Build Configuration |
| 182 | + |
| 183 | +See `eas.json` for build profiles: |
| 184 | +- **development**: Dev client builds |
| 185 | +- **preview**: Internal testing builds |
| 186 | +- **production**: App Store/Play Store builds |
| 187 | + |
| 188 | +### App Configuration |
| 189 | + |
| 190 | +See `app.json` for: |
| 191 | +- App name, bundle identifiers |
| 192 | +- Icon and splash screen |
| 193 | +- iOS/Android specific settings |
| 194 | +- App version (auto-updated by semantic-release) |
| 195 | + |
| 196 | +## Version Management |
| 197 | + |
| 198 | +App versions are automatically managed by semantic-release based on conventional commits: |
| 199 | + |
| 200 | +- `feat(mobile):` → Minor version bump |
| 201 | +- `fix(mobile):` → Patch version bump |
| 202 | +- `refactor(mobile):` → Patch version bump |
| 203 | +- Breaking changes → Major version bump |
| 204 | + |
| 205 | +The version is synced across: |
| 206 | +- `package.json` |
| 207 | +- `app.json` (expo.version) |
| 208 | +- iOS buildNumber (auto-incremented) |
| 209 | +- Android versionCode (auto-incremented) |
| 210 | + |
| 211 | +## Security |
| 212 | + |
| 213 | +- **Encryption**: AES-GCM with PBKDF2 (250k iterations) |
| 214 | +- **Key Storage**: Expo SecureStore (iOS Keychain / Android Keystore) |
| 215 | +- **Authentication**: Clerk with JWT tokens |
| 216 | +- **Transport**: HTTPS only |
| 217 | +- **Master Password**: Never stored, derived on-device |
| 218 | + |
| 219 | +## Contributing |
| 220 | + |
| 221 | +1. Create a feature branch from `main` |
| 222 | +2. Use conventional commits: `feat(mobile):`, `fix(mobile):`, etc. |
| 223 | +3. Run linting before committing: `npm run lint` |
| 224 | +4. Test on both iOS and Android if possible |
| 225 | +5. Create a PR with clear description |
| 226 | + |
| 227 | +## Resources |
| 228 | + |
| 229 | +- [Expo Documentation](https://docs.expo.dev/) |
| 230 | +- [React Native Documentation](https://reactnative.dev/) |
| 231 | +- [Clerk Documentation](https://clerk.com/docs) |
| 232 | +- [EAS Build](https://docs.expo.dev/build/introduction/) |
| 233 | + |
| 234 | +## License |
| 235 | + |
| 236 | +See main repository LICENSE file. |
0 commit comments