Second page of the admin tree. Documents the four-card stats grid with
what each number actually counts (instance-wide totals; Books = every
media item including podcast episodes), the File Watcher card's data
source (/api/scanner/watch/status, armed by Auto-Scan) and its
zero-libraries meaning, Force Rescan All Libraries with its real
mechanics (one job per library, skip-on-active, backfill tool vs.
routine shallow refresh), and the Scanning panel's live progress +
Cancel all scans. Links only to pages that exist (scanning.md); the
Settings reference stays prose until that page lands.
The real-tree nav test's Administration assertion loosens further: guide
leads, everything else strictly follows usabilityOrder — durable across
the remaining page landings. Also fixes the amend this commit replaces:
its first version briefly carried a forward link to the unwritten
settings.md (caught by the link gate, now removed) — the gate worked;
the && chain around go test let the bad commit through, which is exactly
why this amend exists.
First page of the admin tree, written to the new admin tier (what the
click actually does). Documents every scan surface with its verified
semantics: Force Rescan All Libraries (dashboard, force, all libraries,
one job each with skip-on-active), the per-library Scan button (ALSO a
force scan — hx-vals force:true since the button's birth commit 706be09d,
which corrects the owner's stated 'other scan buttons are shallow'
belief; flagged to the owner), Scan this folder (shallow, single-folder
scope, archive pass skipped for partial scans, podcast roots refused),
Auto-Scan + Scan Interval (the watcher + poll + startup triggers, all
shallow, default 60s range 1-3600), Processing Issues retry (per-item
sequential, deliberately not a library scan), and book-level Rescan /
Reset to Scanned. Plus the standing rules: one scan per library
(coalescing), background jobs with the dashboard progress panel, and
the two-consecutive-scans archive rule.
Glossary gains Scan and Scan this folder (same-commit rule for controls
cited in prose). The real-tree nav test's Administration assertion now
pins shape (Admin Guide, Libraries prefix + usabilityOrder subsequence)
instead of an exact slice, so pages landing one at a time don't churn it.
Two structural changes, one owner-approved plan:
- Move the admin guides out of docs/user/ into their own docs/admin/
area — admin-guide.md becomes the Administration section landing page
(pinned first), and the 32-line admin-library-management.md stub
becomes admin/libraries.md, which the admin-docs build-out rebuilds
into the real Libraries page next. Retired URLs 301 via a new
docRedirects map in the docs HTTP handler (checked before .md
canonicalization so even .md spellings one-hop to the new clean URL);
the two inbound links (docs index, user-guide front door) updated.
- Sidebar direct items now sort by usabilityOrder — an explicit,
per-section display order — instead of alphabetically: User Guide
mirrors the 'Where to go' table on user-guide.md, Devices orders
Android → KOReader → Kobo (alphabetically Kobo used to sort ahead of
KOReader), and Administration pre-lists its planned pages so each
lands in place as the admin build writes it. Unlisted docs fall back
to alphabetical after the listed ones. Display-order only by
construction: the URL-driven expand/highlight machinery keys on
containsURL membership and never sees sort order — nav tests updated
to pin the new orders plus a real-tree test
(TestBuildNavigationUsabilityOrder) guarding all three sections.
The filter manual is the docs tree's first FOLDER-index page: it serves
at /docs/user/filters while its nav entry carries /index
(/docs/user/filters/index). The sidebar's two checks — group expansion
(containsURL) and active-link styling (docsNavClass) — compared URLs
EXACTLY, so the folder URL matched neither: no submenu expansion, no
highlight (2026-11-01 user report: "the left sidebar should open to
the submenu and highlight the page").
Fix is structural, not per-page: both checks normalize folder-index
URLs (a trailing /index is the same page as its directory), so EVERY
folder-index page — current and future — expands and highlights like
a file page. No per-page registration exists anywhere in the docs
system to redo: the sidebar derives from the docs tree, and this was
the one URL shape its equality rule missed.
Pins: navigation (section + group expand for the folder URL, group
present) and docsNavClass (folder URL highlights the Overview item,
normalization symmetric, file pages keep their highlight, no
cross-highlighting).
docTitleOverrides now pins the label with lowercase 'and' (the naive
titleCase fallback capitalized every word); only the sidebar label was
affected — the page h1 comes from the markdown heading and was already
correct. Test pin added to TestDocTitle.
Follows the developer/api → API Reference carve-out: placement-only, no
file paths or URLs change. placeDoc routes user/devices/* to a new
top-level "Devices" section (icon: device) and user/admin-* to a new
top-level "Administration" section (icon: shield); User Guide keeps its
direct guides with no groups. Sidebar order: Getting Started, User
Guide, Devices, Administration, API Reference, Developer, Operations,
Contributing.
Verified live: on kobo-setup the Devices section opens with the three
device guides; on admin-guide Administration opens with both admin
guides; on user/dashboard User Guide opens as before. Tests
(TestPlaceDoc, TestBuildNavigation) updated to pin the new placement.
Simplification per spec: the menu tracks state through the URL alone.
Land on /docs: fully closed, headers only (an explicit home rule now
overrides the contains-URL rule, since the root overview doc lives in
Getting Started and would otherwise auto-open it). Land on any doc page:
its containing section + group render open at first paint, current link
bold — no JS, no jump, arrows consistent. Navigate elsewhere: old
closes, new opens.
Deleted: docs_nav cookie const/parse, ApplyNavOverrides, cookie write +
collect/persist helpers in web/src/docs.ts, data-key attributes in the
sidebar templ, and the first-section-open fallback (docs home used to
force-open the first section — spec'd as closed).
toggleCollapsible remains for in-page peeking; purely ephemeral.
The [data-collapsed=true] CSS from the previous round stays — it is what
makes the server-rendered state actually hide sections at paint (the
original bug was that this CSS never existed).
Tests: TestBuildNavigationNothingCurrent now asserts zero sections open
on unmatched paths; TestBuildNavigation asserts Getting Started closed
on a device page (no site-wide pin). make test green; 146 vitests; live
verified: home 0 expanded, doc pages exactly 2 (section+group).
Docs pages no longer embed the app Header (whose hx-post login form silently
degraded to a native GET, leaking credentials into the URL — this page never
loaded htmx). New docs-owned topbar: search, theme picker, Open App; anonymous
visitors get a plain /login link. Optional-auth middleware (hand-rolled —
echojwt's ErrorHandler return ends the chain, producing empty 200s) populates
the user for signed-in visitors.
Navigation rebuilt from the docs directory tree: 6 sections, subcategory
groups, server-rendered expansion and active states. Search results are a
templ partial (/docs/search/partial); code highlighting is server-side chroma
(previously dead hljs CSS); prose is theme-aware via typography DEFAULT vars
(prose-invert painted unreadable text under light themes). /docs renders the
index directly; standalone 404 without the tailwind CDN.
Tests: navigation routing/expansion (internal/docs), render pins asserting no
login form/password field/app sidebar ever return on docs pages.
lint-rendering: exempt *.test.ts fixtures (jsdom DOM building); docs.ts
baseline 5 -> 1.