logicsrc/apps/logicsrc-web/src/app/docs/page.tsx
Anthony Ettinger 8756853e68 Site IA: broad sidebar, four spec families, one registry
Anthony: "that site needs better information architecture, it's impossible
to find anything", "start broad in sidebar and drill down with dedicated
pages, not all one page", and "I see none of our specs" on the home page.

One registry, lib/specs.ts, now lists every specification in four
families (people and agents; access and credentials; catalogs a site
serves about itself; agents and process), with a landing path, a
specification path and, for OpenServer's blocks, a parent. Everything
that lists specs reads it: the sidebar (lib/nav.ts, four groups: Start,
Specs, Tools, Company, rendered by SiteShell and by the home page string
from the same array), /specs and /specs/<family>, the home page's
Standards Surface grid (families with their specs, replacing the five
abstract primitives), /docs (grouped by family, then guides), the sitemap
and llms.txt. DOC_SLUGS is derived from the registry. Adding a spec is
one entry plus its files; the four hand-kept lists are gone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ
2026-09-13 03:35:05 +00:00

88 lines
3.5 KiB
TypeScript

import Link from "next/link";
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { listDocs } from "@/lib/docs";
import { FAMILIES, GUIDES, familyTree } from "@/lib/specs";
import { SiteShell } from "@/components/site-shell";
export const metadata: Metadata = {
title: "Docs · LogicSRC",
description:
"The specification text of every LogicSRC spec, grouped by family, and the guides: data model, CLI and TUI conventions, config, permissions, plugins.",
alternates: { canonical: "/docs" },
};
const row: React.CSSProperties = { padding: "0.9rem 0", borderTop: "1px solid #e3e6e0" };
const h3: React.CSSProperties = { margin: "0 0 0.3rem", fontSize: "1.1rem", color: "#101418" };
const p: React.CSSProperties = { color: "#41505d", margin: 0 };
export default function DocsIndex(): ReactNode {
const docs = new Map(listDocs().map((d) => [d.slug, d]));
const docFor = (path?: string) => (path ? docs.get(path.replace(/^\/docs\//, "")) : undefined);
return (
<SiteShell active="Docs">
<div className="band">
<div className="section-head">
<h2>Docs</h2>
<p>
The specification text, one page per spec, grouped the way{" "}
<Link href="/specs">the specs</Link> are. Source lives in the{" "}
<a href="https://github.com/profullstack/logicsrc" rel="noreferrer">
profullstack/logicsrc
</a>{" "}
repository under <code>docs/</code>.
</p>
</div>
{FAMILIES.map((family) => (
<section key={family.slug} style={{ marginTop: "2rem" }}>
<h3 style={{ ...h3, fontSize: "1.3rem" }}>
<Link href={`/specs/${family.slug}`} style={{ color: "inherit", textDecoration: "none" }}>
{family.name}
</Link>
</h3>
<p style={p}>{family.line}.</p>
<ul style={{ listStyle: "none", margin: "0.75rem 0 0", padding: 0 }}>
{familyTree(family).flatMap(({ spec, children }) => [spec, ...children]).map((spec) => {
const doc = docFor(spec.doc);
if (!doc) return null;
return (
<li key={spec.slug} style={{ ...row, paddingLeft: spec.parent ? "1.25rem" : 0 }}>
<h3 style={h3}>
<Link href={spec.doc as string} style={{ color: "inherit", textDecoration: "none" }}>
{doc.title}
</Link>
</h3>
<p style={p}>{spec.line}.</p>
</li>
);
})}
</ul>
</section>
))}
<section style={{ marginTop: "2rem" }}>
<h3 style={{ ...h3, fontSize: "1.3rem" }}>Guides</h3>
<p style={p}>Conventions the reference implementations follow.</p>
<ul style={{ listStyle: "none", margin: "0.75rem 0 0", padding: 0 }}>
{GUIDES.map((g) => {
const doc = docs.get(g.slug);
if (!doc) return null;
return (
<li key={g.slug} style={row}>
<h3 style={h3}>
<Link href={`/docs/${g.slug}`} style={{ color: "inherit", textDecoration: "none" }}>
{doc.title}
</Link>
</h3>
{doc.excerpt ? <p style={p}>{doc.excerpt}</p> : null}
</li>
);
})}
</ul>
</section>
</div>
</SiteShell>
);
}