shell.tsx146 lines · main
1import Link from 'next/link';
2
3import { fetchIncidents } from '../lib/incidents';
4
5interface NavItem {
6 href: string;
7 label: string;
8}
9
10interface NavGroup {
11 label: string;
12 items: readonly NavItem[];
13}
14
15const GROUPS: readonly NavGroup[] = [
16 {
17 label: 'start',
18 items: [
19 { href: '/', label: 'overview' },
20 { href: '/quickstart', label: 'quickstart' },
21 { href: '/connect', label: 'connect' },
22 { href: '/cli', label: 'cli' },
23 { href: '/templates', label: 'templates' },
24 ],
25 },
26 {
27 label: 'build',
28 items: [
29 { href: '/doltgres', label: 'doltgres (engine)' },
30 { href: '/schema', label: 'schema dsl' },
31 { href: '/auth', label: 'auth' },
32 { href: '/storage', label: 'storage (s3)' },
33 { href: '/undo', label: 'undo + snapshots' },
34 { href: '/examples', label: 'examples' },
35 { href: '/functions', label: 'functions' },
36 { href: '/realtime', label: 'realtime' },
37 { href: '/sdks', label: 'client sdks' },
38 { href: '/api', label: 'http api' },
39 { href: '/api-keys', label: 'api keys' },
40 { href: '/ai', label: 'ai schema' },
41 ],
42 },
43 {
44 label: 'move + run',
45 items: [
46 { href: '/migration', label: 'migration' },
47 { href: '/self-host', label: 'self-host' },
48 { href: '/operator', label: 'operator' },
49 ],
50 },
51 {
52 label: 'meta',
53 items: [
54 { href: '/roadmap', label: 'roadmap' },
55 { href: '/changelog', label: 'changelog' },
56 { href: '/status', label: 'status' },
57 { href: '/support', label: 'support' },
58 ],
59 },
60];
61
62export async function DocsShell({ children }: { children: React.ReactNode }) {
63 // Surface ongoing incidents in the docs header so a visitor mid-outage
64 // sees the acknowledgement without having to navigate to /status. The
65 // fetch degrades to [] when the api is unreachable, so a broken api
66 // doesn't break docs page renders.
67 const ongoing = await fetchIncidents({ activeOnly: true, limit: 1 });
68 const active = ongoing[0] ?? null;
69
70 return (
71 <div className="min-h-dvh">
72 {active ? (
73 <Link
74 href="/status"
75 className="block border-b border-[var(--color-warning)] bg-[var(--color-warning)]/10 px-6 py-2 text-center font-mono text-xs text-[var(--color-warning)] hover:bg-[var(--color-warning)]/20"
76 >
77 <span className="font-semibold uppercase tracking-wider">
78 {active.severity}
79 </span>{' '}
80 · {active.summary}{' '}
81 <span className="text-[var(--color-text-subtle)]">→ status</span>
82 </Link>
83 ) : null}
84
85 <header className="border-b border-[var(--color-border-subtle)]">
86 <div className="mx-auto flex w-full max-w-6xl items-center justify-between px-6 py-4">
87 <Link href="/" className="font-mono text-sm">
88 briven <span className="text-[var(--color-text-subtle)]">· docs</span>
89 </Link>
90 <nav className="flex items-center gap-4 font-mono text-xs">
91 <Link
92 href="https://briven.tech"
93 className="text-[var(--color-text-muted)] hover:text-[var(--color-text)]"
94 >
95 dashboard
96 </Link>
97 <Link
98 href="https://codeberg.org/flndrn/briven"
99 className="inline-flex items-center opacity-80 transition-opacity hover:opacity-100"
100 aria-label="Codeberg"
101 >
102 <img src="/codeberg.svg" alt="Codeberg" className="h-5 w-auto" />
103 </Link>
104 </nav>
105 </div>
106 </header>
107
108 <div className="mx-auto grid w-full max-w-6xl grid-cols-[220px_1fr] gap-10 px-6 py-10">
109 <nav aria-label="docs sections" className="flex flex-col gap-5 font-mono text-sm">
110 {GROUPS.map((group) => (
111 <div key={group.label} className="flex flex-col gap-1">
112 <p className="px-3 pb-1 text-[10px] uppercase tracking-wide text-[var(--color-text-subtle)]">
113 {group.label}
114 </p>
115 {group.items.map((item) => (
116 <Link
117 key={item.href}
118 href={item.href}
119 className="rounded-md px-3 py-1.5 text-[var(--color-text-muted)] hover:bg-[var(--color-surface)] hover:text-[var(--color-text)]"
120 >
121 {item.label}
122 </Link>
123 ))}
124 </div>
125 ))}
126 </nav>
127
128 <main className="prose prose-invert max-w-none">{children}</main>
129 </div>
130
131 <footer className="border-t border-[var(--color-border-subtle)] py-6">
132 <p className="mx-auto max-w-6xl px-6 font-mono text-xs text-[var(--color-text-subtle)]">
133 briven · doltgres-first reactive backend · ©{' '}
134 {new Date().getFullYear()} flndrn Limited ·{' '}
135 <Link
136 href="https://codeberg.org/flndrn/briven"
137 className="underline underline-offset-2 hover:text-[var(--color-text-muted)]"
138 >
139 source
140 </Link>{' '}
141 · built with <span className="text-[#e8344a]">♥</span> in Flanders
142 </p>
143 </footer>
144 </div>
145 );
146}