Universal knowledge capture tool for the r* ecosystem
  • JavaScript 70.9%
  • TypeScript 18.5%
  • CSS 9.2%
  • HTML 1.1%
  • Shell 0.3%
Find a file
Jeff Emmett b4cf5f3286 feat(ui): durable editor /crdt sync + voice extract-concepts + documents UI [rnotes JMJMJ follow-up]
- NoteEditor binds its Yjs doc to the durable holon /crdt log (attachDurableSync:
  pull history on mount, debounced merged push) so collab state survives a yws
  relay restart and is cross-session/offline.
- Voice page: 'Concepts' action runs the transcript through /api/notes/extract-concepts
  → point-form concept notes (JMJMJ aggregation ladder, atom rung).
- Documents UI: /documents (list + create from selected notes) and /documents/[id]
  (ordered members + compose paragraph→article→book via the forge). Nav link added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 18:59:10 +02:00
.gitea/workflows ci: orphan-resilient up (clear renamed orphans + retry on conflict) 2026-05-29 18:31:37 +02:00
backlog chore(backlog): commit completed TASK-17 (hero title + feature shortcuts) 2026-05-30 12:42:17 +02:00
browser-extension feat(extension): add versioned zip build script + install/versioning docs (TASK-MEDIUM.7) 2026-05-29 03:03:35 -07:00
prisma feat(identity): fold DID into the canonical Identity holon via the SDK binding [TASK-11] 2026-06-02 01:15:20 +02:00
public feat: add /voice PWA route with 3-tier live transcription 2026-02-24 17:43:04 -08:00
scripts feat(identity): fold DID into the canonical Identity holon via the SDK binding [TASK-11] 2026-06-02 01:15:20 +02:00
src feat(ui): durable editor /crdt sync + voice extract-concepts + documents UI [rnotes JMJMJ follow-up] 2026-06-03 18:59:10 +02:00
.dockerignore Add .dockerignore for optimized Docker builds 2026-02-21 17:59:43 -07:00
.env.example refactor: migrate EncryptID URLs from encryptid.jeffemmett.com to auth.ridentity.online 2026-02-24 22:20:09 -08:00
.gitignore feat(extension): add versioned zip build script + install/versioning docs (TASK-MEDIUM.7) 2026-05-29 03:03:35 -07:00
docker-compose.yml chore: enable ENCRYPTID_DEMO_SPACES=demo (demo-visitor account for showcase + testing the aggregation routes) 2026-06-03 14:24:37 +02:00
Dockerfile Merge dev into main: add rVoice PWA + browser extension voice recorder 2026-02-24 17:47:31 -08:00
entrypoint.sh feat: wire rnotes to pull secrets from Infisical at startup 2026-02-23 19:35:15 -08:00
MODULE_SPEC.md docs: add README + document gateway-routed API (TASK-MEDIUM.6) 2026-05-28 05:37:03 -07:00
next.config.mjs fix: skip TypeScript errors during Next.js build 2026-03-31 17:53:06 -07:00
package-lock.json feat(extension): Diigo web clipper feature parity for rNotes 2026-05-28 00:59:32 +02:00
package.json feat(extension): Diigo web clipper feature parity for rNotes 2026-05-28 00:59:32 +02:00
postcss.config.mjs Initial scaffold: Next.js 14 + Prisma + Docker 2026-02-13 12:53:52 -07:00
README.md feat(extension): add versioned zip build script + install/versioning docs (TASK-MEDIUM.7) 2026-05-29 03:03:35 -07:00
tailwind.config.ts Initial scaffold: Next.js 14 + Prisma + Docker 2026-02-13 12:53:52 -07:00
tsconfig.json Merge dev: add rApp/Space switcher dropdowns to all headers 2026-02-24 18:31:30 -08:00

rNotes — Collaborative Notebooks

Rich note-taking with notebooks, tags, file uploads, voice transcription, web clipping, in-page annotations, screenshot + PDF annotation, and canvas integration. Part of the rSpace substrate.

Connecting to the rNotes API

rNotes is served behind the rSpace API gateway (see doc-005). The canonical base for every external client is:

https://rspace.online/api/rnotes/<rest>

The gateway strips /api/rnotes from the URL and forwards the remainder verbatim to the rnotes-online backend. Authorization headers (EncryptID DID JWT) pass through unchanged.

# Authenticated GET
curl -H "Authorization: Bearer <jwt>" \
  https://rspace.online/api/rnotes/api/notes

