benjivers/notes Public Public: anyone can read this; nobody can change it.

Shared folders: a repo folder you write in together, kept in git #3

Merged opened this

shipped production is serving it deploy 9965609

opened this

A shared folder is a folder of a forge repository (e.g. docs/ of ben/brainstorm) that you and whoever you invite write in together, with the full vault experience: links, backlinks, tags, search, graph, daily notes. Everything else stays private: shared notes never appear in anyone's own vault, and members never see yours.

How it works

  • Connect (app admins only, since commits use your token): sidebar → Vaults → Share a repo folder → owner/repo, branch, folder.
  • Invite with a join link (forge or email accounts). You can turn the link off, make a new one, or remove people; members can leave.
  • Folder tree in the sidebar mirrors the repo. A note titled ideas/Pricing goes in ideas/, and the File panel moves notes between folders. Front matter renders as properties, and its tags count as tags.
  • Git sync (src/sync.ts): edits commit about 4s after typing stops, at most 20s later (one commit per burst, naming who wrote). Renames and moves move the file, and removing a note removes its file. Pushes to the repo show up within a minute, or immediately with Sync now. A note edited in both places keeps ours and saves theirs beside it as <title> (repo copy). Change detection compares git blob ids.
  • Two people, one note: saves carry base, so a stale save gets a 409 and the editor asks Load theirs or Keep mine.

Design

  • Space notes are ordinary notes with author_id = space:<id>, so every existing vault query isolates them without changes. The contract gains a member role (held by the row's member_id, derived from membership); author sits above it.
  • New tables: space, space_member, space_gone. New note columns: path, synced_path, synced_oid.
  • Needs NOTES_REPO_TOKEN (an rw forge token). Without it the feature stays off.

Verified

  • 70 tests pass: privacy, join/leave/link-off, paths, the 409 conflict, and a full sync round trip against an in-memory repo (pull, commit, rename, delete, external push, edit-in-both-places). Deliberately breaking the membership check, or the conflict-copy rule, makes the tests fail.
  • Drove it in headless Chrome as two users: connect, join by link, edit, then a live conflict prompt where Keep mine saves correctly. Commits came out as expected.

🤖 Generated with Claude Code

merged this
Sign in to join this conversation.

↑↓ navigate ↵ open esc close

Keyboard shortcuts