Data model
On disk
DATA_DIR is the git working tree. Items are real files; the SQLite DB and
.env live outside it so they're never committed.
DATA_DIR/
items/
<folder>/<slug>-<id>.<ext> # one file per item
assets/<token>.<ext> # pasted images
.gitignore
scratchpad.db # SQLite index — OUTSIDE DATA_DIR
.env # secrets — OUTSIDE DATA_DIR
Extensions encode the type: code uses its language extension (.go, .py, …),
drawings .excalidraw, mindmaps .mind, docs .doc (HTML), boards .kanban
(JSON). The <id> keeps filenames unique.
SQLite tables
All rebuildable from disk except shares (and the generated session secret
in settings).
items( id, title, type, path, language, folder, created_at, updated_at )
shares( token, item_id, expires_at, created_at ) -- expires_at = 0 means never
links( from_id, to_title ) -- [[wiki-link]] graph
settings( key, value ) -- session secret, etc.
Reconcile
On boot (after a git pull), Scratchpad walks DATA_DIR/items, upserts each file
into items, rebuilds the links index, and prunes rows whose file is gone. So
the index always reflects what's on disk — including changes pulled from another
machine.