mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-02 04:43:58 +00:00
Anthony: "this needs a cookie crumb navbar, all pages need this with the new IA" and "broad and drill down, I'm not seeing that in the sidebar". lib/crumbs.ts derives the trail from the path and the spec registry, so no page declares it: /openthreat is Home > Specs > Catalogs a site serves about itself > OpenThreat, /opencpu adds OpenServer before OpenCPU, /docs/openthreat ends in Specification, /docs/cli is Home > Docs > CLI, a blog post passes its title as the leaf. components/breadcrumbs.tsx renders it (server-rendered, with a BreadcrumbList JSON-LD) at the top of every SiteShell page; the SPA routes rendered by page-markup.ts get the same trail as a string. components/side-nav.tsx replaces the flat sidebar: the four groups stay, and under Specs the family the current page belongs to unfolds to its specs, and the spec to its blocks, marked active. The home page string marks the active entry for the SPA routes too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { renderInstallCommand } from "@/lib/install-command";
|
|
import { Breadcrumbs } from "@/components/breadcrumbs";
|
|
import { SideNav } from "@/components/side-nav";
|
|
|
|
/**
|
|
* The site chrome for every standalone route: the sidebar that unfolds to
|
|
* where you are (components/side-nav.tsx), and the breadcrumb trail at the
|
|
* top of the page (components/breadcrumbs.tsx), both derived from the spec
|
|
* registry and the path. `crumbTitle` names the last crumb when the
|
|
* registry cannot, such as a blog post's title. `active` is kept for
|
|
* callers that still pass it and is no longer needed.
|
|
*/
|
|
export function SiteShell({
|
|
children,
|
|
crumbTitle,
|
|
}: {
|
|
children: ReactNode;
|
|
active?: string;
|
|
crumbTitle?: string;
|
|
}): ReactNode {
|
|
return (
|
|
<main className="shell">
|
|
<aside className="rail">
|
|
<a className="brand" href="/" style={{ textDecoration: "none", color: "inherit" }}>
|
|
<span className="mark">LS</span>
|
|
<div>
|
|
<strong>LogicSRC</strong>
|
|
<small>Open coordination standards</small>
|
|
</div>
|
|
</a>
|
|
{/* Same markup the homepage uses, so the two can never drift apart.
|
|
Static content from a module constant -- nothing user-supplied. */}
|
|
<div dangerouslySetInnerHTML={{ __html: renderInstallCommand("rail") }} />
|
|
<SideNav />
|
|
</aside>
|
|
<section className="workspace">
|
|
<Breadcrumbs leaf={crumbTitle} />
|
|
{children}
|
|
<footer
|
|
style={{
|
|
maxWidth: "72rem",
|
|
margin: "2rem auto 0",
|
|
padding: "1.25rem 0",
|
|
borderTop: "1px solid #d9ded4",
|
|
display: "flex",
|
|
flexWrap: "wrap",
|
|
gap: "0.75rem",
|
|
justifyContent: "space-between",
|
|
fontSize: "0.85rem",
|
|
color: "#5b6b7a",
|
|
}}
|
|
>
|
|
<span>© {new Date().getFullYear()} Profullstack, Inc. · LogicSRC</span>
|
|
<span style={{ display: "flex", gap: "0.75rem" }}>
|
|
<a href="/specs" style={{ color: "inherit" }}>Specs</a>
|
|
<a href="/docs" style={{ color: "inherit" }}>Docs</a>
|
|
<a href="/blog/rss.xml" style={{ color: "inherit" }}>RSS</a>
|
|
<a href="/llms.txt" style={{ color: "inherit" }}>llms.txt</a>
|
|
<a href="/terms" style={{ color: "inherit" }}>Terms</a>
|
|
<a href="/privacy" style={{ color: "inherit" }}>Privacy</a>
|
|
</span>
|
|
</footer>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|