ThreadCount Community edition

Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
ThreadCount
2026-09-13 08:45:19 +10:00
commit 1bc2de655a
505 changed files with 56223 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
import { SiteFooter } from "@/components/site";
import Analytics from "@/components/Analytics";
import JsonLd from "@/components/JsonLd";
import { graph, organization, website } from "@/lib/schema";
// Route group: no URL segment. Wraps every public marketing page in the same shell so the nav and
// footer are defined once. The nav itself is rendered per page so it can mark the active link.
// These pages are prerendered. Two things in them move on their own: the footer's copyright year,
// and — once, on the day plans go live — the price on every page that states one (lib/plans-live.ts).
// A minute keeps the pages served from the prerender for every reader while letting the console's
// plans switch reach the site without a deploy.
export const revalidate = 60;
export default function SiteLayout({ children }: { children: React.ReactNode }) {
return (
<div style={{ fontFamily: "var(--font-body)", color: "var(--color-text)", background: "var(--color-bg)", minHeight: "100vh", display: "flex", flexDirection: "column" }}>
{/* The link has to be the first focusable thing on the page, so it lives here rather than in
SiteNav. Its target is the page heading — PageHead carries id="content" — because each
page renders its own nav inside `children` to mark the active link, so a target on this
wrapper would land above the nav and skip nothing. */}
<a className="skip-link" href="#content">Skip to content</a>
<main style={{ flex: 1 }}>{children}</main>
<SiteFooter />
<Analytics site="marketing" />
{/* Who this is and what site it is. Stated once, on the shell every public page uses. */}
<JsonLd data={graph(organization, website)} />
</div>
);
}