Offline Support & Sync
Relevant source files
The following files were used as context for generating this wiki page:
Hearth provides comprehensive offline support to ensure the application remains functional even when the server is unreachable. This system allows users to view previously-visited pages and queue writes (creates, updates, or deletes) locally. Once a network connection is restored, the application automatically synchronizes these queued operations with the server.
The system relies on a Service Worker (via @serwist/next) for read-only caching and IndexedDB (idb) for managing the write queue and staged files.
Sources: CLAUDE.md:121-125, src/components/OfflineSyncManager.tsx:75-79
Core Architecture
Hearth's offline architecture consists of three primary layers: the caching layer for read access, the queueing layer for local writes, and the sync manager for reconciliation with the server.
Caching and Persistence
The application caches previously-visited pages for read access. To prevent data loss, the application requests persistent storage from the browser. This prevents the browser from evicting the origin's IndexedDB storage under memory pressure, which would result in the loss of unsynced operations or staged files.
Sources: CLAUDE.md:121-125, src/components/OfflineSyncManager.tsx:71-79
The Offline Write Flow
When a user performs an action (such as creating a contract) while navigator.onLine is false, the application enqueues the operation instead of sending a network request.
The diagram shows how the application branches between immediate server actions and local queueing based on network status.
Sources: src/lib/offlineQueue.ts, src/components/OfflineSyncManager.tsx:82-87, e2e/specs/08-offline-pending-records.spec.ts:10-15
Offline Queue Management
The offline queue is managed within IndexedDB and tracks pending server actions and associated file uploads.
Operation Structure
Queued operations are stored as QueuedOperation objects. This allows the UI to pre-fill forms with unsynced data if a user attempts to edit a pending record.
| Property | Type | Description |
|---|---|---|
id | string | Unique ID for the queued operation. |
label | string | Human-readable description (e.g., "Add contract"). |
entity | string | The domain entity type (e.g., "contract"). |
operation | string | The type of mutation ("create", "update", "delete"). |
entityId | string | Optional ID of existing entity for updates/deletes. |
formValues | Record<string, any> | The serialized form data to be sent to the server. |
Sources: src/components/ContractForm.tsx:55-65, src/lib/offlineQueue.ts, e2e/specs/08-offline-pending-records.spec.ts:25-30
File Staging
Files uploaded while offline are stored in a dedicated pending-files object store. The OfflineSyncManager monitors the total size of these files and warns the user if they exceed PENDING_FILES_WARN_BYTES (a defined threshold to prevent device storage exhaustion).
Sources: src/components/OfflineSyncManager.tsx:13-17, src/components/OfflineSyncManager.tsx:94-104
Synchronization Process
The synchronization process reconciles local changes with the server state once connectivity is restored.
Sync Lifecycle
Synchronization is triggered automatically when the browser's online event fires or manually via the "Sync now" button in the OfflineSyncManager UI.
The sequence diagram illustrates the communication flow during a sync event.
Sources: src/components/OfflineSyncManager.tsx:28-66, src/lib/offlineSync.ts
Error Handling
The syncPendingOperations function tracks successes and failures. If a sync fails, the OfflineSyncManager transitions to an error state and notifies the user that the sync will retry upon reconnection. Pending operations can be discarded by the user before they sync, which removes the local entry without ever creating a server-side record.
Sources: src/components/OfflineSyncManager.tsx:50-60, e2e/specs/08-offline-pending-records.spec.ts:39-43
Components
OfflineSyncManager
A client-side component that provides visual feedback on the status of the offline queue. It displays:
- Count of pending changes.
- Count and total size of pending file uploads.
- Current sync state (
idle,syncing,done,error). - A "Sync now" action when the browser is back online.
Sources: src/components/OfflineSyncManager.tsx:11-25, src/components/OfflineSyncManager.tsx:114-155
Form Integration (makeOfflineAwareAction)
Forms (like ContractForm) use the makeOfflineAwareAction wrapper. This function intercepts form submissions when offline, serializes the FormData, and stores it in the offline-queue store. It also manages "pending sync" cards on list pages, allowing users to edit or discard unsynced items.
Sources: src/components/ContractForm.tsx:45-53, e2e/specs/08-offline-pending-records.spec.ts:21-25, src/lib/help/faq.ts:114-118
Summary
The Offline Support & Sync module ensures data integrity and continuity for Hearth users in unreliable network conditions. By utilizing Service Workers for reads and IndexedDB for a persistent write queue, Hearth allows for a "local-first" experience where changes are captured immediately and reconciled with the self-hosted server as soon as possible.