No description
Find a file
agent 8295894b32 Show add-page indicator as a bar and palm-check its taps
The add-page ghost is now a thin bar along the active page's free edge
instead of a full page-sized block. Pointer taps on it go through the
stage gesture handling, so touches are evaluated by the palm rejector
with the same 'draw' policy as writing, including being cut off if the
pen shows up mid-tap. The native click only handles keyboard activation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 17:54:29 +00:00
.claude Init 2026-09-26 19:13:02 +02:00
docker Fix imported PDFs not rendering in the Docker image 2026-09-27 09:37:15 +00:00
memos/memos Init 2026-09-26 19:13:02 +02:00
scripts Init 2026-09-26 19:13:02 +02:00
src Show add-page indicator as a bar and palm-check its taps 2026-09-27 17:54:29 +00:00
static Init 2026-09-26 19:13:02 +02:00
.dockerignore Add Dockerfile and compose setup for self-hosting 2026-09-26 22:33:08 +00:00
.gitignore Init 2026-09-26 19:13:02 +02:00
compose.yaml Add Dockerfile and compose setup for self-hosting 2026-09-26 22:33:08 +00:00
Dockerfile Add Dockerfile and compose setup for self-hosting 2026-09-26 22:33:08 +00:00
package-lock.json Init 2026-09-26 19:13:02 +02:00
package.json Init 2026-09-26 19:13:02 +02:00
palm-rejection-test.html Init 2026-09-26 19:13:02 +02:00
README.md Add Dockerfile and compose setup for self-hosting 2026-09-26 22:33:08 +00:00
spec.md Init 2026-09-26 19:13:02 +02:00
svelte.config.js Init 2026-09-26 19:13:02 +02:00
tsconfig.json Init 2026-09-26 19:13:02 +02:00
vite.config.ts Init 2026-09-26 19:13:02 +02:00

Papure

Lecture notes as a tree of pages ("comb") — live-preview markdown underneath, vector ink on top — stored as one dual-layer PDF per canvas and synced through a GitHub repo. See spec.md for the design.

Run

npm install
npm run dev        # http://localhost:5173
npm test           # unit tests (tree, markdown, PDF round trip, sync against a fake GitHub)
npm run check      # type-check
npm run build      # static PWA in build/ — serve it from any static host (HTTPS for PWA install)

Docker

docker compose up -d --build    # http://localhost:8080 (set PAPURE_PORT to change)

The image builds the PWA and serves it with nginx. Put an HTTPS reverse proxy in front of it: installing the PWA and the offline service worker both need HTTPS. To update, git pull and run the same command again.

Using it

  • Tools (bottom bar): Text T, Pen P, Highlighter H, Eraser E, Import PDF, Undo/Redo, zoom. The pen's eraser end erases too.
  • Pages: the grey "+" tiles next to the active page add a page there; Alt+Arrow moves to (or creates) the neighbour. Right-click a page or use its ⋯ button to insert, resize or delete it.
  • Importing a PDF into a non-empty canvas shows every free spot; click one to place the chain. Into a blank canvas it simply replaces the empty page. The Files panel can also import a PDF as a new canvas.
  • View: wheel/trackpad pans, Ctrl+wheel or pinch zooms, Ctrl+0 fits the page, Ctrl+9 shows the whole tree, space-drag or middle-drag pans.
  • Sync: Settings → Sync. Use a fine-grained token with Contents: read & write on the repo. Edits autosave locally; pushes happen every N minutes and on Ctrl+S / the sync button. Conflicts: newer wins.

Layout

  • src/lib/model — page tree (pure functions: insert/remove/flatten/layout).
  • src/lib/editor — markdown analysis shared by the CodeMirror live preview and the PDF text layout.
  • src/lib/pdf — PDF writer (vector text, Ink annotations, embedded source-of-truth files) and reader.
  • src/lib/ink — stroke recording/outlines and palm rejection (ported from palm-rejection-test.html).
  • src/lib/storage, src/lib/sync — IndexedDB vault and GitHub sync.

Fonts in static/fonts are pre-subset (scripts/subset-fonts.sh) because pdf-lib's own subsetter drops glyphs.