vite.config.ts stamps the package version, git commit and build time
into the bundle as __BUILD__, and the Settings sidebar shows
"v0.1.0 · <short sha>" (full sha and build time on hover). The Docker
build has no git binary, so the commit is read from .git/HEAD and the
refs directly; .dockerignore now lets just those files through.
GIT_COMMIT in the environment overrides detection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GaoZtJQZwLXkEgWs8twCia
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>
Each grid cell is now the active page's size, aligned to its edges, so
the grid marks where neighbouring pages would sit. Falls back to A4 at
the origin when no page is active.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pages now get a crisp 1 screen-px outline instead of a blurred shadow,
and the canvas background shows faint world-anchored grid lines that
pan and zoom with the pages (spacing steps up ×4 when zoomed out).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hashed assets are served as immutable for a year. Before the nginx MIME
fix, the pdf.js worker was served as application/octet-stream, and the
browser kept that response. Each new service worker then copied it from
the HTTP cache into its offline cache, so PDFs still failed to render
after the server was fixed. Fetching with cache: 'reload' always takes
the current response from the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsorPV3JeJRoZ1mD1pdvtL
Neighbouring pages now touch, so the tree reads like a grid. Rows with
pages of different sizes are still centred, so it isn't a strict grid.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsorPV3JeJRoZ1mD1pdvtL
nginx has no MIME type for .mjs, so the pdf.js worker was served as
application/octet-stream and browsers refused to load it. Every imported
PDF page then showed "Source PDF ... is not available", which looked like
missing files. Serve .mjs as text/javascript.
The page background now also tells the two failures apart: "not stored on
this device" when the source bytes are missing, and "could not display"
(with the error logged) when pdf.js fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsorPV3JeJRoZ1mD1pdvtL
After writing with the pen, fingers could no longer navigate:
- every touch was ignored for 5 s after any pen activity (and for as long
as a hover-capable pen stayed near the screen),
- after that, a one-finger drag on a page drew ink instead of panning,
- a one-finger drag on the background did nothing while an ink tool was on.
Once a pen has been used, fingers now only pan and zoom. The 5 s session
and hover lockouts only block finger ink; touches are still rejected while
the pen is down, for palm-sized contacts and within 150 ms of pen activity.
A finger drag off the page always pans.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsorPV3JeJRoZ1mD1pdvtL
Blank pages added next to an existing page (via the "+" tile, Alt+Arrow
or the page menu) now copy that page's width and height, including
imported PDF pages, instead of always falling back to A4. The "+" preview
tile uses the same size so it matches the page it will create.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsorPV3JeJRoZ1mD1pdvtL