- TypeScript 84.7%
- JavaScript 10.9%
- CSS 2.1%
- Shell 1.7%
- PLpgSQL 0.3%
- Other 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Release note / release-note (pull_request) Successful in 17s
CI / build (pull_request) Successful in 5m33s
CI / e2e (pull_request) Successful in 13m12s
CI / promote (pull_request) Has been skipped
CI / build (push) Successful in 5m47s
CI / e2e (push) Successful in 12m58s
CI / promote (push) Successful in 32s
Task: NEC-322 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tqcdhmk4cWL36YWBmL8vgw |
||
| .forgejo | ||
| .vscode | ||
| brand | ||
| deploy | ||
| docs | ||
| eslint-rules | ||
| packages | ||
| release-notes | ||
| scripts | ||
| site | ||
| .dockerignore | ||
| .gitignore | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.mjs | ||
| LICENSE | ||
| lint-register.json | ||
| manifest.json | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| renovate.json | ||
| stylelint.config.mjs | ||
| tsconfig.base.json | ||
| vitest.shared.ts | ||
Nectenda
End-to-end encrypted real-time collaboration for Obsidian.
Nectenda gives you real-time multi-user collaboration — live cursors in notes, canvases and bases, live Kanban boards and Excalidraw drawings, offline editing, shared folders and attachments — on a server that cannot read your notes. Content is encrypted on your device before it is sent; the server stores ciphertext it has no key for, and even the document paths are HMACs rather than filenames.
The plugin's source is published and ships as readable, never-minified JavaScript, so that claim is one you can check rather than one you have to believe. See what the server can and cannot see.
The managed service is live at nectenda.com. Self-hosting is functional, since it is the same codebase that runs the hosted service, but it is not yet packaged and documented for licensed use; it will be, quickly, if there is demand, for teams whose policy requires that the metadata never leaves their network either.
Features
What it makes live, for everyone in a shared folder (the version each arrived in is on the roadmap):
- Notes — several people type in one note at once; each person's caret, selection and pointer carry their name, a caret scrolled out of view waits at the screen's edge, and edits merge character by character via Yjs
- Canvases — cards moved, resized, linked and typed in show as they happen, and changes to different cards merge instead of making a conflict copy
- Bases — changes to different filters, formulas and views merge; you see which row, cell or card each person is on; cards moved between lanes of the kanban view Obsidian 1.14 adds merge, and so do the lanes
- Properties — a note's properties merge property by property, and the Properties panel shows which one a collaborator is editing
- Kanban boards (the community Kanban plugin) — update live, keep a card you are editing safe while others change the board, and show who is on which card
- Excalidraw drawings (the community Excalidraw plugin) — merge shape by shape, with everyone's pointer and selection; when two people change one shape's text or style at once, the losing change is kept beside it, labelled with who made it. Images in a drawing are attachments, so they need a plan with attachment storage
- Offline — notes stay Markdown files on your disk; what you change offline merges when you reconnect
And around it:
- Folder sharing — share any vault folder, not the whole vault; creates, renames and deletes propagate to everyone in it
- Invitations and share links — invite someone by email from the folder itself, or send a link; they get the folder as soon as they join
- Jump to a collaborator — click someone in the note header to go to where they are
- Attachments — synced on paid plans, encrypted like everything else
- No silent loss — a version that cannot merge is kept as a conflict copy, and a
first sync over existing files backs them up to
.nectenda-backups/ - Sign-in — passkeys, an emailed code, or Google, Apple or Microsoft; your encryption passphrase is separate and never leaves your device
- On your phone too — the same shared folder on desktop and mobile Obsidian
Hosted Service
If you'd rather not manage a server, the hosted service is live. Install the plugin and sign in; signing in creates your own organisation on the free plan. Prices are at nectenda.com/pricing, and plans are bought inside Obsidian — an account cannot be created for you remotely, because your encryption keys are derived on your own device.
There has never been an early-access signup, and this paragraph promised one until 18 September 2026.
Network Use and Accounts
Nectenda is a client-server plugin. It will not work offline-only, and it requires an account. This section states exactly what leaves your machine, because there are two very different deployment modes.
An account is required. Nothing syncs until you sign in. On the hosted service you
sign in with a passkey, an emailed code, or Google, Apple or Microsoft, at
accounts.nectenda.com; your encryption passphrase is chosen afterwards and never
leaves your device. On a self-hosted server registration is invite-only: its admin
issues you a token, and credentials are stored on that server (bcrypt-hashed) while the
plugin holds only a session token.
The plugin talks to the servers you point it at, and to no third party. There is no
analytics and no tracking of what you do. Self-hosted server URLs are ones you enter
yourself; signing in to the hosted service uses accounts.nectenda.com, which is the
only address the plugin knows without being told.
Crash reports, when signed in to the hosted service and not turned off, go to an
error tracker we run ourselves — never a third party, and only once you have been shown
what a report contains. They carry the exception and its scrubbed message, stack frames
as line and column numbers and function names (each frame's file reduced to our
published file, Obsidian, or an unnamed frame), the plugin and Obsidian versions, the
platform, and the install id every request already carries; never note content, names,
paths, the vault name, tokens or keys. packages/plugin/src/error-report.ts builds the
payload from an allowlist, docs/security-model.md states the rule, and a self-hosted
vault sends none because the address comes from the server and a self-hosted one names
none. Off in one click: Settings → Nectenda → Advanced → Send crash reports.
Mode 1 — Managed hosting at nectenda.com
The server is operated by us, and it cannot read your notes. Content is encrypted on your device before it is sent; the server stores ciphertext it has no key for. Document paths are HMACs rather than filenames, so it does not learn your folder structure either. The keys that decrypt your notes never leave your device unencrypted.
What it does see: which accounts share which folders, update sizes and timings, device records, and the display name you give a shared folder. That list is exhaustive and explained in the security model, which is written to be checked against the plugin source rather than believed.
Mode 2 — Self-hosted (not yet packaged)
You run the server on your own infrastructure, as a licensed container image. Nothing reaches us at all — not the ciphertext, and not the metadata above. This is functional since it is the same codebase that runs our hosted service, but we have not yet packaged and documented it nicely for licensed usage. We will prioritise this and have it ready fairly quickly if demand for it is there.
Most people do not need this. On the managed service we already cannot read your content, so self-hosting is not what buys you privacy of your notes; it is what buys you privacy of the metadata, which matters when policy or jurisdiction demands it.
Both modes run the same encryption. Choosing managed hosting does not mean trusting us
with your notes — that is the entire point of the design, and the full account of its
limitations is in the security model and
docs/sync-limitations.md.
Quick Start (Docker)
docker run -d \
--name nectenda \
-p 1234:1234 \
-v nectenda-data:/app/data \
-e JWT_SECRET="your-secret-key-here" \
-e ADMIN_USERNAME="admin" \
-e ADMIN_PASSWORD="your-admin-password" \
nectenda/nectenda
See docs/self-hosting.md for detailed deployment instructions including reverse proxy setup. The image is not yet published for licensed use (Mode 2, above); this is how it runs once it is.
Plugin Installation
From Obsidian's community plugin directory, or Settings → Community plugins → Browse inside Obsidian. Then open Settings → Nectenda and sign in.
To run a build of your own instead:
- Build the plugin:
pnpm install && pnpm -r build - Copy
packages/plugin/main.js,packages/plugin/manifest.json, andpackages/plugin/styles.cssto your vault's.obsidian/plugins/nectenda/directory - Enable "Nectenda" in Obsidian Settings → Community Plugins
- Open Settings → Nectenda and sign in; a self-hosted server's address goes under Advanced
Development
Prerequisites
- Node.js 26 (
enginesinpackage.json) - pnpm 12.5.1 (
packageManagerinpackage.json)
The two move together, and CLAUDE.md lists every place they are pinned.
Setup
git clone <repo-url>
cd nectenda
pnpm install
Dev Server
# Set required env vars
export JWT_SECRET="dev-secret"
export ADMIN_USERNAME="admin"
export ADMIN_PASSWORD="admin"
export SQLITE_PATH="$(pwd)/data/docs.db"
mkdir -p data
# Start the server (with hot reload)
pnpm dev:server
Dev Plugin
# Build plugin and watch for changes
pnpm dev:plugin
The plugin builds to packages/plugin/main.js. Symlink or copy it to your test vault's plugin directory.
Project Structure
packages/
plugin/ — Obsidian plugin (CM6 extensions, sync, file operations); mirrored to the public repository
shared/ — Protocol types and crypto primitives shared by the plugin and the servers; mirrored too
server/ — WebSocket relay shard + REST API + SQLite, with the append-only update log
identity/ — The hosted sign-in service (accounts.nectenda.com) and the shard directory
ops-common/— Logging, rate limiting, readiness, shutdown: shared by the server and the identity service
e2e/ — End-to-end tests against real Obsidian, and the video pipeline
deploy/ — The hosted service's compose files, Caddyfiles and runbook
site/ — nectenda.com, a static build with no JavaScript
docs/ — Plans, the security model, sync limitations and positioning
Architecture
- Server: Custom Yjs WebSocket sync server (built on ws) with SQLite persistence
- Plugin: Obsidian plugin using CodeMirror 6 extensions for collaborative editing
- Sync: Yjs CRDTs for document content + Y.Map meta documents for file operations
- Auth: JWT tokens, bcrypt password hashing, invite-token registration
Environment Variables
The ones every deployment sets. The full list, with defaults and what each one does, is in docs/self-hosting.md; the server prints its effective configuration (secrets redacted) at boot.
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SECRET |
Yes | — | Secret for session tokens (openssl rand -hex 32). The server refuses to start without one. |
ADMIN_USERNAME |
No | — | Auto-create admin user on first run |
ADMIN_PASSWORD |
No | — | Password for auto-created admin |
PORT |
No | 1234 |
Server listen port |
HOST |
No | 0.0.0.0 |
Bind address; 127.0.0.1 behind a proxy |
SQLITE_PATH |
No | ./data/docs.db |
Path to SQLite database |
DATA_DIR |
No | ./data |
Attachments and backups |
TRUSTED_PROXIES |
No | — | Proxies whose X-Forwarded-For is believed |
LOG_LEVEL |
No | info |
Minimum log level: debug, info, warn, error |
FAQ
Why choose Nectenda over Obsidian Sync? Obsidian Sync ($4-5/month) is excellent for syncing your vault across devices, but it doesn't offer real-time collaborative editing with live cursors — it syncs files, not keystrokes. Nectenda is built specifically for real-time collaboration, and keeps the end-to-end encryption you would expect from Sync while adding it. That said, Obsidian Sync is well worth considering — paying for it directly supports the team behind Obsidian, the tool we all love and build on top of.
Why is the plugin's source published but the server's not? Because that is where the security actually lives. Every guarantee Nectenda makes is enforced on your device before anything is sent, so the plugin is the part worth reading — and it ships as the exact JavaScript that runs, unminified, on your own disk. No compiled binary, no reproducible-build argument to take on faith. The server relays ciphertext it has no key for; publishing it would prove little, since nobody can verify which build an operator is actually running. This is the same split Threema uses. What we owe you in return is the security model, written plainly enough to check against the plugin source.
To be precise about the word: the plugin is source-available, not open source. The licence lets you read it, audit it, modify it and use it for anything — including commercially — but not build a product that competes with Nectenda. Publishing it was always about letting you verify the encryption, and that is untouched.
Does it work offline? Yes. Nectenda uses CRDTs (Yjs) with local IndexedDB caching. You can keep editing while offline — changes merge automatically when you reconnect.
How many people can share a folder? As many as the organisation's plan has seats: 3 on Free, 6 on Personal, up to 10 on Team and up to 25 on Small Business, with every live-collaboration feature on every plan. Past that, get in touch. Prices are at nectenda.com/pricing.
Do I need technical skills to self-host? Basic familiarity with Docker is all you need once self-hosting is packaged as a licensed container image (Mode 2, above). See the self-hosting guide. Most people should not need it: on the managed service we cannot read your content either way. Self-hosting is for teams whose policy requires that the metadata — who shares what with whom, and when — stays on their own network too.
License
Licensed per package — see LICENSE.
- Plugin and shared library: PolyForm Shield 1.0.0. Source-available, not open source. Read it, audit it, build it yourself and compare the result to what you installed — all expressly permitted, and the reason it is published at all. Any purpose is permitted except building a product that competes with Nectenda. It holds your keys and does your encrypting, so it is the part you should be able to check.
- Server: proprietary. It stores ciphertext it cannot read. Self-hosting will be offered as a licensed container (Mode 2, above).