Skip to content

Commit 43257d6

Browse files
committed
Optimize marketing landing page performance and layout
- Split the homepage into reusable sections - Add scroll reveal, tab crossfades, and keyboard tab support - Self-host DM Sans to remove the Google Fonts request
1 parent 7beb047 commit 43257d6

12 files changed

Lines changed: 814 additions & 580 deletions

File tree

apps/marketing/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"test": "vitest run"
1212
},
1313
"dependencies": {
14+
"@fontsource-variable/dm-sans": "^5.2.8",
1415
"astro": "^6.0.4"
1516
},
1617
"devDependencies": {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
/**
3+
* Core Surfaces — tabbed spotlight section showing Threads, Diffs, Preview, PR Review, Actions.
4+
* Uses CSS crossfade transitions and keyboard navigation.
5+
*/
6+
7+
interface Surface {
8+
id: string;
9+
label: string;
10+
kicker: string;
11+
title: string;
12+
body: string;
13+
bullets: readonly string[];
14+
}
15+
16+
interface Props {
17+
surfaces: ReadonlyArray<Surface>;
18+
}
19+
20+
const { surfaces } = Astro.props;
21+
const defaultId = surfaces[0]?.id ?? "";
22+
---
23+
24+
<section class="spotlight" data-tab-group data-tab-default={defaultId} data-reveal>
25+
<div class="spotlight-copy">
26+
<p class="section-kicker">Core surfaces</p>
27+
<h2 class="section-title">Built for the way real AI coding sessions actually unfold.</h2>
28+
<p class="section-body">
29+
Explore the surfaces that make OK Code feel coherent: thinking, reviewing, previewing,
30+
and shipping without the usual tab chaos.
31+
</p>
32+
<div class="spotlight-nav" role="tablist" aria-label="Feature spotlight tabs">
33+
{surfaces.map((item) => (
34+
<button
35+
type="button"
36+
class="spotlight-item"
37+
data-tab-button
38+
data-tab-target={item.id}
39+
role="tab"
40+
aria-selected={item.id === defaultId ? "true" : "false"}
41+
aria-controls={`panel-${item.id}`}
42+
tabindex={item.id === defaultId ? 0 : -1}
43+
>
44+
<span class="spotlight-item-label">{item.label}</span>
45+
<span class="spotlight-item-meta">{item.kicker}</span>
46+
</button>
47+
))}
48+
</div>
49+
</div>
50+
51+
<div class="spotlight-panels">
52+
{surfaces.map((item) => (
53+
<article
54+
class="spotlight-panel"
55+
id={`panel-${item.id}`}
56+
data-tab-panel={item.id}
57+
role="tabpanel"
58+
aria-hidden={item.id === defaultId ? "false" : "true"}
59+
data-active={item.id === defaultId ? "true" : "false"}
60+
>
61+
<p class="section-kicker">{item.kicker}</p>
62+
<h3>{item.title}</h3>
63+
<p>{item.body}</p>
64+
<ul class="detail-bullets">
65+
{item.bullets.map((bullet) => (
66+
<li>{bullet}</li>
67+
))}
68+
</ul>
69+
</article>
70+
))}
71+
</div>
72+
</section>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
/**
3+
* FAQ section — two-column grid of Q&A cards.
4+
*/
5+
6+
interface Props {
7+
faqs: ReadonlyArray<{ question: string; answer: string }>;
8+
}
9+
10+
const { faqs } = Astro.props;
11+
---
12+
13+
<section class="faq-section" aria-label="Frequently asked questions" data-reveal>
14+
<div class="section-heading">
15+
<p class="section-kicker">FAQ</p>
16+
<h2 class="section-title">What people need to know before they click.</h2>
17+
</div>
18+
19+
<div class="faq-grid">
20+
{faqs.map((item) => (
21+
<article class="faq-card">
22+
<h3>{item.question}</h3>
23+
<p>{item.answer}</p>
24+
</article>
25+
))}
26+
</div>
27+
</section>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
/**
3+
* Feature grid — three core product pillars.
4+
*/
5+
6+
interface Props {
7+
pillars: ReadonlyArray<{ eyebrow: string; title: string; body: string }>;
8+
}
9+
10+
const { pillars } = Astro.props;
11+
---
12+
13+
<section class="feature-grid" aria-label="Core product pillars" data-reveal>
14+
{pillars.map((pillar) => (
15+
<article class="feature-card">
16+
<div class="feature-eyebrow">{pillar.eyebrow}</div>
17+
<h2>{pillar.title}</h2>
18+
<p>{pillar.body}</p>
19+
</article>
20+
))}
21+
</section>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
/**
3+
* Final CTA — bottom-of-page call to action with download + GitHub links.
4+
*/
5+
---
6+
7+
<section class="final-cta" data-reveal>
8+
<p class="section-kicker">Ready</p>
9+
<h2>Stop building through tab chaos.</h2>
10+
<p>
11+
Bring chat, code review, preview, and release flow into one calm workspace built for serious
12+
AI-assisted work.
13+
</p>
14+
<div class="final-cta-actions">
15+
<a href="https://github.com/OpenKnots/okcode/releases" class="hero-button">
16+
<span class="hero-button-shine" aria-hidden="true"></span>
17+
<span>Download OK Code</span>
18+
</a>
19+
<a
20+
href="https://github.com/OpenKnots/okcode"
21+
target="_blank"
22+
rel="noopener noreferrer"
23+
class="secondary-button"
24+
>
25+
Explore on GitHub
26+
</a>
27+
</div>
28+
</section>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
---
2+
/**
3+
* Hero section — headline, CTA, and glassmorphic workspace mockup.
4+
*/
5+
---
6+
7+
<section class="hero" data-reveal>
8+
<div class="hero-copy">
9+
<div class="eyebrow">
10+
<span class="eyebrow-dot" aria-hidden="true"></span>
11+
AI-native code workspace
12+
</div>
13+
14+
<h1 class="tagline">The beautiful workspace for shipping with AI.</h1>
15+
16+
<p class="subtagline">
17+
Chat, diffs, preview, PR review, and release actions in one glassy desktop + web
18+
workspace — so you can stay in flow instead of juggling tabs, terminals, and disposable
19+
prompts.
20+
</p>
21+
22+
<div class="hero-actions">
23+
<a id="download-btn" href="https://github.com/OpenKnots/okcode/releases" class="hero-button">
24+
<span class="hero-button-shine" aria-hidden="true"></span>
25+
<span id="download-label">Download OK Code</span>
26+
</a>
27+
28+
<a
29+
href="https://github.com/OpenKnots/okcode"
30+
target="_blank"
31+
rel="noopener noreferrer"
32+
class="secondary-button"
33+
>
34+
View on GitHub
35+
</a>
36+
</div>
37+
38+
<div class="hero-meta">
39+
<a href="/download" class="other-platforms">Other platforms</a>
40+
<div class="hero-pills" aria-label="Product highlights">
41+
<span>Desktop + web</span>
42+
<span>Persistent threads</span>
43+
<span>Built-in diffs</span>
44+
<span>Local preview</span>
45+
<span>Open source</span>
46+
</div>
47+
</div>
48+
</div>
49+
50+
<div class="hero-visual" aria-hidden="true">
51+
<div class="hero-glow hero-glow--violet"></div>
52+
<div class="hero-glow hero-glow--cyan"></div>
53+
54+
<div class="orb orb--one"></div>
55+
<div class="orb orb--two"></div>
56+
57+
<div class="glass-stage">
58+
<div class="glass-toolbar">
59+
<div class="traffic-lights"><span></span><span></span><span></span></div>
60+
<div class="glass-label">OK Code</div>
61+
<div class="glass-badge">Live workspace</div>
62+
</div>
63+
64+
<div class="glass-body">
65+
<aside class="rail rail--sidebar">
66+
<div class="rail-title"></div>
67+
<div class="rail-chip rail-chip--active"></div>
68+
<div class="rail-chip"></div>
69+
<div class="rail-chip"></div>
70+
<div class="rail-chip rail-chip--short"></div>
71+
</aside>
72+
73+
<section class="center-stack">
74+
<div class="panel panel--thread">
75+
<div class="panel-head">
76+
<span class="panel-kicker">Thread</span>
77+
<span class="panel-status">Agent warm</span>
78+
</div>
79+
<div class="message message--large"></div>
80+
<div class="message"></div>
81+
<div class="message message--short"></div>
82+
</div>
83+
84+
<div class="panel-row">
85+
<div class="panel panel--diff">
86+
<div class="panel-head">
87+
<span class="panel-kicker">Latest diff</span>
88+
</div>
89+
<div class="code-line code-line--add"></div>
90+
<div class="code-line"></div>
91+
<div class="code-line code-line--remove"></div>
92+
<div class="code-line code-line--short"></div>
93+
</div>
94+
95+
<div class="panel panel--preview">
96+
<div class="panel-head">
97+
<span class="panel-kicker">Preview</span>
98+
</div>
99+
<div class="preview-window">
100+
<div class="preview-nav"></div>
101+
<div class="preview-card"></div>
102+
<div class="preview-line"></div>
103+
<div class="preview-line preview-line--short"></div>
104+
</div>
105+
</div>
106+
</div>
107+
</section>
108+
109+
<aside class="rail rail--meta">
110+
<div class="meta-card">
111+
<span class="meta-label">Review ready</span>
112+
<strong>3 files changed</strong>
113+
</div>
114+
<div class="meta-card">
115+
<span class="meta-label">Project action</span>
116+
<strong>Release flow saved</strong>
117+
</div>
118+
<div class="meta-card">
119+
<span class="meta-label">Mode</span>
120+
<strong>Calm dark glass</strong>
121+
</div>
122+
</aside>
123+
</div>
124+
</div>
125+
</div>
126+
</section>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
/**
3+
* Theme Showcase — tabbed visual identity section with CSS-driven crossfade between themes.
4+
*/
5+
6+
interface Theme {
7+
id: string;
8+
label: string;
9+
vibe: string;
10+
body: string;
11+
gradient: string;
12+
border: string;
13+
accent: string;
14+
}
15+
16+
interface Props {
17+
themes: ReadonlyArray<Theme>;
18+
}
19+
20+
const { themes } = Astro.props;
21+
const defaultId = themes[0]?.id ?? "";
22+
---
23+
24+
<section class="theme-section" data-tab-group data-tab-default={defaultId} data-reveal>
25+
<div class="theme-copy">
26+
<p class="section-kicker">Visual identity</p>
27+
<h2 class="section-title">A workspace with actual visual taste.</h2>
28+
<p class="section-body">
29+
Designed to feel calm, sharp, and expensive: true blacks, soft glass, restrained color,
30+
and enough personality to make long sessions feel better.
31+
</p>
32+
<div class="tab-row" role="tablist" aria-label="Theme preview tabs">
33+
{themes.map((theme) => (
34+
<button
35+
type="button"
36+
class="tab-chip"
37+
data-tab-button
38+
data-tab-target={theme.id}
39+
role="tab"
40+
aria-selected={theme.id === defaultId ? "true" : "false"}
41+
aria-controls={`panel-${theme.id}`}
42+
tabindex={theme.id === defaultId ? 0 : -1}
43+
>
44+
{theme.label}
45+
</button>
46+
))}
47+
</div>
48+
</div>
49+
50+
<div class="theme-preview-wrap">
51+
{themes.map((theme) => (
52+
<div
53+
class="theme-preview"
54+
id={`panel-${theme.id}`}
55+
data-tab-panel={theme.id}
56+
role="tabpanel"
57+
aria-hidden={theme.id === defaultId ? "false" : "true"}
58+
data-active={theme.id === defaultId ? "true" : "false"}
59+
>
60+
<div
61+
class="theme-preview-card"
62+
style={`--theme-gradient:${theme.gradient}; --theme-border:${theme.border}; --theme-accent:${theme.accent};`}
63+
>
64+
<div class="theme-preview-bar">
65+
<span></span><span></span><span></span>
66+
</div>
67+
<div class="theme-preview-body">
68+
<div class="theme-preview-sidebar"></div>
69+
<div class="theme-preview-main">
70+
<div class="theme-preview-line theme-preview-line--short"></div>
71+
<div class="theme-preview-line"></div>
72+
<div class="theme-preview-line theme-preview-line--accent"></div>
73+
<div class="theme-preview-line theme-preview-line--medium"></div>
74+
</div>
75+
</div>
76+
</div>
77+
<div class="theme-note">
78+
<h3>{theme.label}</h3>
79+
<p class="theme-vibe">{theme.vibe}</p>
80+
<p>{theme.body}</p>
81+
</div>
82+
</div>
83+
))}
84+
</div>
85+
</section>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
/**
3+
* Trust strip — three trust signals below the hero.
4+
*/
5+
---
6+
7+
<section class="trust-strip" aria-label="Why teams use OK Code" data-reveal>
8+
<div class="trust-item">
9+
<span class="trust-label">Made for builders</span>
10+
<strong>Designed around real AI coding workflows</strong>
11+
</div>
12+
<div class="trust-item">
13+
<span class="trust-label">Calm by default</span>
14+
<strong>Less context switching, more legible work</strong>
15+
</div>
16+
<div class="trust-item">
17+
<span class="trust-label">Close to the metal</span>
18+
<strong>Open source, desktop-aware, release-friendly</strong>
19+
</div>
20+
</section>

0 commit comments

Comments
 (0)