@@ -4,6 +4,11 @@ import { ArrowRight, Check } from 'lucide-react';
44import { Bricolage_Grotesque , IBM_Plex_Mono } from 'next/font/google' ;
55import { HomeLayout } from 'fumadocs-ui/layouts/home' ;
66import { baseOptions , gitConfig } from '@/lib/layout.shared' ;
7+ import { YouTubeEmbed } from '@/components/youtube-embed' ;
8+
9+ /** The 90-second overview — the same video the README's hero cover links to. */
10+ const OVERVIEW_VIDEO_ID = 'CX_FlOoOtr0' ;
11+ const YOUTUBE_CHANNEL_URL = 'https://www.youtube.com/@objectstack' ;
712
813const display = Bricolage_Grotesque ( {
914 subsets : [ 'latin' ] ,
@@ -105,72 +110,140 @@ export default function HomePage() {
105110 />
106111
107112 { /* ── hero ─────────────────────────────────────────────── */ }
108- < section className = "relative mx-auto grid w-full max-w-6xl items-center gap-12 px-6 pt-20 pb-16 md:grid-cols-[1.05fr_0.95fr] md:pt-28 md:pb-24" >
109- < div >
110- < p className = "text-xs font-medium tracking-[0.18em] text-fd-muted-foreground uppercase" style = { { fontFamily : 'var(--l-mono)' } } >
111- Open protocol & runtime · Apache-2.0
112- </ p >
113- < h1
114- className = "mt-5 text-[2.6rem]/[1.06] font-bold tracking-tight text-balance md:text-6xl/[1.04]"
115- style = { { fontFamily : 'var(--l-display)' } }
113+ < section className = "relative mx-auto w-full max-w-5xl px-6 pt-16 text-center md:pt-20" >
114+ < p className = "text-xs font-medium tracking-[0.18em] text-fd-muted-foreground uppercase" style = { { fontFamily : 'var(--l-mono)' } } >
115+ Open protocol & runtime · Apache-2.0
116+ </ p >
117+ < h1
118+ className = "mx-auto mt-5 max-w-3xl text-[2.6rem]/[1.06] font-bold tracking-tight text-balance md:text-6xl/[1.04]"
119+ style = { { fontFamily : 'var(--l-display)' } }
120+ >
121+ Apps small enough{ ' ' }
122+ < span className = "block bg-gradient-to-r from-indigo-500 to-purple-500 bg-clip-text text-transparent dark:from-indigo-400 dark:to-purple-400" >
123+ for AI to hold whole.
124+ </ span >
125+ </ h1 >
126+ < p className = "mx-auto mt-6 max-w-2xl text-lg text-fd-muted-foreground text-pretty" >
127+ ObjectStack turns the whole app — data model, UI, workflows, permissions — into
128+ typed metadata: a complete CRM in under 150k tokens, one context window. Agents
129+ read it whole, reason it whole, refactor it whole.
130+ </ p >
131+ < div className = "mt-8 flex flex-wrap items-center justify-center gap-3" >
132+ < Link
133+ href = "/docs/getting-started"
134+ className = "inline-flex items-center gap-2 rounded-lg bg-fd-primary px-5 py-2.5 text-sm font-medium text-fd-primary-foreground transition-colors hover:bg-fd-primary/90"
116135 >
117- Apps small enough{ ' ' }
118- < span className = "block bg-gradient-to-r from-indigo-500 to-purple-500 bg-clip-text text-transparent dark:from-indigo-400 dark:to-purple-400" >
119- for AI to hold whole.
120- </ span >
121- </ h1 >
122- < p className = "mt-6 max-w-xl text-lg text-fd-muted-foreground text-pretty" >
123- ObjectStack turns the whole app — data model, UI, workflows, permissions — into
124- typed metadata: a complete CRM in under 150k tokens, one context window. Agents
125- read it whole, reason it whole, refactor it whole.
126- </ p >
127- < p className = "mt-4 max-w-xl text-lg text-fd-muted-foreground text-pretty" >
136+ Get started
137+ < ArrowRight className = "size-4" />
138+ </ Link >
139+ < Link
140+ href = "/docs"
141+ className = "inline-flex items-center rounded-lg border border-fd-border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
142+ >
143+ Documentation
144+ </ Link >
145+ < a
146+ href = { `https://github.com/${ gitConfig . user } /${ gitConfig . repo } ` }
147+ target = "_blank"
148+ rel = "noreferrer noopener"
149+ className = "inline-flex items-center rounded-lg border border-fd-border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
150+ >
151+ GitHub
152+ </ a >
153+ < a
154+ href = { YOUTUBE_CHANNEL_URL }
155+ target = "_blank"
156+ rel = "noreferrer noopener"
157+ className = "inline-flex items-center rounded-lg border border-fd-border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
158+ >
159+ YouTube
160+ </ a >
161+ </ div >
162+ < div
163+ className = "mt-8 flex flex-wrap items-center justify-center gap-x-3 gap-y-2 text-[13px] text-fd-muted-foreground"
164+ style = { { fontFamily : 'var(--l-mono)' } }
165+ >
166+ < span > Fits in an agent's context</ span >
167+ < span aria-hidden className = "text-fd-border" > |</ span >
168+ < span > Typed, validated, governed</ span >
169+ < span aria-hidden className = "text-fd-border" > |</ span >
170+ < span > Self-host anywhere</ span >
171+ </ div >
172+ </ section >
173+
174+ { /* ── the 90-second overview — the page's first visual ──── */ }
175+ < section className = "relative mx-auto w-full max-w-5xl px-6 pt-12 md:pt-14" >
176+ < figure className = "relative" >
177+ < YouTubeEmbed
178+ videoId = { OVERVIEW_VIDEO_ID }
179+ title = "ObjectStack in 90 Seconds"
180+ poster = "/hero-cover-dark.png"
181+ />
182+ < figcaption
183+ className = "mt-3 flex flex-wrap items-center justify-center gap-x-3 gap-y-1 text-[12px] text-fd-muted-foreground"
184+ style = { { fontFamily : 'var(--l-mono)' } }
185+ >
186+ < span > ▶ ObjectStack in 90 Seconds</ span >
187+ < a
188+ href = { YOUTUBE_CHANNEL_URL }
189+ target = "_blank"
190+ rel = "noreferrer noopener"
191+ className = "inline-flex items-center gap-1 text-fd-foreground underline underline-offset-4 transition-colors hover:text-fd-primary"
192+ >
193+ More videos on YouTube
194+ < ArrowRight className = "size-3" />
195+ </ a >
196+ </ figcaption >
197+ </ figure >
198+ </ section >
199+
200+ { /* ── the claim the video makes, in prose ──────────────── */ }
201+ < section className = "relative mx-auto w-full max-w-5xl px-6 pt-12 md:pt-14" >
202+ < div className = "grid gap-8 md:grid-cols-2" >
203+ < p className = "text-lg text-fd-muted-foreground text-pretty" >
128204 The business logic alone — every object, workflow and permission — is under 100k
129205 tokens; the UI adds just 50k more.
130206 </ p >
131- < p className = "mt-4 max-w-xl text-base text-fd-muted-foreground text-pretty" >
207+ < p className = "text-base text-fd-muted-foreground text-pretty" >
132208 That metadata is your business ontology — an open, versioned definition you own.
133- Strict TypeScript, Zod schemas, and a validation gate catch the agent' s mistakes
209+ Strict TypeScript, Zod schemas, and a validation gate catch the agent' s mistakes
134210 at authoring time, and the runtime derives the database, REST API, UI, and MCP
135211 server — permissions and audit enforced on every call.
136212 </ p >
137- < div className = "mt-8 flex flex-wrap items-center gap-3" >
138- < Link
139- href = "/docs/getting-started"
140- className = "inline-flex items-center gap-2 rounded-lg bg-fd-primary px-5 py-2.5 text-sm font-medium text-fd-primary-foreground transition-colors hover:bg-fd-primary/90"
141- >
142- Get started
143- < ArrowRight className = "size-4" />
144- </ Link >
145- < Link
146- href = "/docs"
147- className = "inline-flex items-center rounded-lg border border-fd-border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
148- >
149- Documentation
150- </ Link >
151- < a
152- href = { `https://github.com/${ gitConfig . user } /${ gitConfig . repo } ` }
153- target = "_blank"
154- rel = "noreferrer noopener"
155- className = "inline-flex items-center rounded-lg border border-fd-border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
156- >
157- GitHub
158- </ a >
159- </ div >
160- < div
161- className = "mt-8 flex flex-wrap items-center gap-x-3 gap-y-2 text-[13px] text-fd-muted-foreground"
162- style = { { fontFamily : 'var(--l-mono)' } }
163- >
164- < span > Fits in an agent's context</ span >
165- < span aria-hidden className = "text-fd-border" > |</ span >
166- < span > Typed, validated, governed</ span >
167- < span aria-hidden className = "text-fd-border" > |</ span >
168- < span > Self-host anywhere</ span >
169- </ div >
213+ </ div >
214+ </ section >
215+
216+ { /* ── 01 · the loop ────────────────────────────────────── */ }
217+ < section className = "relative mx-auto w-full max-w-6xl px-6 py-16 md:py-20" >
218+ < div className = "flex items-baseline gap-4 border-t border-fd-border pt-8" >
219+ < span className = "text-xs tracking-[0.18em] text-fd-muted-foreground uppercase" style = { { fontFamily : 'var(--l-mono)' } } >
220+ 01 · The loop
221+ </ span >
222+ </ div >
223+ < h2 className = "mt-4 max-w-2xl text-3xl font-bold tracking-tight md:text-4xl" style = { { fontFamily : 'var(--l-display)' } } >
224+ From requirement to running app
225+ </ h2 >
226+ < div className = "mt-10 grid gap-8 md:grid-cols-3" >
227+ { STEPS . map ( ( s ) => (
228+ < div key = { s . num } className = "group relative" >
229+ < div className = "flex items-center gap-3" >
230+ < span className = "text-sm text-fd-muted-foreground" style = { { fontFamily : 'var(--l-mono)' } } > { s . num } </ span >
231+ < div className = "h-px flex-1 bg-fd-border" aria-hidden />
232+ </ div >
233+ < h3 className = "mt-4 text-lg font-semibold" style = { { fontFamily : 'var(--l-display)' } } > { s . title } </ h3 >
234+ < p
235+ className = "mt-2 inline-block rounded-md border border-fd-border bg-fd-muted/50 px-2.5 py-1 text-[12.5px] text-fd-muted-foreground"
236+ style = { { fontFamily : 'var(--l-mono)' } }
237+ >
238+ { s . cmd }
239+ </ p >
240+ < p className = "mt-3 text-[15px] text-fd-muted-foreground text-pretty" > { s . copy } </ p >
241+ </ div >
242+ ) ) }
170243 </ div >
171244
172245 { /* the artifact card — requirement → metadata → gate → preview */ }
173- < figure className = "relative" >
246+ < figure className = "relative mx-auto mt-12 max-w-2xl " >
174247 < div className = "overflow-hidden rounded-xl border border-fd-border bg-fd-card shadow-[0_24px_60px_-24px_rgb(0_0_0/0.35)]" >
175248 < div className = "border-b border-fd-border px-4 py-3" style = { { fontFamily : 'var(--l-mono)' } } >
176249 < p className = "text-[11px] tracking-wider text-fd-muted-foreground uppercase" > you → claude code</ p >
@@ -217,36 +290,6 @@ export default function HomePage() {
217290 </ figure >
218291 </ section >
219292
220- { /* ── 01 · the loop ────────────────────────────────────── */ }
221- < section className = "relative mx-auto w-full max-w-6xl px-6 py-16 md:py-20" >
222- < div className = "flex items-baseline gap-4 border-t border-fd-border pt-8" >
223- < span className = "text-xs tracking-[0.18em] text-fd-muted-foreground uppercase" style = { { fontFamily : 'var(--l-mono)' } } >
224- 01 · The loop
225- </ span >
226- </ div >
227- < h2 className = "mt-4 max-w-2xl text-3xl font-bold tracking-tight md:text-4xl" style = { { fontFamily : 'var(--l-display)' } } >
228- From requirement to running app
229- </ h2 >
230- < div className = "mt-10 grid gap-8 md:grid-cols-3" >
231- { STEPS . map ( ( s ) => (
232- < div key = { s . num } className = "group relative" >
233- < div className = "flex items-center gap-3" >
234- < span className = "text-sm text-fd-muted-foreground" style = { { fontFamily : 'var(--l-mono)' } } > { s . num } </ span >
235- < div className = "h-px flex-1 bg-fd-border" aria-hidden />
236- </ div >
237- < h3 className = "mt-4 text-lg font-semibold" style = { { fontFamily : 'var(--l-display)' } } > { s . title } </ h3 >
238- < p
239- className = "mt-2 inline-block rounded-md border border-fd-border bg-fd-muted/50 px-2.5 py-1 text-[12.5px] text-fd-muted-foreground"
240- style = { { fontFamily : 'var(--l-mono)' } }
241- >
242- { s . cmd }
243- </ p >
244- < p className = "mt-3 text-[15px] text-fd-muted-foreground text-pretty" > { s . copy } </ p >
245- </ div >
246- ) ) }
247- </ div >
248- </ section >
249-
250293 { /* ── 02 · four gates ──────────────────────────────────── */ }
251294 < section className = "relative mx-auto w-full max-w-6xl px-6 py-16 md:py-20" >
252295 < div className = "flex items-baseline gap-4 border-t border-fd-border pt-8" >
0 commit comments