React Native mobile application for Typelets - a secure, encrypted note-taking platform.
- 🔐 End-to-end encryption with master password protection
- 📱 Cross-platform - iOS and Android support via React Native
- 📁 Folder organization with nested folder support
- ⭐ Starred notes for quick access
- 🗑️ Trash management with restore capabilities
- 🎨 Theme support - Light and dark modes
- 🔄 Real-time sync with backend API
- 📝 Rich text editing powered by TipTap
- Framework: React Native with Expo 54
- Routing: Expo Router (file-based)
- Authentication: Clerk
- Encryption: AES-GCM with PBKDF2 key derivation
- State Management: React hooks
- Storage: Expo SecureStore
- Editor: TipTap (WebView-based)
The app follows a clean, modular architecture:
src/
├── components/ # Reusable UI components
│ ├── MasterPasswordDialog/ # Password UI (modular)
│ └── ui/ # Base UI components
├── screens/ # Main app screens
├── services/ # API and business logic
│ └── api/ # Modular API service
├── lib/ # Core libraries
│ └── encryption/ # Modular encryption service
├── hooks/ # Custom React hooks
└── theme/ # Theme configuration
API Service (src/services/api/)
- Modular REST API client with authentication
- Separated concerns: notes, folders, encryption
- Centralized error handling and pagination
Encryption Service (src/lib/encryption/)
- AES-GCM encryption with 250,000 PBKDF2 iterations
- Master password support with secure key storage
- LRU cache for decrypted notes (15-minute TTL)
Master Password UI (src/components/MasterPasswordDialog/)
- Modular password setup/unlock flows
- Custom hooks for validation and keyboard handling
- Optimized for long-running PBKDF2 operations
- Node.js 18+ and npm
- Expo CLI:
npm install -g expo-cli - For iOS: Xcode and iOS Simulator
- For Android: Android Studio and Android Emulator
-
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env
Edit
.envand add:EXPO_PUBLIC_API_URL=your_api_url EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_key -
Start development server
npx expo start
-
Run on device/emulator
- Press
afor Android - Press
ifor iOS - Scan QR code with Expo Go app
- Press
eas build --platform android --profile previeweas build --platform android --profile productioneas build --platform ios --profile productionnpm run lintnpx tsc --noEmitnpx expo start --clearapp/index.tsx- Folders list (home)app/folder-notes.tsx- Notes in a folderapp/view-note.tsx- View note (read-only)app/edit-note.tsx- Edit note with TipTapapp/settings.tsx- App settings
The app uses a modular API service with automatic authentication:
const { getNotes, createNote, getFolders } = useApiService();
// Fetch notes with encryption/decryption
const notes = await getNotes({ folderId: 'abc123' });
// Create encrypted note
await createNote({
title: 'My Note',
content: '<p>Content</p>',
folderId: 'abc123'
});Master password encryption is handled automatically:
import {
setupMasterPassword,
unlockWithMasterPassword,
hasMasterPassword
} from '@/lib/encryption';
// Setup (first time)
await setupMasterPassword('my-password', userId);
// Unlock (returning user)
const success = await unlockWithMasterPassword('my-password', userId);See eas.json for build profiles:
- development: Dev client builds
- preview: Internal testing builds
- production: App Store/Play Store builds
See app.json for:
- App name, bundle identifiers
- Icon and splash screen
- iOS/Android specific settings
- App version (auto-updated by semantic-release)
App versions are automatically managed by semantic-release based on conventional commits:
feat(mobile):→ Minor version bumpfix(mobile):→ Patch version bumprefactor(mobile):→ Patch version bump- Breaking changes → Major version bump
The version is synced across:
package.jsonapp.json(expo.version)- iOS buildNumber (auto-incremented)
- Android versionCode (auto-incremented)
- Encryption: AES-GCM with PBKDF2 (250k iterations)
- Key Storage: Expo SecureStore (iOS Keychain / Android Keystore)
- Authentication: Clerk with JWT tokens
- Transport: HTTPS only
- Master Password: Never stored, derived on-device
- Create a feature branch from
main - Use conventional commits:
feat(mobile):,fix(mobile):, etc. - Run linting before committing:
npm run lint - Test on both iOS and Android if possible
- Create a PR with clear description
See main repository LICENSE file.