Right now this application is "server first", meaning that the server holds the single source of truth and data is updated via HTTP requests.
This works fine, but will not be ideal for offline support going forwards. If I wanted to support offline usage I would probably have to implement some sort of rudimentary sync system which would store a log of changes locally, then calculate the difference when online and push these changes. This would have a number of problems including conflict issues if multiple clients make offline changes then attempt to push these changes later.
There's also the general question of data ownership too, especially for a notes app where offline use and owning your
data is of paticualr importance.
Solution
I should look at changing this application around, so it works primarily as as a local first, offline first web app (using service worker etc?) which saves and reads data to a local store (such as IndexDB, in-browser sqlite etc?).
Data could then be synced via a CRDT system such as automerge with changes being communicated via a technology like websockets rather than a REST API.
I could then still use a server as always online data sync client/backup and a central way to communicate between different clients.
Links to more info:
Automerge - Likely the JS library I'd use for managing data sync
CRDTs - General info about CRDTs (Conflict-Free Distrubuted Data Types)
Local First - An article about local first application architecture
Actual is an open source budgeting app, built in a local-first way using CRDT (GitHub)
Logux a websocket framework with CRDT like behaviour, intergrates with Redux
Implementation Ideas
Use same React app
Redux provides application state management
Redux application state maps to an automerge document, changes to redux state can be mapped to automerge changes and sent via websocket to server.
Server can still use REST to initially authenticate users - and maybe first time data sync/dumps? - but websockets can then handle the CRDT based change sync.
Potentially all clients should sync via the server. So a client makes a change, then sends this change to the server. The server then merges that change with it's own copy of the data, then broadcasts that change out as it's own change to all clients connected on the websocket.
In the React app, local first support could be implemented with either some sort of Redux persistence library or more likely through a mixture of browser storage (IndexDB for content, localStorage for user details & keys still)
To potentially improve performace, I think character level changes in note content (body, title, description etc) should not always count as syncable changes, but be batched together. So if a user makes changes to a notes body, maybe a change would be registered every x minutes or if they close/navigate away from the content. If the user changes the title, that is a single change etc etc.
Each user vault is a single automerge document, content (such as notes, tags etc) are split using automerge tables.
Redux stores one document/application state at a time but local persistent storage can store multiple vaults & maybe even multiple users?
The sync system will then only act against for the currently active user & vault, even if there are locally persisted changes previously made in other vaults or by other users
Logux looks like a good option, but I fear relying on it might cause library lock in and it would mean that I'm not learning and practising an in depth use of websockets, CRDTs etc
Problem
Right now this application is "server first", meaning that the server holds the single source of truth and data is updated via HTTP requests. This works fine, but will not be ideal for offline support going forwards. If I wanted to support offline usage I would probably have to implement some sort of rudimentary sync system which would store a log of changes locally, then calculate the difference when online and push these changes. This would have a number of problems including conflict issues if multiple clients make offline changes then attempt to push these changes later.
There's also the general question of data ownership too, especially for a notes app where offline use and owning your data is of paticualr importance.
Solution
I should look at changing this application around, so it works primarily as as a local first, offline first web app (using service worker etc?) which saves and reads data to a local store (such as IndexDB, in-browser sqlite etc?). Data could then be synced via a CRDT system such as automerge with changes being communicated via a technology like websockets rather than a REST API. I could then still use a server as always online data sync client/backup and a central way to communicate between different clients.
Links to more info:
Implementation Ideas