-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Local-First Data Layer & Offline Support
Goal
Make the forum usable even when the Waku network is unavailable by caching data in the browser (IndexedDB) and automatically syncing when connectivity is restored.
Motivation
Today, all forum content is fetched live from Waku and kept only in memory (messageCache).
If the user reloads while offline – or loads the site before peers are discovered – the UI is empty.
Making the app local-first will:
- Deliver instant page loads from local data.
- Let users browse / write posts & comments offline.
- Reduce network load & perceived latency even when online.
High-Level Design
| Layer | Responsibility |
|---|---|
| IndexedDB (via Dexie) | Persistent store for all message types (cells, posts, comments, votes, moderations). |
MessageManager (src/lib/waku/index.ts) |
– Persist every received message to IndexedDB. – Maintain an outbox collection of locally-created messages with isPublished = false. |
| Sync Engine | – On startup: hydrate messageCache from IndexedDB before touching the network.– While offline: queue outgoing messages → outbox. – When MessageManager.isReady === true: replay outbox, mark isPublished = true, then delete. |
UI (ForumContext, pages) |
– Renders immediately from hydrated cache. – Shows a small “Offline” banner when isNetworkConnected is false.– Shows a “⟳ syncing n items…” indicator while flushing the outbox. |
Implementation Plan
-
Set up Dexie wrapper (
src/lib/storage/db.ts)```ts export const db = new Dexie("opchan"); db.version(1).stores({ cells: "id, timestamp", posts: "id, cellId, timestamp", comments: "id, postId, timestamp", votes: "&[targetId+author], timestamp", moderations: "targetId, timestamp", outbox: "id, type, timestamp" // unsent msgs }); ``` -
Hydrate on bootstrap
InForumContext, beforeinitializeNetwork()call:
1. Load all tables intomessageManager.messageCache.
2.updateStateFromCache()so the UI renders instantly. -
Persist incoming messages
ExtendMessageManager.updateCache()toawait db.<table>.put(message). -
Offline detection
The existingmessageManager.onHealthChange()already emits readiness; surface this in UI (banner). -
Outbox queue
1.sendMessage()detects offline →db.outbox.put({...msg, isPublished:false}).
2. When health flips to online, iterateoutbox, push viaephemeralProtocolsManager.sendMessage(), thendb.outbox.delete(id). -
Conflict handling (simple)
If Waku later returns a message with the sameid, just overwrite local copy – messages are immutable. -
Unit tests for the storage layer (Dexie mock) & sync logic.
-
E2E smoke test:
1. Load site → disconnect network → create post.
2. Reload (still offline) → post is visible.
3. Reconnect network → post is published and visible on a second device.
Acceptance Criteria
- App loads fully offline using previously cached data.
- Users can create posts/comments while offline; they appear with a “pending” style.
- Pending items are automatically published within 10 s of regaining connectivity.
- No data loss after browser refreshes (validated across Chrome/Firefox).
- Lighthouse “Offline” audit passes.
- No TypeScript errors or ESLint warnings.
References & Inspiration
- Local-First Software
- Dexie.js – IndexedDB wrapper
- PouchDB + Couch Sync model (conceptual sync idea)
Related Code Pointers
src/lib/waku/index.ts– TODO at top about IndexedDB storage.src/contexts/ForumContext.tsx– initial loading flow &updateStateFromCache.src/contexts/forum/network.ts– health monitoring utilities.