package templates import "fmt" // DocsLayout renders the standalone documentation site: a docs-owned topbar // (search, theme picker, Open App), a docs-only sidebar with category → // subcategory navigation, and the markdown content. // // It deliberately does NOT embed the app Header: docs are a public surface // (setup and troubleshooting happen pre-login), and the app chrome assumed a // signed-in user — it rendered a sign-in form that silently degraded into a // native GET submit (credentials into the URL) because this page never loaded // htmx. Signed-out visitors get a plain "Sign in" LINK here; the form lives // on /login where it belongs. templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) { @ThemeFlashGuard() { doc.Title } - Bookhoard Documentation @DocsTopbar(user)
@DocsSidebar(nav, currentPath)
if len(doc.Breadcrumb) > 0 { }

{ doc.Title }

if len(doc.TOC) > 0 {
On this page @Icon("chevron-down", "h-4 w-4 ml-auto")
for _, item := range doc.TOC { { item.Title } }
}
@UnsafeHTML(doc.Content).ToComponent()
} // DocsTopbar is the docs site's own slim header. It never contains a login // form — anonymous visitors get a link to /login (the only place credentials // are posted from). templ DocsTopbar(user User) {
@Icon("book-open", "h-6 w-6") Docs
@DocsSearchBox() @DocsThemePicker()
} // DocsSearchBox hosts the header search input. Results are a server-rendered // partial (GET /docs/search/partial) swapped into #docs-search-results by // web/src/docs.ts — the server renders what results look like. templ DocsSearchBox() {
@Icon("search", "h-4 w-4")
} // DocsThemePicker reuses the app's theme Alpine component: initializeTheme // applies the saved (and, when signed in, server) theme and syncs the select; // changeTheme persists the choice. Anchors in the content smooth-scroll via // the same init. templ DocsThemePicker() {
} // DocsSidebar renders the category → subcategory navigation. Sections and // groups toggle collapsed/expanded client-side (pure open/closed state); // the server decides what is expanded on first paint via data-collapsed. templ DocsSidebar(nav Navigation, currentPath string) { } // DocsSearchResults renders the search results partial swapped into the // header dropdown. Server-rendered on purpose (rendering ownership): the // client never builds result markup from JSON. templ DocsSearchResults(results []SearchResultItem) { if len(results) == 0 {
No matching pages.
} else { } } // DocsNotFound renders the standalone docs 404 page: same theme tokens, no // app chrome, no CDN dependencies. templ DocsNotFound(title string, message string) { @ThemeFlashGuard() { title } - Bookhoard Documentation
@Icon("book-open", "h-10 w-10")

{ title }

{ message }

}