@rizom/site-rizom-ai 0.2.0-alpha.166 → 0.2.0-alpha.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/brain-screens.tsx +465 -0
- package/src/brain.tsx +418 -0
- package/src/home.tsx +50 -180
- package/src/layout.tsx +52 -18
- package/src/routes.ts +34 -4
- package/src/shared.tsx +58 -0
- package/src/site.ts +4 -2
package/src/brain.tsx
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/** @jsxImportSource preact */
|
|
2
|
+
import type { JSX } from "preact";
|
|
3
|
+
import type { SiteSectionGroup } from "@rizom/site";
|
|
4
|
+
import { defineSection, sectionGroup, z } from "@rizom/site-sections";
|
|
5
|
+
import { Section, renderHighlightedText } from "@rizom/site-rizom";
|
|
6
|
+
import {
|
|
7
|
+
Band,
|
|
8
|
+
CtaRow,
|
|
9
|
+
SectCap,
|
|
10
|
+
Trio,
|
|
11
|
+
trioSchema,
|
|
12
|
+
ctaSchema,
|
|
13
|
+
ROOM_HIGHLIGHT_CLS,
|
|
14
|
+
} from "./shared";
|
|
15
|
+
import {
|
|
16
|
+
BrainScreenStyles,
|
|
17
|
+
StudioScreen,
|
|
18
|
+
ChatScreen,
|
|
19
|
+
IntegrationsScreen,
|
|
20
|
+
DashboardScreen,
|
|
21
|
+
} from "./brain-screens";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The /brain room — the product's own page. The consolidated homepage grew
|
|
25
|
+
* two pages long because it told the umbrella story and the product story at
|
|
26
|
+
* once; the product story lives here, told as the brain's life with its owner
|
|
27
|
+
* in four chapters — capture, ask, see it run, connect — each illustrated by a
|
|
28
|
+
* real interface screen, then the data principles and the quickstart.
|
|
29
|
+
*
|
|
30
|
+
* The namespace ("brain") matches the route id, so each section stores as
|
|
31
|
+
* site-content/brain/<section>.md and resolves as "brain:<section>".
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/* ============ chapter heading ============ */
|
|
35
|
+
|
|
36
|
+
/* The shared chapter head: a numbered cap, a display headline with an accent
|
|
37
|
+
em, and a standfirst. Used by every chapter so the copy stays authored. */
|
|
38
|
+
function ChapterHead({
|
|
39
|
+
cap,
|
|
40
|
+
capNote,
|
|
41
|
+
headline,
|
|
42
|
+
intro,
|
|
43
|
+
}: {
|
|
44
|
+
cap: string;
|
|
45
|
+
capNote?: string | undefined;
|
|
46
|
+
headline: string;
|
|
47
|
+
intro: string;
|
|
48
|
+
}): JSX.Element {
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<SectCap lead={cap} trail={capNote} />
|
|
52
|
+
<h2 className="reveal reveal-delay-1 mt-3.5 max-w-[20em] font-display text-[clamp(28px,3vw,40px)] font-[465] leading-[1.1] tracking-[-0.014em] text-theme [font-variation-settings:'SOFT'_78,'opsz'_84]">
|
|
53
|
+
{renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
|
|
54
|
+
</h2>
|
|
55
|
+
<p className="reveal reveal-delay-2 mt-4 max-w-[62ch] font-body text-[17px] leading-[1.7] text-theme-muted">
|
|
56
|
+
{intro}
|
|
57
|
+
</p>
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* ============ hero ============ */
|
|
63
|
+
|
|
64
|
+
const heroSchema = z.object({
|
|
65
|
+
eyebrow: z.string(),
|
|
66
|
+
provenance: z.string(),
|
|
67
|
+
headline: z.string(),
|
|
68
|
+
standfirst: z.string(),
|
|
69
|
+
primaryCta: ctaSchema,
|
|
70
|
+
secondaryCta: ctaSchema,
|
|
71
|
+
chips: z.array(z.string()),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
function BrainHeroSection({
|
|
75
|
+
eyebrow,
|
|
76
|
+
provenance,
|
|
77
|
+
headline,
|
|
78
|
+
standfirst,
|
|
79
|
+
primaryCta,
|
|
80
|
+
secondaryCta,
|
|
81
|
+
chips,
|
|
82
|
+
}: z.infer<typeof heroSchema>): JSX.Element {
|
|
83
|
+
return (
|
|
84
|
+
<Section
|
|
85
|
+
id="brain-hero"
|
|
86
|
+
className="relative overflow-hidden pt-16 pb-8 md:pt-20"
|
|
87
|
+
>
|
|
88
|
+
<div
|
|
89
|
+
aria-hidden="true"
|
|
90
|
+
className="pointer-events-none absolute -inset-x-[10%] -inset-y-[30%] bg-[radial-gradient(680px_360px_at_14%_8%,rgb(from_var(--color-accent)_r_g_b_/_0.14),transparent_66%)]"
|
|
91
|
+
/>
|
|
92
|
+
<div className="relative">
|
|
93
|
+
<SectCap lead={eyebrow} trail={provenance} />
|
|
94
|
+
<h1 className="mt-[18px] max-w-[15.5em] font-display text-[clamp(36px,4.8vw,64px)] font-[448] leading-[1.04] tracking-[-0.02em] text-theme [font-variation-settings:'SOFT'_88,'opsz'_110]">
|
|
95
|
+
{renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
|
|
96
|
+
</h1>
|
|
97
|
+
<p className="mt-4 max-w-[52ch] font-body text-[20px] leading-[1.7] text-theme-muted">
|
|
98
|
+
{standfirst}
|
|
99
|
+
</p>
|
|
100
|
+
<CtaRow
|
|
101
|
+
primaryCta={primaryCta}
|
|
102
|
+
secondaryCta={secondaryCta}
|
|
103
|
+
className="mt-[26px]"
|
|
104
|
+
/>
|
|
105
|
+
<div className="mt-9 flex flex-wrap gap-2.5">
|
|
106
|
+
{chips.map((chip) => (
|
|
107
|
+
<span
|
|
108
|
+
key={chip}
|
|
109
|
+
className="rounded-full border border-theme px-[13px] py-1.5 font-label text-[10.5px] tracking-[0.06em] text-theme-light"
|
|
110
|
+
>
|
|
111
|
+
{chip}
|
|
112
|
+
</span>
|
|
113
|
+
))}
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</Section>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* ============ shared authored checklist ============ */
|
|
121
|
+
|
|
122
|
+
function Checks({ items }: { items: string[] }): JSX.Element {
|
|
123
|
+
return (
|
|
124
|
+
<ul className="mt-[18px] max-w-[40ch] font-body text-[15.5px] text-theme-light">
|
|
125
|
+
{items.map((item) => (
|
|
126
|
+
<li
|
|
127
|
+
key={item}
|
|
128
|
+
className="flex gap-2.5 border-b border-theme-light py-[7px]"
|
|
129
|
+
>
|
|
130
|
+
<span aria-hidden="true" className="font-label text-secondary">
|
|
131
|
+
✓
|
|
132
|
+
</span>
|
|
133
|
+
{item}
|
|
134
|
+
</li>
|
|
135
|
+
))}
|
|
136
|
+
</ul>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* ============ 01 · capture — the studio ============ */
|
|
141
|
+
|
|
142
|
+
const captureSchema = z.object({
|
|
143
|
+
cap: z.string(),
|
|
144
|
+
capNote: z.string().optional(),
|
|
145
|
+
headline: z.string(),
|
|
146
|
+
intro: z.string(),
|
|
147
|
+
checks: z.array(z.string()),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
function BrainCaptureSection({
|
|
151
|
+
cap,
|
|
152
|
+
capNote,
|
|
153
|
+
headline,
|
|
154
|
+
intro,
|
|
155
|
+
checks,
|
|
156
|
+
}: z.infer<typeof captureSchema>): JSX.Element {
|
|
157
|
+
return (
|
|
158
|
+
<Section id="capture" className="py-14">
|
|
159
|
+
{/* Screen styles are global; emitted once here, the first screen chapter. */}
|
|
160
|
+
<BrainScreenStyles />
|
|
161
|
+
<SectCap lead={cap} trail={capNote} />
|
|
162
|
+
<div className="mt-4 grid items-center gap-11 lg:grid-cols-[4fr_8fr]">
|
|
163
|
+
<div>
|
|
164
|
+
<h2 className="reveal reveal-delay-1 font-display text-[clamp(26px,2.6vw,34px)] font-[465] leading-[1.12] tracking-[-0.012em] text-theme [font-variation-settings:'SOFT'_78,'opsz'_84]">
|
|
165
|
+
{renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
|
|
166
|
+
</h2>
|
|
167
|
+
<p className="reveal reveal-delay-2 mt-4 font-body text-[16.5px] leading-[1.7] text-theme-muted">
|
|
168
|
+
{intro}
|
|
169
|
+
</p>
|
|
170
|
+
<Checks items={checks} />
|
|
171
|
+
</div>
|
|
172
|
+
<div className="reveal reveal-delay-2">
|
|
173
|
+
<StudioScreen />
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</Section>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ============ 02 · ask — the chat and its integrations ============ */
|
|
181
|
+
|
|
182
|
+
const askSchema = z.object({
|
|
183
|
+
cap: z.string(),
|
|
184
|
+
capNote: z.string().optional(),
|
|
185
|
+
headline: z.string(),
|
|
186
|
+
intro: z.string(),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
function BrainAskSection({
|
|
190
|
+
cap,
|
|
191
|
+
capNote,
|
|
192
|
+
headline,
|
|
193
|
+
intro,
|
|
194
|
+
}: z.infer<typeof askSchema>): JSX.Element {
|
|
195
|
+
return (
|
|
196
|
+
<Section id="ask" className="py-14">
|
|
197
|
+
<ChapterHead
|
|
198
|
+
cap={cap}
|
|
199
|
+
capNote={capNote}
|
|
200
|
+
headline={headline}
|
|
201
|
+
intro={intro}
|
|
202
|
+
/>
|
|
203
|
+
<div className="mt-7 grid items-start gap-6 lg:grid-cols-[1.12fr_1fr]">
|
|
204
|
+
<div className="reveal reveal-delay-1">
|
|
205
|
+
<ChatScreen />
|
|
206
|
+
</div>
|
|
207
|
+
<div className="reveal reveal-delay-2">
|
|
208
|
+
<IntegrationsScreen />
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</Section>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* ============ 03 · see it run — the dashboard ============ */
|
|
216
|
+
|
|
217
|
+
const runSchema = z.object({
|
|
218
|
+
cap: z.string(),
|
|
219
|
+
capNote: z.string().optional(),
|
|
220
|
+
headline: z.string(),
|
|
221
|
+
intro: z.string(),
|
|
222
|
+
note: z.string(),
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
function BrainRunSection({
|
|
226
|
+
cap,
|
|
227
|
+
capNote,
|
|
228
|
+
headline,
|
|
229
|
+
intro,
|
|
230
|
+
note,
|
|
231
|
+
}: z.infer<typeof runSchema>): JSX.Element {
|
|
232
|
+
return (
|
|
233
|
+
<Section id="run" className="py-14">
|
|
234
|
+
<ChapterHead
|
|
235
|
+
cap={cap}
|
|
236
|
+
capNote={capNote}
|
|
237
|
+
headline={headline}
|
|
238
|
+
intro={intro}
|
|
239
|
+
/>
|
|
240
|
+
<div className="reveal reveal-delay-1 mt-7 max-w-[1120px]">
|
|
241
|
+
<DashboardScreen />
|
|
242
|
+
</div>
|
|
243
|
+
<p className="reveal reveal-delay-2 mt-5 max-w-[52em] font-display text-[17px] font-normal italic text-theme-light [font-variation-settings:'SOFT'_85]">
|
|
244
|
+
{renderHighlightedText(note, "font-medium not-italic text-theme-muted")}
|
|
245
|
+
</p>
|
|
246
|
+
</Section>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* ============ 04 · connect — back to the map ============ */
|
|
251
|
+
|
|
252
|
+
const connectSchema = z.object({
|
|
253
|
+
cap: z.string(),
|
|
254
|
+
capNote: z.string().optional(),
|
|
255
|
+
headline: z.string(),
|
|
256
|
+
intro: z.string(),
|
|
257
|
+
cta: ctaSchema,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
function BrainConnectSection({
|
|
261
|
+
cap,
|
|
262
|
+
capNote,
|
|
263
|
+
headline,
|
|
264
|
+
intro,
|
|
265
|
+
cta,
|
|
266
|
+
}: z.infer<typeof connectSchema>): JSX.Element {
|
|
267
|
+
return (
|
|
268
|
+
<Section id="connect" className="py-14">
|
|
269
|
+
<ChapterHead
|
|
270
|
+
cap={cap}
|
|
271
|
+
capNote={capNote}
|
|
272
|
+
headline={headline}
|
|
273
|
+
intro={intro}
|
|
274
|
+
/>
|
|
275
|
+
<div className="reveal reveal-delay-2 mt-6">
|
|
276
|
+
<a
|
|
277
|
+
href={cta.href}
|
|
278
|
+
className="font-body text-[15.5px] text-theme-light no-underline transition-colors hover:text-accent"
|
|
279
|
+
>
|
|
280
|
+
{cta.label}
|
|
281
|
+
</a>
|
|
282
|
+
</div>
|
|
283
|
+
</Section>
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* ============ your data, your rules ============ */
|
|
288
|
+
|
|
289
|
+
function BrainYourDataSection({
|
|
290
|
+
cap,
|
|
291
|
+
items,
|
|
292
|
+
}: z.infer<typeof trioSchema>): JSX.Element {
|
|
293
|
+
return (
|
|
294
|
+
<Section id="your-data" className="py-14">
|
|
295
|
+
<SectCap lead={cap} />
|
|
296
|
+
<Trio items={items} mono={true} />
|
|
297
|
+
</Section>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* ============ quickstart ============ */
|
|
302
|
+
|
|
303
|
+
const termLineSchema = z.object({
|
|
304
|
+
kind: z.enum(["comment", "command", "ok"]),
|
|
305
|
+
text: z.string(),
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const quickstartSchema = z.object({
|
|
309
|
+
cap: z.string(),
|
|
310
|
+
capNote: z.string(),
|
|
311
|
+
lines: z.array(termLineSchema),
|
|
312
|
+
checks: z.array(z.string()),
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
type TermLine = z.infer<typeof termLineSchema>;
|
|
316
|
+
|
|
317
|
+
function termLineClass(kind: TermLine["kind"]): string {
|
|
318
|
+
switch (kind) {
|
|
319
|
+
case "comment":
|
|
320
|
+
return "text-theme-light opacity-70";
|
|
321
|
+
case "ok":
|
|
322
|
+
return "text-secondary";
|
|
323
|
+
case "command":
|
|
324
|
+
return "text-theme";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function BrainQuickstartSection({
|
|
329
|
+
cap,
|
|
330
|
+
capNote,
|
|
331
|
+
lines,
|
|
332
|
+
checks,
|
|
333
|
+
}: z.infer<typeof quickstartSchema>): JSX.Element {
|
|
334
|
+
return (
|
|
335
|
+
<Section id="quickstart" className="py-14">
|
|
336
|
+
<SectCap lead={cap} trail={capNote} />
|
|
337
|
+
<div className="mt-7 grid max-w-[1000px] items-start gap-12 md:grid-cols-[1.15fr_1fr]">
|
|
338
|
+
<div className="reveal reveal-delay-1 border border-theme bg-theme-subtle/60 px-6 py-5 font-label text-[14px] leading-[1.9]">
|
|
339
|
+
{lines.map((line, i) => (
|
|
340
|
+
<div key={i} className={termLineClass(line.kind)}>
|
|
341
|
+
{line.kind === "command" && (
|
|
342
|
+
<span className="select-none text-accent">$ </span>
|
|
343
|
+
)}
|
|
344
|
+
{line.text}
|
|
345
|
+
</div>
|
|
346
|
+
))}
|
|
347
|
+
</div>
|
|
348
|
+
<Checks items={checks} />
|
|
349
|
+
</div>
|
|
350
|
+
</Section>
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* ============ closing band ============ */
|
|
355
|
+
|
|
356
|
+
const closeSchema = z.object({
|
|
357
|
+
quote: z.string(),
|
|
358
|
+
sub: z.string(),
|
|
359
|
+
primaryCta: ctaSchema,
|
|
360
|
+
secondaryCta: ctaSchema,
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
function BrainCloseSection({
|
|
364
|
+
quote,
|
|
365
|
+
sub,
|
|
366
|
+
primaryCta,
|
|
367
|
+
secondaryCta,
|
|
368
|
+
}: z.infer<typeof closeSchema>): JSX.Element {
|
|
369
|
+
return (
|
|
370
|
+
<Band quote={quote}>
|
|
371
|
+
<p className="reveal reveal-delay-1 mt-[18px] max-w-[52ch] font-body text-[17px] text-theme-light">
|
|
372
|
+
{sub}
|
|
373
|
+
</p>
|
|
374
|
+
<CtaRow
|
|
375
|
+
primaryCta={primaryCta}
|
|
376
|
+
secondaryCta={secondaryCta}
|
|
377
|
+
className="reveal reveal-delay-2 mt-[26px]"
|
|
378
|
+
/>
|
|
379
|
+
</Band>
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* ============ the brain section group ============ */
|
|
384
|
+
|
|
385
|
+
export const brainSections: SiteSectionGroup = sectionGroup("brain", {
|
|
386
|
+
hero: defineSection(heroSchema, BrainHeroSection, {
|
|
387
|
+
title: "Hero",
|
|
388
|
+
description: "Product hero — build the agent that represents you",
|
|
389
|
+
}),
|
|
390
|
+
capture: defineSection(captureSchema, BrainCaptureSection, {
|
|
391
|
+
title: "Capture",
|
|
392
|
+
description: "01 · Capture — markdown corpus, illustrated by the studio",
|
|
393
|
+
}),
|
|
394
|
+
ask: defineSection(askSchema, BrainAskSection, {
|
|
395
|
+
title: "Ask",
|
|
396
|
+
description: "02 · Ask — chat + Discord, Claude/MCP, terminal",
|
|
397
|
+
}),
|
|
398
|
+
run: defineSection(runSchema, BrainRunSection, {
|
|
399
|
+
title: "See It Run",
|
|
400
|
+
description: "03 · See it run — the dashboard overview",
|
|
401
|
+
}),
|
|
402
|
+
connect: defineSection(connectSchema, BrainConnectSection, {
|
|
403
|
+
title: "Connect",
|
|
404
|
+
description: "04 · Connect — takes your seat in the network (the map)",
|
|
405
|
+
}),
|
|
406
|
+
"your-data": defineSection(trioSchema, BrainYourDataSection, {
|
|
407
|
+
title: "Your Data",
|
|
408
|
+
description: "Your data, your rules — ownership trio (mono markers)",
|
|
409
|
+
}),
|
|
410
|
+
quickstart: defineSection(quickstartSchema, BrainQuickstartSection, {
|
|
411
|
+
title: "Quickstart",
|
|
412
|
+
description: "Three-command quickstart terminal with a checklist",
|
|
413
|
+
}),
|
|
414
|
+
close: defineSection(closeSchema, BrainCloseSection, {
|
|
415
|
+
title: "Close",
|
|
416
|
+
description: "Closing band — own the intelligence you already have",
|
|
417
|
+
}),
|
|
418
|
+
});
|