A privacy-first, zero-infrastructure TOTP authenticator built with React Native (Expo) and Pear Runtime. Your 2FA secrets never touch a server — they live on your device, encrypted at rest, and will sync across your devices peer-to-peer via Autopass.
Most authenticator apps make you choose between convenience (cloud backup) and privacy (local only). Fidel removes that tradeoff — your secrets stay on your device and sync directly to your other devices, with no server ever in the middle.
| Google / Microsoft | Fidel | |
|---|---|---|
| Secret storage | Synced to Google/Microsoft servers | Device only, encrypted at rest |
| Account required | Yes (Google/Microsoft account) | No — zero sign-up |
| Vendor lock-in | Lose your account → lose your codes | Secrets are yours, no dependency |
| Open source | Closed source | Fully auditable |
| Sync | Cloud (their servers) | P2P direct device-to-device |
- No phone number required — Authy ties your vault to a phone number; if Twilio locks your account, you're locked out. Fidel has no registration at all.
- No proprietary server — Authy backups live on Authy's servers. Fidel syncs peer-to-peer.
- No single point of failure — Authy going down or shutting down means you lose access. Fidel has no central service to go down.
- Free forever — 1Password requires a paid plan for TOTP. Fidel is MIT licensed with no subscription.
- Purpose-built — password managers bolt on TOTP as a feature. Fidel is offline-first and built around authenticator UX.
- No master password risk — your 2FA codes aren't bundled with your passwords in a single breach target.
Most authenticators make a security vs. convenience tradeoff — no backup (risky) or cloud backup (trusts a third party). Fidel's P2P sync removes that tradeoff: multi-device, fully encrypted, zero servers.
| QR code scanning | Scan any otpauth://totp/... QR code (Google Authenticator standard) |
| Manual entry | Add accounts with issuer name, email, and base32 secret key |
| Live 6-digit codes | Codes refresh every second with an animated 30-second countdown ring |
| Copy on tap | Tap any account card to copy the current code with haptic feedback |
| Biometric lock | Face ID or fingerprint secures the entire vault on app launch |
| Delete accounts | Long-press any card to remove it with a confirmation prompt |
| Fully offline | Works with no internet connection — all TOTP computation is local |
| P2P sync | Device-to-device vault sync via Autopass (in development) |
Home screen · Add account · Empty state onboarding
┌─────────────────────────────────────┐
│ React Native (UI) │
│ expo-router · TypeScript · Expo │
│ │
│ useVault() — TOTP + storage │
│ useBiometrics() — Face ID / Touch │
└──────────────┬──────────────────────┘
│
┌───────────▼───────────┐
│ expo-secure-store │ ← encrypted on-device vault
└───────────────────────┘
┌───────────────────────┐ (future)
│ Bare Worklet │
│ Autopass · Hyperswarm│ ← P2P sync thread
└───────────────────────┘
TOTP codes are generated entirely in JavaScript with a pure-JS SHA-1 + HMAC-SHA1 implementation (RFC 6238). No native modules, no Web Crypto API dependency — it runs on any Hermes version.
Secrets are stored in expo-secure-store under a single encrypted JSON blob (fidel_accounts_v1). On iOS this uses the Keychain; on Android it uses EncryptedSharedPreferences. Secrets are stripped before they ever reach the UI layer — only { id, issuer, account, digits, period, addedAt } is returned to components.
useVault() uses a module-level singleton store so all screen instances share the same live state. Adding an account in /add immediately appears on the home screen without any re-mount or navigation callback.
A Bare worklet running in a separate thread via react-native-bare-kit will handle Autopass/Hyperswarm P2P sync. The worklet communicates with the UI thread over a newline-delimited JSON IPC protocol. The sync layer is isolated from the core vault so the app works fully offline with zero P2P code running.
fidel/
├── app/ # expo-router screens (routes only)
│ ├── _layout.tsx # Root layout + biometric gate
│ ├── index.tsx # Home screen — live TOTP list
│ ├── add.tsx # Add account (QR scanner + manual entry)
│ └── settings.tsx # P2P sync + security settings
│
├── src/
│ ├── hooks/
│ │ ├── useVault.ts # Core vault — TOTP engine, secure storage, state
│ │ ├── useRPC.ts # Worklet IPC bridge (stub until P2P is wired)
│ │ └── useBiometrics.ts # expo-local-authentication wrapper
│ ├── components/
│ │ ├── AccountCard.tsx # TOTP card: avatar, live code, countdown ring
│ │ ├── CountdownRing.tsx # SVG animated progress ring
│ │ ├── EmptyState.tsx # Onboarding empty state
│ │ └── SyncStatusBadge.tsx # Peer count badge in header
│ └── theme/
│ └── index.ts # Colors, typography, spacing, shadows
│
├── backend/
│ ├── backend.mjs # Bare worklet source (future P2P vault)
│ └── bundle.js # Bundled worklet (output of bundle-worklet)
│
├── assets/
│ └── images/
│ └── icon.png # App icon
│
└── scripts/
└── bundle-worklet.mjs # Bare worklet bundler
- Node.js 18+
- Xcode 14+ (iOS) or Android Studio (Android)
npx expoCLI
git clone https://github.com/rkmonarch/fidel.git
cd fidel
npm installnpx expo run:iosThis performs a native build on first run (a few minutes). Subsequent launches are instant — just start Metro:
npx expo startnpx expo run:androidOpen Expo Go or a custom dev build, then scan the QR code printed by npx expo start.
- Go to your service's 2FA setup page and display the QR code.
- Tap + in Fidel → Scan QR tab.
- Grant camera permission and point at the QR code — it adds automatically.
- In your service's 2FA setup, look for "enter key manually" or "show text key".
- Tap + → Manual tab.
- Enter the service name, your account/email, and the base32 secret key.
- Tap Add Account.
The key JBSWY3DPEHPK3PXP is a standard RFC 6238 test vector. You can use it to verify Fidel generates the correct codes against any reference TOTP tool.
| Layer | Technology |
|---|---|
| UI framework | React Native 0.83 + Expo 55 |
| Navigation | expo-router (file-based) |
| Language | TypeScript |
| TOTP | RFC 6238 — pure JS SHA-1 + HMAC-SHA1 |
| Secure storage | expo-secure-store (Keychain / EncryptedSharedPreferences) |
| Biometrics | expo-local-authentication |
| QR scanning | expo-camera |
| P2P runtime | react-native-bare-kit + Bare JS |
| P2P vault | Autopass + Corestore + Hyperswarm (in development) |
| Icons | SVG via react-native-svg |
| Theme | Custom light design system (primary #0066FF) |
- Live TOTP code generation (RFC 6238)
- QR code scanner
- Manual account entry
- Biometric lock (Face ID / Fingerprint)
- Encrypted local vault (expo-secure-store)
- Animated countdown rings
- Copy on tap with haptics
- P2P device sync via Autopass/Hyperswarm
- TOTP algorithm options (SHA-256, SHA-512)
- 8-digit code support
- iCloud / Google Drive backup (opt-in)
- Account grouping / search
- Import from Google Authenticator
Pull requests are welcome. For large changes, open an issue first to discuss what you'd like to change.
# Lint / format
npx prettier --write .
# TypeScript check
npx tsc --noEmitMIT — see LICENSE.
Built by @rkmonarch · Powered by Pear Runtime / Holepunch