* docs: rename to lowercase + drop leftover plans Rename docs in docs/ to lowercase kebab-case for consistency and update all references in CLAUDE.md, CONTRIBUTING.md, CHANGELOG.md, packages/server/CLAUDE.md, and inter-doc links. Drop two leftover design plan docs: - docs/ATTACHMENT_BASED_REVIEW_CONTEXT_PLAN.md - docs/plan-approval-normalization.md * docs: drop stale uppercase entries from case-insensitive rename * feat(website): power /docs from public-docs/ markdown tree Move website docs out of TSX route components and into a root-level public-docs/ directory of plain markdown files with frontmatter (title, description, nav, order). - Add packages/website/src/docs.ts loader using import.meta.glob with ?raw to compile the markdown into the bundle at build time. - Replace the 9 hand-written docs/*.tsx routes with a single $.tsx catch-all that renders any slug via react-markdown. - Drive the docs sidebar nav from frontmatter order/nav. - Auto-discover docs routes in vite.config.ts so the sitemap stays in sync without manual edits. * fix(website): bind dev server to 0.0.0.0 so port collisions trigger fallback `host: "127.0.0.1"` (or unset) lets macOS coexist with another process holding an IPv6 dual-stack `*:8082` socket, so Vite never sees EADDRINUSE and silently binds alongside it. Forcing IPv4 wildcard makes the conflict real, and Vite's default `strictPort: false` falls through to the next free port. * fix(website): restore docs page styling after markdown migration Add a .docs-prose class that mirrors the styling the original docs/*.tsx components hand-rolled (h1/h2/h3 sizes, paragraph/list spacing, link colors, code blocks, callout-style blockquotes). ReactMarkdown was emitting unstyled HTML because the previous wrapper class only had inline-code rules — headings and code blocks fell back to user-agent defaults.
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import { createFileRoute, Link, Outlet } from "@tanstack/react-router";
|
|
import { getDocs } from "~/docs";
|
|
import "~/styles.css";
|
|
|
|
export const Route = createFileRoute("/docs")({
|
|
component: DocsLayout,
|
|
});
|
|
|
|
const ACTIVE_OPTIONS_EXACT = { exact: true };
|
|
const MOBILE_ACTIVE_PROPS = { className: "text-foreground" };
|
|
const DESKTOP_ACTIVE_PROPS = { className: "bg-muted text-foreground" };
|
|
|
|
function DocsLayout() {
|
|
const navigation = getDocs().map((doc) => ({
|
|
name: doc.frontmatter.nav,
|
|
href: doc.href,
|
|
}));
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
{/* Mobile header */}
|
|
<header className="md:hidden border-b border-border p-4">
|
|
<Link to="/" className="flex items-center gap-3">
|
|
<img src="/logo.svg" alt="Paseo" className="w-6 h-6" />
|
|
<span className="text-lg font-medium">Paseo</span>
|
|
</Link>
|
|
<nav className="flex gap-4 mt-4 flex-wrap">
|
|
{navigation.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
to={item.href}
|
|
activeOptions={ACTIVE_OPTIONS_EXACT}
|
|
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
activeProps={MOBILE_ACTIVE_PROPS}
|
|
>
|
|
{item.name}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</header>
|
|
|
|
<div className="max-w-5xl mx-auto flex">
|
|
{/* Desktop sidebar */}
|
|
<aside className="hidden md:block w-56 shrink-0 border-r border-border p-6 sticky top-0 h-screen">
|
|
<Link to="/" className="flex items-center gap-3 mb-8">
|
|
<img src="/logo.svg" alt="Paseo" className="w-6 h-6" />
|
|
<span className="text-lg font-medium">Paseo</span>
|
|
</Link>
|
|
<nav className="space-y-1">
|
|
{navigation.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
to={item.href}
|
|
activeOptions={ACTIVE_OPTIONS_EXACT}
|
|
className="block px-3 py-2 text-sm rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
|
|
activeProps={DESKTOP_ACTIVE_PROPS}
|
|
>
|
|
{item.name}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</aside>
|
|
<main className="flex-1 p-6 md:p-12 max-w-3xl docs-prose">
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|