libretechandClaude Opus 4.7 274c7054d0 Add JWT session client and tenant-scoped storage
cmd/librenotes/web/public/auth-client.js exposes window.authClient
with the full session API used by the rest of the frontend:

Session storage (#14):
- saveSession / loadSession / clearSession / isAuthenticated
- Backed by sessionStorage, not localStorage: tokens are isolated
  per tab and cleared on tab close. localStorage would survive
  tab close on a shared device, which we want to avoid.
- loadSession returns null when expires_at has passed, so callers
  treat expired sessions as logged-out without a network round
  trip.

API wrapper (#14):
- apiFetch(url, init) attaches Authorization: Bearer <jwt> to
  every call. On 401 it clears the session and redirects to
  /login.html?next=<current-path> so the user returns where they
  started. Throws after the redirect so the caller's .then does
  not run with stale data.

Tenant-scoped localStorage (#15):
- tenantStore() returns a get/set/remove wrapper whose keys are
  prefixed "librenotes:{user_id}:". Two users on the same browser
  therefore have fully independent UI state. JSON serialisation
  with try/catch fallbacks for corrupted or quota-exceeded
  storage so a bad blob never crashes the app.
- clearTenantStore(userID) removes every key with that prefix.
  Called from clearSession() so logout wipes both the JWT and
  the user's preferences.

verify.html + verify.js complete the magic-link flow: read
?token=, POST /auth/verify, hand the response to saveSession(),
strip the token from the URL via history.replaceState. Errors
route the user back to /login.html.

app.html + app.js are a minimal authenticated landing demonstrating
the full stack end-to-end: apiFetch hits /api/whoami, tenantStore
persists a theme preference, logout clears both. The full notes
UI is left to a later phase — this is the seam.

Closes #14 and #15.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:25:07 +02:00
2026-04-28 21:58:59 +02:00
2026-04-28 21:58:59 +02:00
2026-04-28 21:58:59 +02:00

librenotes

CI

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.

S
Description
No description provided
Readme MIT
987 KiB
2026-04-29 01:30:06 +02:00
Languages
JavaScript 51.3%
Go 33.8%
HTML 8%
Shell 2.9%
CSS 2.4%
Other 1.6%