a a vibe-coded abomination experiment of a fragrance review platform built on the atmosphere. drydown.social

Storage Strategy#

Related Documents:

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.review records)
  • User settings (social.drydown.settings record)

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#

  1. User starts review → Save to LocalStorage with timestamp ID
  2. User completes Stage 1 → Update LocalStorage record
  3. User waits 2-4 hours
  4. User completes Stage 2 → Update LocalStorage record
  5. User waits 4+ hours
  6. User completes Stage 3 & text → Calculate final rating
  7. Save to AT Protocol → Create social.drydown.review record
  8. Remove from LocalStorage → Clean up draft
  9. Update UI → Show in completed reviews list

Loading Reviews on App Start#

  1. App initializes → Load from LocalStorage for in-progress reviews
  2. OAuth session restored → Fetch from AT Protocol for completed reviews
  3. Fetch settings → Load social.drydown.settings record
  4. Render UI → Display both in-progress and completed reviews

Updating Settings#

  1. User changes weights → Update in-memory state
  2. User clicks "Save" → Store to AT Protocol (putRecord)
  3. Recalculate ratings → Update all completed reviews' calculated ratings
  4. Update UI → Re-sort and display updated ratings

Synchronization#

LocalStorage → AT Protocol#

Trigger: Review completion

Process:

  1. Validate review data (all required stages present)
  2. Calculate final weighted rating
  3. Create AT Protocol record via createRecord()
  4. On success: Remove from LocalStorage
  5. 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:

  1. Catch error when writing
  2. Show user-friendly message: "Storage full. Please complete or delete in-progress reviews."
  3. Highlight oldest in-progress reviews
  4. Offer bulk delete option

AT Protocol Network Errors#

Error: Network failure, timeout, server error

Handling:

  1. Keep data in LocalStorage
  2. Show error message: "Failed to save review. Saved locally. Retry?"
  3. Offer manual retry button
  4. Auto-retry on connection restore

AT Protocol Session Expiry#

Error: 401 Unauthorized

Handling:

  1. Keep data in LocalStorage
  2. Show message: "Session expired. Please log in again."
  3. Redirect to login
  4. 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: