cmd/librenotes/web/public/sync.js drives the offline-online
reconciliation flow against the notes REST API:
- start(): registers online/offline window listeners, runs an
initial syncOnce() if currently online.
- syncOnce(): push() then pull(); emits "librenotes:sync-state"
events with state in {online, offline, syncing, synced, error}.
- push(): walks notesCache.pending() (rows with dirty=1, including
tombstones). PUTs use ?base=<synced_at> for optimistic locking
and DELETEs use the same. The notes API returns 409 with the
current server body on conflict; sync.js stashes the pair in
conflictsById and dispatches "librenotes:sync-conflict" so the
app shell can render a resolution dialog.
- pull(): GETs the summary list, refetches any row whose server
updated_at exceeds the local synced_at (or that is missing
locally), and stamps it as cleanly synced. Skips locally-dirty
rows so push's conflict path stays authoritative.
- resolveConflict(id, "local"|"remote"|"merge", merged): replays
the user's choice. "local" and "merge" PUT with the latest
server base so the second attempt accepts; "remote" overwrites
the local cache with the server copy.
app.html now includes a sync-state badge in the header and a
<dialog> for conflict resolution wired to the events. app.js
calls notesSync.start() on load and routes dialog clicks back to
resolveConflict. The dialog uses native <dialog>.showModal(),
which all current target browsers support.
style.css adds badge colour states (syncing/synced/offline/error)
and a two-column conflict layout that collapses on narrow widths.
Closes #23.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
librenotes
Cloud-native, multi-tenant notes application. A fork of Notesium extended with authentication, per-user data isolation, sync, and PWA support so it can run as a hosted service at librenot.es.
Features
- Markdown notes with bi-directional links (Zettelkasten / evergreen notes)
- Embedded web app — no Electron, no Node runtime, single static binary
- Multi-tenant backend with magic-link authentication (in development)
- Offline-capable PWA with background sync (planned, Phase 4)
Build
Requires Go 1.20 or later.
go build ./cmd/librenotes
This produces a librenotes binary in the current directory. The web
frontend and shell completion are embedded into the binary at compile
time, so no extra files are needed at runtime.
A Makefile with build, test, run, and clean targets is provided
for convenience:
make build
make test
Run
./librenotes web --notes-dir ~/notes
See ./librenotes help for the full command list.
Development setup
A Nix flake provides a reproducible development environment with Go,
build tools, and the project CLIs. Use the plain dev shell for a
non-sandboxed Go toolchain:
nix develop .#dev
Alternatively, build a Docker-based dev environment:
docker build -f Dockerfile.dev -t librenotes-dev .
docker run --rm -it -v "$PWD:/workspace" librenotes-dev
The repository layout follows the standard Go project structure:
cmd/librenotes/ Binary entry point
internal/notesium/ Core notes package (forked from Notesium)
internal/notesium/web/ Embedded frontend assets
The Go module path is git.librete.ch/public/librenotes.
Fork attribution
librenotes is a fork of Notesium by Alon Swartz, used and redistributed under the MIT License. See NOTICE for the upstream commit hash at fork time and instructions for tracking upstream changes.
License
MIT — see LICENSE. Copyright is shared between the original Notesium author and the librenotes contributors.