@rizom/site-rizom-ai 0.2.0-alpha.159 → 0.2.0-alpha.161

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/src/home.tsx ADDED
@@ -0,0 +1,369 @@
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 { GrowthDiagram } from "./growth-diagram";
7
+ import {
8
+ Band,
9
+ CtaRow,
10
+ AliveLine,
11
+ SectCap,
12
+ ctaSchema,
13
+ delayClass,
14
+ HIGHLIGHT_CLS,
15
+ } from "./shared";
16
+
17
+ /**
18
+ * The platform home page — today's rizom.ai tightened (hero → growth diagram
19
+ * → problem → your-data → quickstart → mission band → faces → living-proof
20
+ * colophon). Each section is authored from one zod schema (its component's
21
+ * props are `z.infer` of that schema); copy is content-driven, stored as
22
+ * markdown in site-content/home/<section>.md. Only the assembled section group
23
+ * is exported — the schemas and components are module-local.
24
+ */
25
+
26
+ /* ============ hero ============ */
27
+
28
+ const heroSchema = z.object({
29
+ kicker: z.string(),
30
+ headline: z.string(),
31
+ standfirst: z.string(),
32
+ primaryCta: ctaSchema,
33
+ secondaryCta: ctaSchema,
34
+ });
35
+
36
+ function HomeHeroSection({
37
+ kicker,
38
+ headline,
39
+ standfirst,
40
+ primaryCta,
41
+ secondaryCta,
42
+ }: z.infer<typeof heroSchema>): JSX.Element {
43
+ return (
44
+ <Section
45
+ id="hero"
46
+ className="relative overflow-hidden pt-[84px] pb-[72px] md:pt-[110px]"
47
+ >
48
+ <div
49
+ aria-hidden="true"
50
+ className="pointer-events-none absolute -inset-x-[15%] -inset-y-[35%] bg-[radial-gradient(760px_400px_at_16%_4%,var(--color-wash-a),transparent_64%),radial-gradient(560px_340px_at_92%_90%,var(--color-wash-b),transparent_70%)]"
51
+ />
52
+ <div className="relative">
53
+ <p className="animate-hero-rise font-label text-label-sm uppercase tracking-[0.22em] text-accent opacity-0">
54
+ {kicker}
55
+ </p>
56
+ <h1 className="mt-5 max-w-[10.5em] animate-hero-rise font-display text-[clamp(50px,6.4vw,96px)] font-[435] leading-[0.99] tracking-[-0.022em] text-theme opacity-0 [animation-delay:0.12s] [font-variation-settings:'SOFT'_92,'opsz'_130]">
57
+ {renderHighlightedText(headline, HIGHLIGHT_CLS)}
58
+ </h1>
59
+ <div className="mt-9 flex animate-hero-rise flex-col items-start gap-[22px] opacity-0 [animation-delay:0.26s] lg:flex-row lg:items-baseline lg:gap-[60px]">
60
+ <p className="max-w-[42ch] font-body text-[21px] leading-[1.7] text-theme-muted">
61
+ {renderHighlightedText(
62
+ standfirst,
63
+ "font-medium not-italic text-theme",
64
+ )}
65
+ </p>
66
+ <CtaRow primaryCta={primaryCta} secondaryCta={secondaryCta} />
67
+ </div>
68
+ </div>
69
+ </Section>
70
+ );
71
+ }
72
+
73
+ /* ============ growth diagram ============ */
74
+
75
+ const growthSchema = z.object({
76
+ cap: z.string(),
77
+ capNote: z.string(),
78
+ note: z.string(),
79
+ });
80
+
81
+ function HomeGrowthSection({
82
+ cap,
83
+ capNote,
84
+ note,
85
+ }: z.infer<typeof growthSchema>): JSX.Element {
86
+ return (
87
+ <Section id="growth" className="py-14">
88
+ <SectCap lead={cap} trail={capNote} />
89
+ <GrowthDiagram />
90
+ <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]">
91
+ {renderHighlightedText(note, "font-medium not-italic text-theme-muted")}
92
+ </p>
93
+ </Section>
94
+ );
95
+ }
96
+
97
+ /* ============ trios: problem + your-data ============ */
98
+
99
+ const trioItemSchema = z.object({
100
+ marker: z.string(),
101
+ title: z.string(),
102
+ text: z.string(),
103
+ });
104
+
105
+ const trioSchema = z.object({
106
+ cap: z.string(),
107
+ items: z.array(trioItemSchema),
108
+ });
109
+
110
+ type TrioItem = z.infer<typeof trioItemSchema>;
111
+
112
+ function Trio({
113
+ items,
114
+ mono,
115
+ }: {
116
+ items: TrioItem[];
117
+ mono: boolean;
118
+ }): JSX.Element {
119
+ return (
120
+ <div className="mt-[30px] grid max-w-[1040px] gap-11 md:grid-cols-3">
121
+ {items.map((item, i) => (
122
+ <div key={item.title} className={`reveal ${delayClass(i)}`}>
123
+ {mono ? (
124
+ <span className="inline-block pt-3 pb-[15px] font-label text-[14px] font-medium tracking-[0.1em] text-accent">
125
+ {item.marker}
126
+ </span>
127
+ ) : (
128
+ <span className="block font-display text-[44px] font-light leading-none text-theme-light [font-variation-settings:'SOFT'_30,'opsz'_100]">
129
+ {item.marker}
130
+ </span>
131
+ )}
132
+ <b className="mt-2.5 block font-display text-[21px] font-[520] tracking-[-0.006em] text-theme [font-variation-settings:'SOFT'_55]">
133
+ {item.title}
134
+ </b>
135
+ <p className="mt-2 font-body text-[15.5px] text-theme-light">
136
+ {item.text}
137
+ </p>
138
+ </div>
139
+ ))}
140
+ </div>
141
+ );
142
+ }
143
+
144
+ function HomeProblemSection({
145
+ cap,
146
+ items,
147
+ }: z.infer<typeof trioSchema>): JSX.Element {
148
+ return (
149
+ <Section id="problem" className="py-14">
150
+ <SectCap lead={cap} />
151
+ <Trio items={items} mono={false} />
152
+ </Section>
153
+ );
154
+ }
155
+
156
+ function HomeYourDataSection({
157
+ cap,
158
+ items,
159
+ }: z.infer<typeof trioSchema>): JSX.Element {
160
+ return (
161
+ <Section id="your-data" className="py-14">
162
+ <SectCap lead={cap} />
163
+ <Trio items={items} mono={true} />
164
+ </Section>
165
+ );
166
+ }
167
+
168
+ /* ============ quickstart ============ */
169
+
170
+ const termLineSchema = z.object({
171
+ kind: z.enum(["comment", "command", "ok"]),
172
+ text: z.string(),
173
+ });
174
+
175
+ const quickstartSchema = z.object({
176
+ cap: z.string(),
177
+ capNote: z.string(),
178
+ lines: z.array(termLineSchema),
179
+ checks: z.array(z.string()),
180
+ });
181
+
182
+ type TermLine = z.infer<typeof termLineSchema>;
183
+
184
+ function termLineClass(kind: TermLine["kind"]): string {
185
+ switch (kind) {
186
+ case "comment":
187
+ return "text-theme-light opacity-70";
188
+ case "ok":
189
+ return "text-secondary";
190
+ case "command":
191
+ return "text-theme";
192
+ }
193
+ }
194
+
195
+ function HomeQuickstartSection({
196
+ cap,
197
+ capNote,
198
+ lines,
199
+ checks,
200
+ }: z.infer<typeof quickstartSchema>): JSX.Element {
201
+ return (
202
+ <Section id="quickstart" className="py-14">
203
+ <SectCap lead={cap} trail={capNote} />
204
+ <div className="mt-7 grid max-w-[1000px] items-start gap-12 md:grid-cols-[1.15fr_1fr]">
205
+ <div className="reveal reveal-delay-1 border border-theme bg-theme-subtle/60 px-6 py-5 font-label text-[14px] leading-[1.9]">
206
+ {lines.map((line, i) => (
207
+ <div key={i} className={termLineClass(line.kind)}>
208
+ {line.kind === "command" && (
209
+ <span className="select-none text-accent">$ </span>
210
+ )}
211
+ {line.text}
212
+ </div>
213
+ ))}
214
+ </div>
215
+ <ul className="reveal reveal-delay-2 font-body text-[15.5px] text-theme-light">
216
+ {checks.map((check) => (
217
+ <li
218
+ key={check}
219
+ className="flex gap-2.5 border-b border-theme-light py-[7px]"
220
+ >
221
+ <span aria-hidden="true" className="font-label text-secondary">
222
+
223
+ </span>
224
+ {check}
225
+ </li>
226
+ ))}
227
+ </ul>
228
+ </div>
229
+ </Section>
230
+ );
231
+ }
232
+
233
+ /* ============ mission band ============ */
234
+
235
+ const missionSchema = z.object({
236
+ quote: z.string(),
237
+ sub: z.string(),
238
+ primaryCta: ctaSchema,
239
+ secondaryCta: ctaSchema,
240
+ });
241
+
242
+ function HomeMissionSection({
243
+ quote,
244
+ sub,
245
+ primaryCta,
246
+ secondaryCta,
247
+ }: z.infer<typeof missionSchema>): JSX.Element {
248
+ return (
249
+ <Band quote={quote}>
250
+ <p className="reveal reveal-delay-1 mt-[18px] max-w-[52ch] font-body text-[17px] text-theme-light">
251
+ {sub}
252
+ </p>
253
+ <CtaRow
254
+ primaryCta={primaryCta}
255
+ secondaryCta={secondaryCta}
256
+ className="reveal reveal-delay-2 mt-[26px]"
257
+ />
258
+ </Band>
259
+ );
260
+ }
261
+
262
+ /* ============ faces ============ */
263
+
264
+ const faceSchema = z.object({
265
+ room: z.enum(["platform", "work", "foundation"]),
266
+ kicker: z.string(),
267
+ title: z.string(),
268
+ go: z.string(),
269
+ href: z.string(),
270
+ });
271
+
272
+ const facesSchema = z.object({
273
+ cap: z.string(),
274
+ faces: z.array(faceSchema),
275
+ });
276
+
277
+ type FaceRow = z.infer<typeof faceSchema>;
278
+
279
+ const FACE_KICKER_COLOR: Record<FaceRow["room"], string> = {
280
+ platform: "text-[color:var(--palette-brass)]",
281
+ work: "text-[color:var(--palette-ruby-soft)]",
282
+ foundation: "text-[color:var(--palette-moss)]",
283
+ };
284
+
285
+ function HomeFacesSection({
286
+ cap,
287
+ faces,
288
+ }: z.infer<typeof facesSchema>): JSX.Element {
289
+ return (
290
+ <Section id="faces" className="py-14">
291
+ <SectCap lead={cap} />
292
+ <div className="mt-2.5">
293
+ {faces.map((face, i) => (
294
+ <a
295
+ key={face.room}
296
+ href={face.href}
297
+ data-room={face.room}
298
+ className={`reveal ${delayClass(i)} group grid items-baseline gap-1.5 border-t border-theme-light py-5 no-underline first:border-t-0 md:grid-cols-[120px_1fr_auto] md:gap-[30px]`}
299
+ >
300
+ <span
301
+ className={`font-label text-label-xs uppercase tracking-[0.16em] ${FACE_KICKER_COLOR[face.room]}`}
302
+ >
303
+ {face.kicker}
304
+ </span>
305
+ <span className="font-display text-[23px] font-[480] tracking-[-0.008em] text-theme [font-variation-settings:'SOFT'_70]">
306
+ {renderHighlightedText(
307
+ face.title,
308
+ "italic transition-colors group-hover:text-accent",
309
+ )}
310
+ </span>
311
+ <span className="font-label text-[12px] text-theme-light">
312
+ {face.go}
313
+ </span>
314
+ </a>
315
+ ))}
316
+ </div>
317
+ </Section>
318
+ );
319
+ }
320
+
321
+ /* ============ living-proof colophon ============ */
322
+
323
+ // The colophon renders through the shared AliveLine component directly.
324
+ const aliveSchema = z.object({
325
+ claim: z.string(),
326
+ links: z.array(ctaSchema),
327
+ });
328
+
329
+ /* ============ the home section group ============ */
330
+
331
+ /**
332
+ * The platform home page, in order. The namespace ("home") matches the route
333
+ * id, so each section stores as site-content/home/<section>.md and its
334
+ * template resolves as "home:<section>".
335
+ */
336
+ export const homeSections: SiteSectionGroup = sectionGroup("home", {
337
+ hero: defineSection(heroSchema, HomeHeroSection, {
338
+ title: "Hero",
339
+ description: "Platform homepage hero: kicker, headline, standfirst, CTAs",
340
+ }),
341
+ growth: defineSection(growthSchema, HomeGrowthSection, {
342
+ title: "Growth",
343
+ description: "You → Team → Network growth diagram with caption and note",
344
+ }),
345
+ problem: defineSection(trioSchema, HomeProblemSection, {
346
+ title: "Problem",
347
+ description: "Why it has to exist — problem trio (large numerals)",
348
+ }),
349
+ "your-data": defineSection(trioSchema, HomeYourDataSection, {
350
+ title: "Your Data",
351
+ description: "Your data, your rules — ownership trio (mono markers)",
352
+ }),
353
+ quickstart: defineSection(quickstartSchema, HomeQuickstartSection, {
354
+ title: "Quickstart",
355
+ description: "Three-command quickstart terminal with a checklist",
356
+ }),
357
+ mission: defineSection(missionSchema, HomeMissionSection, {
358
+ title: "Mission",
359
+ description: "Mission band — display-italic statement, sub line, CTAs",
360
+ }),
361
+ faces: defineSection(facesSchema, HomeFacesSection, {
362
+ title: "Faces",
363
+ description: "One practice, three faces — platform / work / foundation",
364
+ }),
365
+ alive: defineSection(aliveSchema, AliveLine, {
366
+ title: "Alive",
367
+ description: "Living-proof colophon — italic claim plus proof links",
368
+ }),
369
+ });
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { rizomAiSite, rizomAiSite as default } from "./site";
2
2
  export { aiRoutes } from "./routes";
3
- export { default as aiSiteContent } from "./site-content";
3
+ export { homeSections } from "./home";
4
+ export { workSections } from "./work";
5
+ export { foundationSections } from "./foundation";