- JavaScript 70.9%
- TypeScript 18.5%
- CSS 9.2%
- HTML 1.1%
- Shell 0.3%
- 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> |
||
|---|---|---|
| .gitea/workflows | ||
| backlog | ||
| browser-extension | ||
| prisma | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| MODULE_SPEC.md | ||
| next.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
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.
- Live: https://rnotes.online (UI) / https://rspace.online/api/rnotes (API)
- Module spec: MODULE_SPEC.md
- Browser extension: browser-extension/ — Chrome / Edge / Firefox MV3
- Stack: Next.js 14 · React 18 · Prisma · PostgreSQL · TipTap · Bun (tests)
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)
- Download the latest
rnotes-clipper-v<version>.zipfrom https://rnotes.online/extension.zip. - Unzip it to a folder you'll keep (Chrome loads the extension from this path — don't delete it).
- Open
chrome://extensions, toggle Developer mode on (top-right). - 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:
- Work on
devbranch, push to gitea - Fast-forward
mainfromdev, push 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.