Documents Vault
A private, offline-first mobile app to scan, store, and view your important documents.
Built with Expo + React Native.
Features • Tech Stack • Getting Started • Development Build • Project Structure • Privacy • Contributing • License
- Document scanning — Uses the native document scanner to capture the front and back of ID cards sequentially. Requires a development build (not Expo Go).
- Offline-first — All data and images are stored locally on-device. No network requests, no accounts, no telemetry.
- 3D flip viewer — Swipe or tap to flip between the front and back of a card, powered by Reanimated shared values and gestures.
- Save to device gallery — Save card images to the native photo library during creation or from the card detail view, using
expo-media-library. - Light / Dark / System theme — Persisted theme preference with a clean monochrome palette.
- Review & save — Preview both sides, add a name and optional note, then save to the local database.
- Card grid — 2-column grid of cards with staggered entrance animations.
- Settings — App info, privacy statement, and appearance controls.
| Layer | Technology |
|---|---|
| Framework | Expo SDK 54 |
| UI | React Native 0.81, Reanimated 4, Gesture Handler 2 |
| Navigation | Expo Router (file-based) |
| Database | SQLite via expo-sqlite + Drizzle ORM |
| Fonts | Geist & Geist Mono (@expo-google-fonts/geist) |
| Scanner | @dariyd/react-native-document-scanner |
| Images | expo-image, stored as JPG files in FileSystem.documentDirectory |
| TypeScript | Strict mode, path aliases @/* → ./src/* |
npm installThe document scanner (@dariyd/react-native-document-scanner) is a native module that is not included in Expo Go. To scan documents, run the app in a development build.
Local build (simulator, emulator, or connected device):
npm run ios # iOS
npm run android # AndroidThese commands compile the native app with the scanner module and start Metro.
EAS cloud build (physical devices without a local toolchain):
eas build --platform android --profile development
eas build --platform ios --profile developmentInstall the resulting build on your device, then connect to Metro with npx expo start --dev-client.
If you already have a development build installed:
npm startFor EAS-built dev clients, use npx expo start --dev-client instead.
npm run lintBuild and distribute the app using EAS Build.
- EAS CLI:
npm install -g eas-cli - Log in to your Expo account:
eas login
| Profile | Type | Use case |
|---|---|---|
development |
Dev client | Debug builds with the dev menu |
preview |
Internal distribution | Share with testers via QR or link |
production |
App store release | Production binary for submission |
eas build --platform android --profile previewFor a development build:
eas build --platform android --profile developmentFor a production build:
eas build --platform android --profile productioneas build --platform ios --profile previewNote: iOS builds require an active Apple Developer account and are only available on macOS.
For all available options, see the EAS Build documentation.
ivault/
├── assets/ # App icons & images
├── drizzle/ # Drizzle Kit migration output
├── src/
│ ├── app/ # Expo Router file-based routes
│ │ ├── _layout.tsx # Root layout (fonts, theme, stack nav)
│ │ ├── index.tsx # Home screen (card grid / empty state)
│ │ ├── capture.tsx # Document scanner (front → back)
│ │ ├── transform.tsx # Review & save captured images
│ │ ├── settings.tsx # Theme toggle, about, privacy info
│ │ └── card/[id].tsx # Card detail with 3D flip viewer
│ ├── components/ # Reusable UI components
│ │ ├── flip-card.tsx # 3D flip card (pan + tap gestures)
│ │ ├── card-face.tsx # Single card face with animated style
│ │ ├── card-grid.tsx # 2-column FlatList of card thumbnails
│ │ ├── card-thumbnail.tsx # Pressable card preview
│ │ ├── empty-state.tsx # Empty state with CTA
│ │ ├── themed-text.tsx # Theme-aware Text component
│ │ └── themed-view.tsx # Theme-aware View component
│ ├── constants/
│ │ └── theme.ts # Colors, fonts, spacing, radii, motion
│ ├── contexts/
│ │ └── theme-context.tsx # Theme mode provider & persistence
│ ├── db/
│ │ ├── index.ts # SQLite + Drizzle initialization
│ │ └── schema.ts # Cards table schema
│ ├── hooks/
│ │ ├── use-cards.ts # CRUD hook with auto-refresh on focus
│ │ ├── use-color-scheme.ts # Resolved light/dark from theme context
│ │ └── use-theme.ts # Returns current Colors palette
│ └── utils/
│ └── image-loader.ts # Delete card image files
├── drizzle.config.ts # Drizzle Kit configuration
├── tsconfig.json # TypeScript config with path aliases
└── package.json
IVault is built as an offline-first application.
- All documents and data are stored exclusively on your device.
- Nothing is ever sent to any server, API, or third party.
- No accounts, no telemetry, no tracking.
Contributions are welcome! Please open an issue or submit a pull request.
- Fork the repository.
- Create a feature branch (
git checkout -b feat/amazing-feature). - Commit your changes (
git commit -m 'Add amazing feature'). - Push to the branch (
git push origin feat/amazing-feature). - Open a Pull Request.