Skip to content

Commit 4503784

Browse files
committed
fix(web): update landing page copy and add Sign in button
- Fix misleading claims: "Zero data retention" (we persist events), "Anthropic API key" (it's an OAuth token), "both author and reviewer" (only author for now), "automatically creates session" (posts a link) - Replace "Zero data retention" with "Ephemeral containers" - Replace "2 roles" stat with "Self-hosted" - Add Sign in button in header for authenticated access to dashboard - Add SignInButton component linking to /api/v1/auth/github
1 parent 47b3df8 commit 4503784

3 files changed

Lines changed: 48 additions & 14 deletions

File tree

apps/web/src/features/landing/LandingPage.test.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ describe('LandingPage', () => {
4343
test('renders terminal-like visuals for each step', () => {
4444
const { container } = render(<LandingPage />)
4545
const text = container.textContent ?? ''
46-
expect(text).toContain('PR #42 opened')
46+
expect(text).toContain('PR #42')
4747
expect(text).toContain('recursive approach here')
4848
expect(text).toContain('strong')
4949
})
@@ -52,7 +52,7 @@ describe('LandingPage', () => {
5252
render(<LandingPage />)
5353
expect(screen.getByText('Your keys, your data, your control')).toBeTruthy()
5454
expect(screen.getByText('Bring Your Own Key')).toBeTruthy()
55-
expect(screen.getByText('Zero data retention')).toBeTruthy()
55+
expect(screen.getByText('Ephemeral containers')).toBeTruthy()
5656
expect(screen.getByText('Private by default')).toBeTruthy()
5757
})
5858

@@ -71,7 +71,13 @@ describe('LandingPage', () => {
7171
render(<LandingPage />)
7272
expect(screen.getByText(/Comprehension debt/)).toBeTruthy()
7373
expect(screen.getByText('5-7x')).toBeTruthy()
74-
expect(screen.getByText('2 roles')).toBeTruthy()
74+
expect(screen.getByText('Self-hosted')).toBeTruthy()
75+
})
76+
77+
test('renders sign-in link in header', () => {
78+
render(<LandingPage />)
79+
const signIn = screen.getByRole('link', { name: /sign in/i })
80+
expect(signIn.getAttribute('href')).toContain('/api/v1/auth/github')
7581
})
7682

7783
test('renders footer with GitHub link', () => {

apps/web/src/features/landing/LandingPage.tsx

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import InstallCTA from './InstallCTA'
2+
import SignInButton from './SignInButton'
23

34
/*
45
* Dark theme — Raycast-inspired with amber accent and real terminal blocks.
@@ -60,19 +61,19 @@ const STEPS = [
6061
{
6162
number: '01',
6263
title: 'PR opened',
63-
description: 'helPRs automatically creates a comprehension session for every pull request.',
64+
description: 'helPRs comments on every pull request with a link to start a comprehension session.',
6465
terminal: (
6566
<>
6667
<span style={{ color: TERM.green }}>$</span>{' git push origin feature/auth\n'}
6768
<span style={{ color: TERM.muted }}>{' \u2192 PR #42 opened\n'}</span>
68-
<span style={{ color: TERM.green }}>{' \u2192 helPRs session created'}</span>
69+
<span style={{ color: TERM.green }}>{' \u2192 helPRs: Ready to challenge you'}</span>
6970
</>
7071
),
7172
},
7273
{
7374
number: '02',
7475
title: 'Answer Socratic questions',
75-
description: 'AI asks targeted questions about your code decisions \u2014 both author and reviewer.',
76+
description: 'AI asks targeted questions about your code decisions, trade-offs, and edge cases.',
7677
terminal: (
7778
<>
7879
<span style={{ color: TERM.amber }}>?</span>{' Why did you choose a\n recursive approach here\n instead of iterative?'}
@@ -102,12 +103,12 @@ const BYOK_ITEMS = [
102103
{
103104
label: 'BYOK',
104105
title: 'Bring Your Own Key',
105-
description: 'You provide your Anthropic API key. We never touch it beyond forwarding requests.',
106+
description: 'You provide your own Claude credentials. They stay on your infrastructure \u2014 encrypted at rest, injected at runtime.',
106107
},
107108
{
108-
label: 'ZERO',
109-
title: 'Zero data retention',
110-
description: 'No question or answer text stored. Metadata only \u2014 hashes, scores, timestamps.',
109+
label: 'EPHEM',
110+
title: 'Ephemeral containers',
111+
description: 'Each session runs in an isolated Docker container that is destroyed after completion. Nothing persists between sessions.',
111112
},
112113
{
113114
label: 'PRIV',
@@ -139,8 +140,18 @@ export default function LandingPage() {
139140
className="min-h-screen bg-primary text-text-primary"
140141
style={{ fontFamily: 'var(--font-family-sans)', letterSpacing: '0.2px' }}
141142
>
143+
{/* Nav */}
144+
<header className="w-full px-6 py-5">
145+
<div className="max-w-[960px] mx-auto flex items-center justify-between">
146+
<span className="text-text-secondary font-semibold font-mono text-[15px]" style={{ letterSpacing: '-0.01em' }}>
147+
<span style={{ color: '#E2A039' }}>helPRs</span>
148+
</span>
149+
<SignInButton />
150+
</div>
151+
</header>
152+
142153
{/* Hero */}
143-
<Section className="pt-28 pb-24 md:pt-44 md:pb-36">
154+
<Section className="pt-16 pb-24 md:pt-32 md:pb-36">
144155
<div className="mb-8">
145156
<span
146157
className="inline-block text-text-secondary text-[13px] font-medium px-3.5 py-1.5"
@@ -172,7 +183,7 @@ export default function LandingPage() {
172183
{' '}the code you ship?
173184
</h1>
174185
<p className="text-text-secondary text-[17px] leading-[1.65] mb-12 max-w-[540px]">
175-
helPRs creates Socratic comprehension sessions for every pull request — challenging both author and reviewer to prove they understand the code before it merges.
186+
helPRs creates Socratic comprehension sessions for every pull request — challenging the author to prove they understand the code before it merges.
176187
</p>
177188
<div className="flex flex-col sm:flex-row items-start gap-5">
178189
<InstallCTA className="w-full sm:w-auto" />
@@ -259,8 +270,8 @@ export default function LandingPage() {
259270
<p className="text-text-secondary text-[14px] leading-[1.55] mt-1">faster code generation than comprehension</p>
260271
</div>
261272
<div className="py-5" style={{ borderTop: '1px solid rgba(255,255,255,0.08)' }}>
262-
<p className="text-text-primary text-[28px] font-bold font-mono" style={{ letterSpacing: '-0.02em' }}>2 roles</p>
263-
<p className="text-text-secondary text-[14px] leading-[1.55] mt-1">both author and reviewer are challenged</p>
273+
<p className="text-text-primary text-[28px] font-bold font-mono" style={{ letterSpacing: '-0.02em' }}>Self-hosted</p>
274+
<p className="text-text-secondary text-[14px] leading-[1.55] mt-1">your infrastructure, your data, your Claude credentials</p>
264275
</div>
265276
<div className="pt-5" style={{ borderTop: '1px solid rgba(255,255,255,0.08)' }}>
266277
<p className="text-success text-[28px] font-bold font-mono" style={{ letterSpacing: '-0.02em' }}>Private</p>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const API_BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:8000'
2+
3+
export default function SignInButton() {
4+
return (
5+
<a
6+
href={`${API_BASE}/api/v1/auth/github`}
7+
className="text-[13px] font-medium px-4 py-2 transition-colors duration-150 hover:text-text-primary"
8+
style={{
9+
borderRadius: '8px',
10+
color: 'rgba(255, 255, 255, 0.6)',
11+
boxShadow: 'rgba(255,255,255,0.08) 0 0 0 1px',
12+
}}
13+
>
14+
Sign in
15+
</a>
16+
)
17+
}

0 commit comments

Comments
 (0)