# Create a clip
curl -X POST \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{"title":"Hello","content":"<p>world</p>","type":"CLIP","url":"https://example.com"}' \
  https://rspace.online/api/rnotes/api/notes

# Tag suggestions for a URL (public-ish, requires auth)
curl -H "Authorization: Bearer <jwt>" \
  "https://rspace.online/api/rnotes/api/tags/suggest?url=https://example.com"

Every gateway response includes x-rspace-gateway: rnotes for observability.

Why not rnotes.online/api/* directly?

The bare rnotes.online host 301-redirects all paths to rspace.online/rnotes/* for unified UX (per rspace-online standalone-domain handling, commit b32d7528 from 2026-02-27). Calling rnotes.online/api/notes directly will redirect but lose the POST body, so route through the gateway instead.

Browser extension

The browser-extension/ directory contains the rNotes Web Clipper & Voice extension.

Install (non-developers)

  1. Download the latest rnotes-clipper-v<version>.zip from https://rnotes.online/extension.zip.
  2. Unzip it to a folder you'll keep (Chrome loads the extension from this path — don't delete it).
  3. Open chrome://extensions, toggle Developer mode on (top-right).
  4. Click Load unpacked and select the unzipped folder.

This is option (a) — load-unpacked still requires Developer mode. A Chrome Web Store listing (auto-update, no warnings) is tracked as TASK-MEDIUM.7 option (c), to follow after the Diigo-parity field test (TASK-HIGH.2).

Build the distributable zip

cd browser-extension && ./build-zip.sh
# → dist/rnotes-clipper-v<version>.zip   (version read from manifest.json)

The script uses the zip CLI when present and falls back to python3 otherwise. The dist/ output is gitignored — upload the produced zip to the rnotes.online/extension.zip host on release.

Versioning policy

The extension follows semver, sourced from browser-extension/manifest.json (1.3.0 today). Bump manifest.json before running build-zip.sh so the archive filename and the installed version match:

  • patch (1.3.0 → 1.3.1) — bug fixes, no new permissions or UI surfaces
  • minor (1.3.0 → 1.4.0) — new clip/annotate features, additive only
  • major (1.x → 2.0.0) — manifest permission changes or breaking API-base / auth changes

Quick install (developers)

Load directly from the repo: chrome://extensions → Developer mode → Load unpacked → select browser-extension/.

Features (Diigo-parity, v1.3.0):

  • Save Bookmark / Clip Page / Clip Selection / Save Image
  • Read & Annotate — in-page highlights + sticky notes anchored via W3C Web Annotation text-quote selector; marks reappear on revisit
  • Annotate Screenshot — captureVisibleTab → in-extension canvas with rect/arrow/text/freehand/crop tools → upload as IMAGE note
  • Annotate PDF — full PDF.js viewer with built-in Highlight/FreeText/Ink editor; saved with embedded annotations
  • Outliner sidebar — nested lists of notes/links/comments, opened as a right-edge iframe on any page
  • Voice notes — Ctrl+Shift+V opens the rNotes recorder (Whisper transcription)
  • Unlock Article — paywall bypass via archive.today
  • Save dialog with description, Private/Read Later/Cache flags, "Remember preferences" toggle, tag suggestions, shared-notebook hint, "Add to outliner" dropdown

The extension defaults to the gateway base above. Override in the options page's "API base" field for local-dev (http://localhost:3000 for direct backend hits).

Local development

# Install deps
npm install

# Generate Prisma client
npx prisma generate

# Run migrations against your local DB
DATABASE_URL=postgresql://rnotes:rnotes@localhost:5432/rnotes \
  npx prisma migrate deploy

# Dev server
DATABASE_URL=postgresql://rnotes:rnotes@localhost:5432/rnotes npm run dev

For local extension testing, set the extension's "API base" to http://localhost:3000 (the rnotes-online backend mounts /api/* directly — no gateway prefix when hitting the container directly).

Deployment

Production runs on Netcup behind Traefik + Cloudflared. The deploy flow per CLAUDE.md:

  1. Work on dev branch, push to gitea
  2. Fast-forward main from dev, push
  3. ssh netcup "cd /opt/apps/rnotes-online && git pull origin main && docker compose up -d --build"

Auto-mirrors to GitHub (gitea push hook).

Backlog

Tasks live in backlog/tasks/ and are managed by Backlog.md. Browse the live aggregator at https://backlog.jeffemmett.com.

License

MIT.