The docs catch up with the shelves the audits built

Eric asked whether the shelf work was documented — the guide and Help
described the launch version, not the three audit rounds and design
passes since. Both now cover the physical wall rendering, the
suggestion doctrine (♥ reunification, remaining-room honesty, tightest
fit, honest empties), descriptions at both furniture levels,
row-clamped reordering, grid continuation on existing units, chained
containment, and the fill-bar epistemics. The tour gains a Shelves
entry with a screenshot of the drawn Kallax, and four documents stop
claiming the app has seven pages — Shelves made it eight.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
Eric Wagoner
2026-08-09 14:34:48 -04:00
co-authored by Claude Fable 5
parent 7ac80d1526
commit d6ff5e73e9
7 changed files with 47 additions and 20 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ Full design lives in `docs/spec.md` (read it before changing pipeline semantics)
## Commands
- `uv sync` — install deps (Python 3.12+, managed by **uv**; use `uv add`, never pip). `uv run bggpipe init` handles first-run setup (folders, .env credentials, the one-time `playwright install chromium`).
- `uv run bggpipe web` — the app: seven pages (Pipeline `/`, Photos, Titles, Review, Queue, Library, Help) in a shared sidebar shell (responsive: hamburger nav + stacked tables under 900px); stage runs execute one-at-a-time in a background job. `--lan` binds 0.0.0.0 behind a per-device access key: persisted in `data/.lan_key` (gitignored), printed as a QR at startup, cookie-paired for a year, required on EVERY network request (loopback clients and `/static/*` are exempt; the Host/Origin guard still applies). Phone camera uploads (generic `image.jpg` names) get minted `shelf-<timestamp>` names — only explicitly-named files trigger the replace-to-reshoot flow.
- `uv run bggpipe web` — the app: eight pages (Pipeline `/`, Photos, Titles, Review, Queue, Library, Shelves, Help) in a shared sidebar shell (responsive: hamburger nav + stacked tables under 900px); stage runs execute one-at-a-time in a background job. `--lan` binds 0.0.0.0 behind a per-device access key: persisted in `data/.lan_key` (gitignored), printed as a QR at startup, cookie-paired for a year, required on EVERY network request (loopback clients and `/static/*` are exempt; the Host/Origin guard still applies). Phone camera uploads (generic `image.jpg` names) get minted `shelf-<timestamp>` names — only explicitly-named files trigger the replace-to-reshoot flow.
- `uv run bggpipe <stage>` — run a pipeline stage. Non-secret settings come from `config.toml` (dirs, rate limit, `vision_provider` + per-provider `[vision.*]` blocks — "anthropic" or any OpenAI-compatible endpoint incl. local Ollama); `--config` overrides the path.
- `uv run pytest` — the suite runs fully offline against fixtures. Tests marked `live` hit the real BGG API (read-only) and are skipped unless you pass `--run-live`.
- `uv run ruff check` / `uv run ruff format` — lint (rules E, F, I, UP, B, SIM) and format.
+1 -1
View File
@@ -33,7 +33,7 @@ Everything runs locally, every stage survives being killed mid-run, and all arti
![Pipeline dashboard: six stage cards with live counts and Run buttons, showing a completed pipeline — 136 titles extracted, 115 resolved, 62 games added, 136 in the library](docs/screenshots/01.png)
**➔ [See the full tour](docs/tour.md)** — all seven pages, the game-detail view, and the phone experience.
**➔ [See the full tour](docs/tour.md)** — all eight pages, the game-detail view, and the phone experience.
## Requirements
+2 -1
View File
@@ -115,7 +115,8 @@
"height_in": 13.25,
"depth_in": 15.4
}
]
],
"description": "Centerpiece of the game wall in the library"
}
]
}
+37 -15
View File
@@ -40,7 +40,7 @@ Non-secret knobs live in `config.toml`: `photos_dir`, `data_dir`, the BGG rate l
bggpipe web # opens http://127.0.0.1:8377/ — the whole app in the browser
```
Seven pages — Pipeline, Photos, Titles, Review, Queue, Library, and Help — all [pictured in the tour](tour.md). Stage runs execute one at a time in the background with live output:
Eight pages — Pipeline, Photos, Titles, Review, Queue, Library, Shelves, and Help — all [pictured in the tour](tour.md). Stage runs execute one at a time in the background with live output:
![The Pipeline page mid-extract: stage cards above a live activity log listing each photo and how many titles it yielded](screenshots/15-extract-live.png)
@@ -111,26 +111,48 @@ BGG application approval can take a week or more. Until then: `extract` works im
## Where everything lives
The **Shelves** page maps your physical storage: create units from presets
(IKEA Kallax cube 13.25″ × 13.25″ × 15.4″, Billy shelf, custom sizes) as
grids of rows × columns, add one-off openings (double-wides, a top shelf),
and no-size virtual spots ("travel case", "lent out"). Openings carry free-
text zones, are editable and reorderable, and everything lands in
`data/furniture.json` + `data/locations.json` — committed local stores;
The **Shelves** page maps your physical storage and draws it as it really
stands: openings group into rows by their label letters, and each cell's
width is proportional to its interior width, so a Kallax with a double-wide
top row renders as exactly that — a diagram of the wall, not a list. Create
units from presets (IKEA Kallax cube 13.25″ × 13.25″ × 15.4″, Billy shelf,
custom, or a no-size virtual spot like "travel case") as grids of rows ×
columns; add more sections to an existing unit the same way — a later grid
continues the row letters, so 3 × 4 under an A row lands as B1…D4. Openings
are editable (dimensions are all-or-none: three numbers or a no-limit
spot), reorderable within their row (moves clamp at row boundaries so the
diagram can't fragment), and deletable. Both units and openings take a
free-text **description** alongside the **zone** keyword — the label is
the address, the zone matches, the description explains. Everything lands
in `data/furniture.json` + `data/locations.json` — committed local stores;
your shelf layout is never sent anywhere.
Assign games by tapping an unshelved game's suggested openings (only
openings it actually fits, with room to spare), by searching inside an
opening, or from a game's detail page (openings grouped by unit, each
labeled fits / doesn't fit / can't verify). Games stored inside another
box inherit their container's spot. On a phone over `--lan`, the opening
view docks as a bottom sheet — the moving-day loop is search, tap, done.
Assigning games: every measured unshelved game shows up to three suggested
openings, ranked by a strict relevance doctrine. An opening already holding
a **series-mate or base game ranks first** (marked ♥) — kinship is the
pre-colon name stem plus BGG's series field, no taxonomy to maintain, so
every placement you confirm teaches the suggester your organization and
expansions chase their base games automatically. "Fits" always means the
**remaining** opening — stack budget already spent is subtracted — and
after that, tightest verified fit, so small boxes are offered cubes and
never the oversize row. A measured game with nowhere suitable says
"no matching openings yet"; an unmeasured game gets no suggestions at all,
because can't-verify is not the same as fits. You can also assign by
searching inside an opening, or from a game's detail page (openings
grouped by unit, each labeled fits / doesn't fit / can't verify). Games
stored inside another box inherit their container's spot — through whole
chains (minis in an insert in a big box live where the big box does). On a
phone over `--lan`, the opening view docks as a bottom sheet — the
moving-day loop is search, tap, done.
Bulk-load a reviewed plan with `bggpipe shelve --import plan.csv` (columns
`name,opening`, accepting opening ids or labels) — rejects are reported
(unknown name, ambiguous copies, unknown opening, doesn't fit, lives
inside another box), never guessed. `bggpipe dims` reports per-opening
capacity, overfull warnings, and misfits against your real furniture.
inside another box), never guessed, and re-imports preserve hand-entered
notes. `bggpipe dims` reports per-opening capacity, overfull warnings, and
misfits against your real furniture. Fill bars measure stacked thickness
against interior height (boxes lying flat); unmeasured boxes are counted
and shown, never silently assumed to fit.
## Shelf-space planning
Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

+5 -1
View File
@@ -1,6 +1,6 @@
# A tour of bggpipe
Seven pages in one local app — Pipeline, Photos, Titles, Review, Queue, Library, and Help. Every screenshot below is the real app on the author's real shelves, and the end product is public: [the author's BGG collection](https://boardgamegeek.com/collection/user/ewagoner) is what this pipeline built. (Back to the [README](../README.md) · how to use it all: the [user's guide](guide.md).)
Eight pages in one local app — Pipeline, Photos, Titles, Review, Queue, Library, Shelves, and Help. Every screenshot below is the real app on the author's real shelves, and the end product is public: [the author's BGG collection](https://boardgamegeek.com/collection/user/ewagoner) is what this pipeline built. (Back to the [README](../README.md) · how to use it all: the [user's guide](guide.md).)
**The Pipeline page** — every stage is a card with live counts and a Run button; blockers (missing token, stub-data lock) surface as banners, not surprises. Here: the settled state after a full run — 136 titles read, 115 matched, 62 added.
@@ -34,6 +34,10 @@ Seven pages in one local app — Pipeline, Photos, Titles, Review, Queue, Librar
![Game detail page for Britannia: box art beside player counts, playing time, weight, rank, designers and mechanics as chips, with a Your Edition card naming the owned printing](screenshots/10-game-detail.png)
**Shelves** — your furniture drawn as it stands: units render their physical arrangement (a double-wide top row spans the top), with fill bars, zones, and a suggestion engine that learns your organization from every placement you confirm.
![Shelves page: the add-a-unit form with presets above a Library Kallax unit drawn as its real arrangement — two double-wide openings spanning the top, three rows of four cubes beneath, each with zone label and fill bar](screenshots/17-shelves.png)
**Help** — the whole flow, every page, every status, and every keyboard shortcut, documented in-app.
![Help page documenting the shelves-to-collection flow, what each page is for, and the proofreading and review checkpoints](screenshots/07.png)
+1 -1
View File
@@ -30,7 +30,7 @@
<p><b><a href="/titles">Titles</a></b> — every read off your shelves, alphabetized, with its status and photos. This is the proofread checkpoint: <a href="#curation">edit, split, remove</a>. Its badge counts <span class="chip shaky">shaky read</span> lines — the model wasn't sure and nothing has verified them; filter to them, then press <b>✓ looks right</b> or edit each one.</p>
<p><b><a href="/review">Review</a></b> — the decisions only you can make: which game a title is, which edition a copy is, whether two same-game reads are really one box (merges show a veto), and whether an unmatched title is a real game BGG simply doesn't have (<b>keep locally</b>: it joins the Library, never uploads). Keyboard-first; see <a href="#keys">shortcuts</a>.</p>
<p><b><a href="/queue">Queue</a></b> — exactly what upload will do (new entries and version upgrades) and the log of everything it has done. Nothing reaches BGG that isn't visible here first. A job that fails is skipped by later runs (so one broken game can't loop forever); when any exist, the Pipeline's upload card offers a <b>retry N failed</b> checkbox. Each queued row shows what upload did with it — <span class="chip open">pending</span>, <span class="chip ok">done</span>, <span class="chip no">failed</span>, or <span class="chip no">retired</span> (a review decision since the last diff withdrew it). Finished rows stay listed until the next <b>diff</b> rebuilds the queue; the log below them is the permanent record.</p>
<p><b><a href="/shelves">Shelves</a></b> — where everything physically lives. Describe your furniture once (presets for Kallax cubes and Billy shelves, grids of rows × columns, custom sizes, and no-size spots like a travel case), then assign games to openings — by tapping suggestions next to unshelved games, by searching inside an opening, or from any game's detail page. Fill bars show stacked thickness against interior height; ⚠ flags overfull openings and boxes that can't fit. Games stored inside another box ride along with their container. Your layout is local data only — never sent anywhere. Bulk-load a plan with <code>bggpipe shelve --import plan.csv</code> (name,opening) and check capacity anytime with <code>bggpipe dims</code>.</p>
<p><b><a href="/shelves">Shelves</a></b> — where everything physically lives, drawn as it really stands: openings group into rows by label letter with widths proportional to their interiors, so the page is a diagram of your wall. Describe furniture once (presets for Kallax cubes and Billy shelves, grids of rows × columns — a later grid continues the row letters — custom sizes, and no-size spots like a travel case); units and openings both take a free-text description beside the zone keyword. Suggestions rank an opening holding a <b>series-mate or base game first</b> (marked ♥ — every placement you confirm teaches the suggester your organization), always against the <i>remaining</i> room, then tightest verified fit; a measured game with nowhere suitable says "no matching openings yet", and unmeasured games get no suggestions because can't-verify ≠ fits. Assign by tapping suggestions, searching inside an opening, or from any game's detail page. Fill bars show stacked thickness against interior height; ⚠ flags overfull openings and boxes that can't fit; games stored inside another box ride along with their container, through whole chains. Your layout is local data only — never sent anywhere. Bulk-load a plan with <code>bggpipe shelve --import plan.csv</code> (name,opening) and check capacity anytime with <code>bggpipe dims</code>.</p>
<p><b><a href="/library">Library</a></b> — your enriched collection. Search titles, designers, mechanics and categories at once; filter by kind (board games, RPGs, off-BGG) or by how many people are playing tonight; sort by name, year, BGG rank, weight, or playing time. Click any game for its full detail: art, the usual stats, designers and mechanics, <b>your</b> edition, the shelf photos it was read from, and a link to its BGG page. RPG and off-BGG games live here too — identified and enriched, never uploaded. RPGs pull their designers, publishers and genres from RPGGeek; an off-BGG game's detail page lets you write its facts yourself and add a cover photo, since nothing else will ever have them (both are saved under <code>data/</code> and folded in by the next <b>enrich</b>).</p>
</div>