Storage Strategy#
Related Documents:
- Lexicon Schemas - AT Protocol record structures
- Data Models - TypeScript interfaces
- Architecture Overview - System design
Overview#
Drydown uses a hybrid storage strategy: LocalStorage for in-progress reviews (client-side), and AT Protocol repositories for completed reviews and settings (distributed, user-owned).
Status: 🔴 Planned
Storage Layers#
Layer 1: LocalStorage (In-Progress Reviews)#
Purpose: Auto-save review drafts during the multi-hour creation process
Data Stored:
- In-progress reviews (Stage 1 only, Stage 1+2, etc.)
- Review metadata (timestamps, fragrance info)
- Current stage data
Why LocalStorage:
- Fast, synchronous access
- No network required
- Survives page refreshes
- User may complete review over many hours
Key Format:
localStorage.setItem('drydown:review:${timestamp}', JSON.stringify(reviewData))
Limitations:
- ~5-10MB storage limit
- Cleared if user clears browser data
- Not synced across devices
- Only available on same browser
Migration Strategy: When review is completed, it's moved from LocalStorage to AT Protocol repository and removed from LocalStorage.
Layer 2: AT Protocol Repository (Completed Reviews & Settings)#
Purpose: Permanent, user-owned storage for completed reviews and user settings
Data Stored:
- Completed reviews (
social.drydown.reviewrecords) - User settings (
social.drydown.settingsrecord)
Why AT Protocol:
- User owns their data
- Synced across devices
- Survives app uninstall
- Portable to other apps
- Federated, distributed storage
Record Collections:
social.drydown.review- Multiple records per user (one per fragrance)social.drydown.settings- Single record per user
Access Method: @atproto/api Agent with OAuth session
Data Flow#
Creating a New Review#
- User starts review → Save to LocalStorage with timestamp ID
- User completes Stage 1 → Update LocalStorage record
- User waits 2-4 hours
- User completes Stage 2 → Update LocalStorage record
- User waits 4+ hours
- User completes Stage 3 & text → Calculate final rating
- Save to AT Protocol → Create
social.drydown.reviewrecord - Remove from LocalStorage → Clean up draft
- Update UI → Show in completed reviews list
Loading Reviews on App Start#
- App initializes → Load from LocalStorage for in-progress reviews
- OAuth session restored → Fetch from AT Protocol for completed reviews
- Fetch settings → Load
social.drydown.settingsrecord - Render UI → Display both in-progress and completed reviews
Updating Settings#
- User changes weights → Update in-memory state
- User clicks "Save" → Store to AT Protocol (
putRecord) - Recalculate ratings → Update all completed reviews' calculated ratings
- Update UI → Re-sort and display updated ratings
Synchronization#
LocalStorage → AT Protocol#
Trigger: Review completion
Process:
- Validate review data (all required stages present)
- Calculate final weighted rating
- Create AT Protocol record via
createRecord() - On success: Remove from LocalStorage
- On failure: Keep in LocalStorage, show retry button
AT Protocol → LocalStorage#
Trigger: Not applicable (one-way sync)
Rationale: Completed reviews don't need to be copied back to LocalStorage. They're fetched from AT Protocol on demand.
Offline Support#
Current Behavior (Planned)#
Creating Reviews:
- Works offline (LocalStorage)
- Shows warning: "Connection lost. Changes saved locally."
- Sync attempted when connection restored
Viewing Completed Reviews:
- Requires network (AT Protocol fetch)
- Shows cached data if available
- Shows error if offline and no cache
Future Enhancement (Service Worker)#
- Cache completed reviews for offline viewing
- Queue AT Protocol writes when offline
- Sync automatically when online
Data Retention#
LocalStorage#
Retention: Indefinite (until user clears browser data)
Cleanup Strategy:
- Completed reviews removed immediately after AT Protocol sync
- In-progress reviews remain until completed or manually deleted
- Future: Auto-expire in-progress reviews after 30 days
AT Protocol Repository#
Retention: Permanent (user controls deletion)
Deletion:
- User can delete individual reviews (future feature)
- User can delete entire account (AT Protocol account deletion)
Error Handling#
LocalStorage Quota Exceeded#
Error: QuotaExceededError
Handling:
- Catch error when writing
- Show user-friendly message: "Storage full. Please complete or delete in-progress reviews."
- Highlight oldest in-progress reviews
- Offer bulk delete option
AT Protocol Network Errors#
Error: Network failure, timeout, server error
Handling:
- Keep data in LocalStorage
- Show error message: "Failed to save review. Saved locally. Retry?"
- Offer manual retry button
- Auto-retry on connection restore
AT Protocol Session Expiry#
Error: 401 Unauthorized
Handling:
- Keep data in LocalStorage
- Show message: "Session expired. Please log in again."
- Redirect to login
- After re-auth, resume save operation
Performance Considerations#
LocalStorage#
Reads: Synchronous, fast (<1ms typically)
Writes: Synchronous, fast (<5ms typically)
Optimization: Debounce auto-save (every 2 seconds, not every keystroke)
AT Protocol#
Reads: Async, network-dependent (100-500ms typically)
Writes: Async, network-dependent (200-1000ms typically)
Optimization:
- Cache fetched reviews in memory
- Batch updates when possible
- Show loading states
- Implement retry with exponential backoff
Security & Privacy#
LocalStorage#
Security:
- Same-origin policy (secure)
- Not encrypted at rest (browser manages)
- Accessible to XSS attacks (sanitize all inputs)
Privacy:
- Stored locally on user's device
- Not sent to servers
- Cleared when user clears browser data
AT Protocol Repository#
Security:
- OAuth authentication required
- DPoP tokens for API requests
- HTTPS required
Privacy:
- User owns data in their PDS
- User controls access
- No centralized database
- Reviews private until shared to Bluesky
Related Documents:
- Lexicon Schemas - Record structures
- Data Models - TypeScript interfaces
- AT Protocol Repo API - API operations