Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ temp/
# Add your project-specific ignores here
uploads/
public/uploads/
storage/
/storage/

# Drizzle
drizzle/
Expand Down
16 changes: 13 additions & 3 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
[
"@semantic-release/commit-analyzer",
{
"releaseRules": [
{ "scope": "mobile", "release": false }
]
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"@semantic-release/exec",
{
"prepareCmd": "node scripts/update-version.js ${nextRelease.version}"
"prepareCmd": "node scripts/update-version.js ${nextRelease.version}",
"publishCmd": "node scripts/update-mobile-version.js"
}
],
[
Expand All @@ -17,7 +25,9 @@
"CHANGELOG.md",
"package.json",
"src/constants/version.ts",
"apps/desktop/package.json"
"apps/desktop/package.json",
"apps/mobile/v1/package.json",
"apps/mobile/v1/app.json"
],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
Expand Down
10 changes: 10 additions & 0 deletions apps/mobile/v1/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Clerk Authentication
# Get your publishable key from https://dashboard.clerk.com
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key_here

# API Configuration
# Set to your API endpoint
EXPO_PUBLIC_API_URL=https://api.typelets.com/api

# Development/Testing
# EXPO_PUBLIC_API_URL=http://localhost:3000/api
44 changes: 44 additions & 0 deletions apps/mobile/v1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/
expo-env.d.ts

# Native
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env
.env*.local

# typescript
*.tsbuildinfo

app-example

# generated native folders
/ios
/android
236 changes: 236 additions & 0 deletions apps/mobile/v1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
# Typelets Mobile App

React Native mobile application for Typelets - a secure, encrypted note-taking platform.

## Features

- πŸ” **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

## Tech Stack

- **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)

## Architecture

### Modular Structure

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
```

### Key Modules

**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

## Getting Started

### Prerequisites

- 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

### Installation

1. **Install dependencies**
```bash
npm install
```

2. **Set up environment variables**
```bash
cp .env.example .env
```

Edit `.env` and add:
```
EXPO_PUBLIC_API_URL=your_api_url
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_key
```

3. **Start development server**
```bash
npx expo start
```

4. **Run on device/emulator**
- Press `a` for Android
- Press `i` for iOS
- Scan QR code with Expo Go app

### Building for Production

#### Android (Preview Build)
```bash
eas build --platform android --profile preview
```

#### Android (Production Build)
```bash
eas build --platform android --profile production
```

#### iOS (Production Build)
```bash
eas build --platform ios --profile production
```

## Development

### Linting
```bash
npm run lint
```

### Type Checking
```bash
npx tsc --noEmit
```

### Clear Cache
```bash
npx expo start --clear
```

## Project Structure

### Screens
- `app/index.tsx` - Folders list (home)
- `app/folder-notes.tsx` - Notes in a folder
- `app/view-note.tsx` - View note (read-only)
- `app/edit-note.tsx` - Edit note with TipTap
- `app/settings.tsx` - App settings

### API Integration

The app uses a modular API service with automatic authentication:

```typescript
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'
});
```

### Encryption

Master password encryption is handled automatically:

```typescript
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);
```

## Configuration

### EAS Build Configuration

See `eas.json` for build profiles:
- **development**: Dev client builds
- **preview**: Internal testing builds
- **production**: App Store/Play Store builds

### App Configuration

See `app.json` for:
- App name, bundle identifiers
- Icon and splash screen
- iOS/Android specific settings
- App version (auto-updated by semantic-release)

## Version Management

App versions are automatically managed by semantic-release based on conventional commits:

- `feat(mobile):` β†’ Minor version bump
- `fix(mobile):` β†’ Patch version bump
- `refactor(mobile):` β†’ Patch version bump
- Breaking changes β†’ Major version bump

The version is synced across:
- `package.json`
- `app.json` (expo.version)
- iOS buildNumber (auto-incremented)
- Android versionCode (auto-incremented)

## Security

- **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

## Contributing

1. Create a feature branch from `main`
2. Use conventional commits: `feat(mobile):`, `fix(mobile):`, etc.
3. Run linting before committing: `npm run lint`
4. Test on both iOS and Android if possible
5. Create a PR with clear description

## Resources

- [Expo Documentation](https://docs.expo.dev/)
- [React Native Documentation](https://reactnative.dev/)
- [Clerk Documentation](https://clerk.com/docs)
- [EAS Build](https://docs.expo.dev/build/introduction/)

## License

See main repository LICENSE file.
Loading