Work

A Read-Only Reader for Notes and Code

Frontend
Tooling
Full-Stack

A read-only reader for a notes vault or a code repository — wikilinks, backlinks, search, and a faithful reimplementation of git's layered ignore semantics, pruning behaviour included.

Layered ignore rules decide what is published; innermost wins Ignore layers · innermost wins defaults built in .gitignore the vault's own .pkmignore can rescue files nested scoped to subtree Index, rebuilt on every change notes: full text searchable code: names and paths only navigable, not searchable The pruning rule, reproduced on purpose In git, "!dist/keep.ts" does nothing while dist/ is excluded — the walk never opens dist/ to find the exception. Reproducing that means reproducing a limitation, and that is the right call: a tool almost compatible with a familiar format is worse than one exactly compatible, because the gap only ever surfaces as surprise — in the mechanism that decides what becomes public.

A read-only web reader that serves a personal notes vault, or a code repository, as a navigable site: folder tree, full-text search, wikilinks and backlinks, tag index, diagrams and maths, and a syntax-highlighted code viewer with a symbol outline. I run it for my own notes.

Ignore rules turned out to be the whole job

Deciding what to publish means reimplementing git’s ignore semantics, and they are subtler than they look. Rules layer innermost-first: built-in defaults, then the vault’s .gitignore, then a reader-specific ignore file applied afterwards so it can rescue files git excludes, then nested files scoped to their own subtree.

The behaviour worth getting right is directory pruning. In git, an exception like !dist/keep.ts does nothing on its own while dist/ is excluded — the walk never opens dist/ to discover the exception. So reproducing git faithfully means reproducing a limitation, which felt wrong for about a day.

Then I decided it was not. A tool that is almost compatible with a familiar format is worse than one that is exactly compatible, because the gap only ever shows up as surprise: someone reasons from what git would do, gets something else, and the mechanism they got it wrong about is the one that decides what becomes public. I would rather ship the limitation.

What it will not do

Code file contents are never indexed. Only filenames and paths.

The index rebuilds from scratch on every filesystem change and on a timer, so holding every code file’s text in memory across rebuilds was the wrong shape. Notes are searchable in full; code is navigable but not searchable by content.

That is in the README along with the others: no extends chain following in tsconfig, no support for git’s global excludes file, package-style Python and Go imports that never resolve to links. It is the part of the README I would keep if I had to cut the rest.

Access is gated by signed-cookie middleware at the edge, with one bypass: a bearer token scoped to the refresh endpoint alone, so a git post-receive hook can trigger a rescan without holding a session.