A futuristic, Apple-styled Progressive Web App for TOTP (Time-based One-Time Password) authentication, compatible with Google Authenticator and the Ruby totp.rb script.
Bare minimum PWA code ...
The 'app' directory contains the same minimal code.
GitHub Pages hosts the PWA at TOTP PWA
- Core TOTP Engine: RFC 6238 compliant implementation
- Custom Base32 encoding/decoding (matching Ruby implementation)
- HOTP (HMAC-based OTP) algorithm
- TOTP (Time-based OTP) with 30-second intervals
- Real-time countdown timers with progress visualization
- Storage: IndexedDB for accounts, LocalStorage for settings
- UI: Futuristic Apple-style glass morphism design
- Dark/Light/Auto theme modes
- Bootstrap 5.3 components
- Smooth animations and transitions
- Responsive mobile-first layout
- PWA: Offline-capable with service worker
- Installable on iOS and Android
- Works without internet connection
- App manifest with icons
- Add, edit, delete accounts
- Show/hide secrets
- Account menu with all operations
- Full CRUD functionality
- Camera QR code scanning
- QR code generation for accounts
- File upload for QR images
- otpauth:// URI parsing
- JSON export/import (full details)
- Base64 compact format
- otpauth:// URI export
- File upload and download
- Clipboard operations
- Batch export all accounts
- Theme presets (Classic Apple, Dark, High Contrast)
- Color customization (primary, accent)
- Size controls (fonts, spacing, radius)
- Effect controls (glass opacity, blur, shadow)
- Animation speed and toggle
- Reset to defaults
- Search/filter accounts
- Keyboard shortcuts (/, N, E, S, T, ?)
- Install prompt handling
- Update notifications
- Haptic feedback
- Auto-update checks
- RFC 4226 test vectors validation
- Ruby script compatibility testing
- Comprehensive documentation
- Git integration
cd ~/src/morganism/totp/app
python3 -m http.server 8000Then open http://localhost:8000 in your browser.
- Open the
app/folder in VS Code - Right-click
index.html→ "Open with Live Server"
Deploy to any static hosting (GitHub Pages, Netlify, Vercel, etc.)
- Click "Add Account" button
- Choose "Manual" tab
- Enter:
- Account name (e.g., user@example.com)
- Issuer (e.g., GitHub)
- Secret key (Base32 format, e.g., JBSWY3DPEHPK3PXP)
- Digits (6 or 8)
- Interval (30 or 60 seconds)
- Click "Add Account"
- Click on any displayed code to copy it to clipboard
- Codes auto-refresh every 30 seconds
- Progress bar shows remaining time
- Click the moon/sun icon in the navbar
- Cycles through: Light → Dark → Auto (system preference)
- Or press
Tkeyboard shortcut
/- Focus search barN- Add new accountE- Export all accountsS- Open settingsT- Toggle theme?- Show keyboard shortcuts helpEsc- Close modals or blur inputsSpace- Copy code (when account is focused)
To verify the JavaScript implementation matches the Ruby script:
# Terminal 1: Generate code with Ruby
cd ~/src/morganism/totp
ruby totp.rb --current --secret JBSWY3DPEHPK3PXP
# Terminal 2: Start web server
cd ~/src/morganism/totp/app
python3 -m http.server 8000
# Browser: Add account with secret JBSWY3DPEHPK3PXP
# Compare codes - they should match!The Ruby script includes test vectors. To verify:
cd ~/src/morganism/totp
ruby totp_test.rbExpected output:
PASS Base32 round-trip
PASS HOTP counter=0 => 755224
PASS HOTP counter=1 => 287082
PASS HOTP counter=2 => 359152
PASS HOTP counter=3 => 969429
PASS HOTP counter=4 => 338314
...
- Frontend: Vanilla JavaScript (ES6+), Bootstrap 5.3
- Storage: IndexedDB API, LocalStorage API
- Crypto: Web Crypto API (HMAC-SHA1)
- PWA: Service Worker API, Web App Manifest
- Styling: CSS Custom Properties, Glass Morphism
app/
├── index.html # Single-page app (~50KB)
├── manifest.json # PWA manifest
├── service-worker.js # Offline caching
├── icons/
│ ├── icon-192.png # App icons
│ ├── icon-512.png
│ └── icon-maskable-512.png
└── lib/
├── qrcode.min.js # QR generation (Phase 5)
└── html5-qrcode.min.js # QR scanning (Phase 5)
encodeBase32(bytes)- Base32 encodingdecodeBase32(str)- Base32 decodinghotp(secret, counter, digits)- HMAC-based OTPtotp(secret, time, digits, interval)- Time-based OTPvalidate(secret, code, ...)- Code validationparseOtpauthURI(uri)- Parse otpauth:// URIsgenerateOtpauthURI(account)- Generate URIsgenerateSecret(length)- Random secret generation
init()- Initialize IndexedDBgetAccounts()- Retrieve all accountsaddAccount(account)- Add new accountupdateAccount(id, updates)- Update accountdeleteAccount(id)- Delete accountexportJSON()- Export to JSONimportJSON(data)- Import from JSONexportBase64()- Export to Base64importBase64(base64)- Import from Base64
get(key, default)- Get settingset(key, value)- Set settinggetAll()- Get all settingsreset()- Reset to defaultsapplyTheme(theme)- Apply theme
init()- Initialize applicationrenderAccounts()- Render account gridupdateCode(accountId)- Update TOTP codestartTimers()- Start countdown timersupdateAllTimers()- Update all timerscopyCode(accountId)- Copy code to clipboardshowToast(message, type)- Show notificationsaveAccount()- Save new account
- Glass Morphism: Frosted glass effect with
backdrop-filter: blur(20px) - SF Pro Font: Apple system font stack
- iOS Colors: Primary #007aff (iOS blue), Accent #5856d6 (iOS purple)
- Smooth Animations: Cubic Bezier easing (0.4, 0, 0.2, 1)
- Large Touch Targets: Minimum 44x44px per Apple HIG
- Rounded Corners: 16px cards, 12px buttons
- Generous Spacing: White space for clarity
All design tokens are CSS variables for easy customization:
--totp-primary: #007aff;
--totp-accent: #5856d6;
--totp-font-code: 48px;
--totp-border-radius: 16px;
--totp-glass-opacity: 0.85;
--totp-blur: 20px;- Chrome 90+ (Desktop & Android)
- Firefox 88+ (Desktop)
- Safari 14+ (macOS & iOS)
- Edge 90+ (Desktop)
- IndexedDB
- LocalStorage
- Service Workers
- Web Crypto API (HMAC-SHA1)
- Clipboard API
- CSS backdrop-filter (for glass effect)
- IndexedDB: Origin-isolated, not accessible by other sites
- No Encryption at Rest: Secrets stored in plain text
- Recommendation: Protect device with PIN/password/biometric lock
- Never log secrets to console (production mode)
- Use HTTPS in production (required for Service Workers)
- Regular backups via export functionality
- Validate Base32 secrets before storage
- First Contentful Paint: < 1.5s
- Time to Interactive: < 2.5s
- Lighthouse PWA Score: Target 100
- Offline Support: 100% functional offline
- Bundle Size: ~50KB HTML + ~60KB Bootstrap + ~19KB QR libs
# Start development server
cd ~/src/morganism/totp/app
python3 -m http.server 8000
# Or use VS Code Live Server extension- TOTP codes match Ruby script output
- Codes refresh every 30 seconds
- Countdown timer accurate
- Copy to clipboard works
- Works offline (disconnect WiFi)
- Theme switching works
- Responsive on mobile
- Service worker caches assets
- PWA installable
- No QR code scanning/generation yet (Phase 5)
- No import/export yet (Phase 6)
- No account editing/deletion yet (Phase 4)
- No search/filter yet (Phase 8)
- No customization UI yet (Phase 7)
Integrated in Phase 1.
- Edit account details
- Delete with confirmation
- Show/hide secret
- Bulk operations
- Camera scanning
- QR code generation
- otpauth:// URI parsing
- File upload support
- JSON export/import
- Base64 compact format
- Google Authenticator compatibility
- Drag-and-drop file upload
- Settings modal
- Color pickers
- Size controls
- Effect controls (blur, shadow)
- Theme presets
- Animation toggles
- Search/filter accounts
- Drag-to-reorder
- Keyboard shortcuts (Space=copy, N=new, /=search)
- Haptic feedback
- Update notifications
- Cross-browser testing
- Performance optimization
- Security audit
- Comprehensive documentation
- TOTP Algorithm: RFC 6238 / RFC 4226
- Design Inspiration: Apple iOS Human Interface Guidelines
- Compatible with: Google Authenticator, Authy, Microsoft Authenticator
- Ruby Reference:
/Users/morgan/src/morganism/totp/totp.rb
Part of the TOTP project at /Users/morgan/src/morganism/totp/
Status: All Phases Complete ✅ - Production Ready
Last Updated: 2026-03-10
Version: 1.0.0
Test: Open test.html to verify TOTP algorithm compatibility