feat(docs): standalone docs site chrome + category/subcategory navigation

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.
This commit is contained in:
John O'Keefe committed 2026-10-24 14:31:36 -04:00
1 parent 9d0ae2bcc4
commit 84cd6328f4
19 files changed
+2030 -1097

No files matched your search

+20 -1
View File
@@ -209,8 +209,20 @@ type Navigation struct {
Sections []NavSection
}
// NavSection is a top-level documentation category. Items are documents that
// live directly in the section; Groups are subcategories (subdirectories).
type NavSection struct {
Title string
Icon string
Items []NavItem
Groups []NavGroup
Collapsed bool
}
// NavGroup is a subcategory inside a NavSection (a subdirectory of docs).
type NavGroup struct {
Title string
Icon string
Items []NavItem
Collapsed bool
}
@@ -218,7 +230,14 @@ type NavSection struct {
type NavItem struct {
Title string
URL string
Icon string
}
// SearchResultItem is one entry in the docs search results partial. The
// server renders it (templ); the client only swaps the markup in.
type SearchResultItem struct {
Title string
Category string
URL string
}
type Document struct {