Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 106 additions & 36 deletions docs/src/components/HeroSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,95 @@ import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import styles from './styles.module.css';

interface DemoScenario {
id: 'figma' | 'github' | 'linear' | 'notion';
tagline: [string, string];
subtitle: string;
command: string;
outputLines: string[];
successLine: string;
}
Comment on lines +6 to +13
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interface instead of type for DemoScenario

DemoScenario is a plain data structure with no inheritance or extension — the project's conventions prefer type over interface for such shapes.

Suggested change
interface DemoScenario {
id: 'figma' | 'github' | 'linear' | 'notion';
tagline: [string, string];
subtitle: string;
command: string;
outputLines: string[];
successLine: string;
}
type DemoScenario = {
id: 'figma' | 'github' | 'linear' | 'notion';
tagline: [string, string];
subtitle: string;
command: string;
outputLines: string[];
successLine: string;
};

Context Used: Rule from dashboard - Use type by default in TypeScript unless you specifically need interface features like extension... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/src/components/HeroSection/index.tsx
Line: 6-13

Comment:
**`interface` instead of `type` for `DemoScenario`**

`DemoScenario` is a plain data structure with no inheritance or extension — the project's conventions prefer `type` over `interface` for such shapes.

```suggestion
type DemoScenario = {
  id: 'figma' | 'github' | 'linear' | 'notion';
  tagline: [string, string];
  subtitle: string;
  command: string;
  outputLines: string[];
  successLine: string;
};
```

**Context Used:** Rule from `dashboard` - Use `type` by default in TypeScript unless you specifically need `interface` features like extension... ([source](https://app.greptile.com/review/custom-context?memory=c862f053-5655-4b41-be69-c840e3c9f280))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


const DEMO_SCENARIOS: DemoScenario[] = [
{
id: 'figma',
tagline: ['Design in Figma.', 'Ship pixel-perfect code.'],
subtitle:
'Point ralph-starter at a Figma file and get production-ready components with visual validation.',
command: 'ralph-starter figma',
outputLines: [
' Figma to Code',
'? Figma URL: https://figma.com/design/ABC123/Dashboard',
'? Build: responsive dashboard with sidebar nav',
'? Stack: Next.js + TypeScript + Tailwind CSS',
'\u2192 Fetching Figma API... 8 frames, 21 components',
'\u2192 Visual validation: 98.2% pixel match',
],
successLine: '\u2713 Done! Cost: $0.94 | 3 commits',
},
{
id: 'github',
tagline: ['Specs on GitHub.', 'Code ships itself.'],
subtitle:
'Point ralph-starter at a GitHub issue and get a fully implemented feature with tests and a PR.',
command: 'ralph-starter run --from github --issue 42',
outputLines: [
'\u2192 Fetching GitHub issue #42...',
' Found: "Add user authentication"',
' Labels: feature, auth',
'\u2192 Loop 1/5: Generating auth module...',
'\u2192 Loop 2/5: Adding tests and validation...',
'\u2192 Validation passed: 12 tests, lint clean',
],
successLine: '\u2713 Done! Cost: $0.38 | PR #87 created',
},
{
id: 'linear',
tagline: ['Tickets in Linear.', 'Features in production.'],
subtitle:
'Pull Linear tickets and let AI agents implement them end-to-end with automatic commits.',
command: 'ralph-starter run --from linear --label ready',
outputLines: [
'\u2192 Fetching Linear issues (ready)...',
' Found 4 issues: RAL-41, RAL-42, RAL-43, RAL-44',
'\u2192 Processing RAL-42: "Dark mode toggle"',
'\u2192 Loop 1/8: Implementing theme provider...',
'\u2192 Loop 2/8: Adding CSS variables...',
'\u2192 Validation passed: build clean',
],
successLine: '\u2713 Done! Cost: $0.52 | 5 commits',
},
{
id: 'notion',
tagline: ['Specs in Notion.', 'Code writes itself.'],
subtitle:
'Import requirements from Notion pages and let AI agents turn them into production-ready code.',
command: 'ralph-starter run --from notion --project "API Spec"',
outputLines: [
'\u2192 Fetching Notion page: "API Spec"...',
' Parsed: 3 sections, 12 endpoints',
'\u2192 Loop 1/6: Scaffolding Express routes...',
'\u2192 Loop 2/6: Adding middleware & validation...',
'\u2192 Loop 3/6: Writing integration tests...',
'\u2192 Validation passed: 18 tests, lint clean',
],
successLine: '\u2713 Done! Cost: $0.61 | 4 commits',
},
];

export default function HeroSection(): React.ReactElement {
const [isVisible, setIsVisible] = useState(false);
const [copied, setCopied] = useState(false);
const [scenarioIndex, setScenarioIndex] = useState(0);

useEffect(() => {
setScenarioIndex(Math.floor(Math.random() * DEMO_SCENARIOS.length));
const timer = setTimeout(() => setIsVisible(true), 100);
return () => clearTimeout(timer);
}, []);
Comment on lines +85 to 91
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSR hydration mismatch from Math.random() in useEffect

scenarioIndex is initialised to 0 (Figma) at render time, and then setScenarioIndex(Math.floor(Math.random() * …)) runs in useEffect after hydration. This is intentional for SSR/SEO (Figma is the safe default), but the two setScenarioIndex + setTimeout calls share one useEffect and only the timer is cleaned up. If the component were ever unmounted before the effect runs the setScenarioIndex call would still execute, causing a state-update-on-unmounted-component warning. Consider splitting them into two separate effects, or guarding with a ref:

Suggested change
const [scenarioIndex, setScenarioIndex] = useState(0);
useEffect(() => {
setScenarioIndex(Math.floor(Math.random() * DEMO_SCENARIOS.length));
const timer = setTimeout(() => setIsVisible(true), 100);
return () => clearTimeout(timer);
}, []);
useEffect(() => {
setScenarioIndex(Math.floor(Math.random() * DEMO_SCENARIOS.length));
}, []);
useEffect(() => {
const timer = setTimeout(() => setIsVisible(true), 100);
return () => clearTimeout(timer);
}, []);
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/src/components/HeroSection/index.tsx
Line: 85-91

Comment:
**SSR hydration mismatch from `Math.random()` in `useEffect`**

`scenarioIndex` is initialised to `0` (Figma) at render time, and then `setScenarioIndex(Math.floor(Math.random() * …))` runs in `useEffect` after hydration. This is intentional for SSR/SEO (Figma is the safe default), but the two `setScenarioIndex` + `setTimeout` calls share one `useEffect` and only the timer is cleaned up. If the component were ever unmounted before the effect runs the `setScenarioIndex` call would still execute, causing a state-update-on-unmounted-component warning. Consider splitting them into two separate effects, or guarding with a ref:

```suggestion
  useEffect(() => {
    setScenarioIndex(Math.floor(Math.random() * DEMO_SCENARIOS.length));
  }, []);

  useEffect(() => {
    const timer = setTimeout(() => setIsVisible(true), 100);
    return () => clearTimeout(timer);
  }, []);
```

How can I resolve this? If you propose a fix, please make it concise.


const scenario = DEMO_SCENARIOS[scenarioIndex];

const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText('npx ralph-starter');
Expand Down Expand Up @@ -50,12 +130,16 @@ export default function HeroSection(): React.ReactElement {
{/* Left: Text content */}
<div className={styles.heroContent}>
<h1 className={`${styles.tagline} ${styles.animateIn} ${styles.delay1}`}>
Get specs from anywhere.<br />
Run AI loops<br /> from zero to prod.
{scenario.tagline[0]}<br />
{scenario.tagline[1]}
</h1>

<p className={`${styles.subtitle} ${styles.animateIn} ${styles.delay2}`}>
Connect your tools, fetch requirements, and let AI agents build production-ready code automatically.
{scenario.subtitle} Also works with {
['Figma', 'GitHub', 'Linear', 'Notion']
.filter(name => name.toLowerCase() !== scenario.id)
.join(', ')
} specs.
</p>
Comment on lines +138 to 143
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtitle "Also works with" text not updated during SSR

On the server, scenarioIndex is 0 (Figma), so the subtitle correctly says "Also works with GitHub, Linear, Notion specs." After the client-side useEffect fires and picks a different scenario, the subtitle switches. This is fine for the crawlable SSR output.

However, the filter comparison uses name.toLowerCase() !== scenario.id. The IDs are already lowercase ('figma', 'github', etc.) and the display names are title-case ('Figma', 'GitHub', etc.). 'GitHub'.toLowerCase()'github' matches correctly, so the logic is sound. No bug here, just worth a note that this implicit casing convention should be kept consistent if new integrations are added.

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/src/components/HeroSection/index.tsx
Line: 138-143

Comment:
**Subtitle "Also works with" text not updated during SSR**

On the server, `scenarioIndex` is `0` (Figma), so the subtitle correctly says "Also works with GitHub, Linear, Notion specs." After the client-side `useEffect` fires and picks a different scenario, the subtitle switches. This is fine for the crawlable SSR output.

However, the filter comparison uses `name.toLowerCase() !== scenario.id`. The IDs are already lowercase (`'figma'`, `'github'`, etc.) and the display names are title-case (`'Figma'`, `'GitHub'`, etc.). `'GitHub'.toLowerCase()``'github'` matches correctly, so the logic is sound. No bug here, just worth a note that this implicit casing convention should be kept consistent if new integrations are added.

How can I resolve this? If you propose a fix, please make it concise.


{/* CTA row: button + install command + integrations */}
Expand Down Expand Up @@ -105,13 +189,13 @@ export default function HeroSection(): React.ReactElement {
<div className={styles.terminalBody}>
<div className={styles.terminalLine}>
<span className={styles.terminalPrompt}>$</span>
<span className={styles.terminalCommand}> ralph-starter run &quot;build a todo app&quot; --commit</span>
<span className={styles.terminalCommand}> {scenario.command}</span>
</div>
<div className={styles.terminalOutput}>
<div>✓ Loop 1: Analyzing requirements...</div>
<div>✓ Loop 2: Creating components...</div>
<div>✓ Loop 3: Adding tests...</div>
<div className={styles.terminalSuccess}>✓ Done! Cost: $0.42 | 3 commits created</div>
{scenario.outputLines.map((line, i) => (
<div key={i}>{line}</div>
))}
<div className={styles.terminalSuccess}>{scenario.successLine}</div>
</div>
</div>
</div>
Expand All @@ -120,34 +204,20 @@ export default function HeroSection(): React.ReactElement {
<div className={styles.integrations}>
<span className={styles.integrationLabel}>Integrations</span>
<div className={styles.integrationLogos}>
<Link to="/docs/sources/github" className={styles.integrationLink}>
<img
src={useBaseUrl('/img/github logo.webp')}
alt="GitHub"
className={styles.integrationLogo}
/>
</Link>
<Link to="/docs/sources/figma" className={styles.integrationLink}>
<img
src={useBaseUrl('/img/figma-logo.svg')}
alt="Figma"
className={styles.integrationLogo}
/>
</Link>
<Link to="/docs/sources/linear" className={styles.integrationLink}>
<img
src={useBaseUrl('/img/linear.jpeg')}
alt="Linear"
className={styles.integrationLogo}
/>
</Link>
<Link to="/docs/sources/notion" className={styles.integrationLink}>
<img
src={useBaseUrl('/img/notion logo.png')}
alt="Notion"
className={styles.integrationLogo}
/>
</Link>
{[
{ id: 'figma' as const, to: '/docs/cli/figma', src: '/img/figma-logo.svg', alt: 'Figma' },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point Figma integration logo at the sources route

The Figma logo link was changed to /docs/cli/figma, but this repo only defines the Figma docs page under the sources section (docs/docs/sources/figma.md, and other internal links use /docs/sources/figma). Clicking the hero Figma logo will therefore route users to a non-existent page instead of the Figma integration documentation.

Useful? React with 👍 / 👎.

{ id: 'github' as const, to: '/docs/sources/github', src: '/img/github logo.webp', alt: 'GitHub' },
{ id: 'linear' as const, to: '/docs/sources/linear', src: '/img/linear.jpeg', alt: 'Linear' },
{ id: 'notion' as const, to: '/docs/sources/notion', src: '/img/notion logo.png', alt: 'Notion' },
].map(({ id, to, src, alt }) => (
<Link key={id} to={to} className={styles.integrationLink}>
<img
src={useBaseUrl(src)}
alt={alt}
className={`${styles.integrationLogo} ${scenario.id === id ? styles.integrationLogoActive : ''}`}
/>
</Link>
))}
</div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion docs/src/components/HeroSection/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@
transition: all 0.3s ease;
}

.integrationLogo:hover {
.integrationLogo:hover,
.integrationLogoActive {
opacity: 0.8;
filter: grayscale(0%) brightness(1);
}
Expand Down
20 changes: 11 additions & 9 deletions docs/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { useEffect } from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import HeroSection from '@site/src/components/HeroSection';
import FigmaShowcase from '@site/src/components/FigmaShowcase';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import existing homepage sections instead of missing modules

index.tsx now imports and renders FigmaShowcase, VisualValidation, and AgentEcosystem, but these modules are not present anywhere under docs/src/components in this commit, so the docs app cannot resolve these imports during build/bundle. This makes the homepage fail to compile until the imports are reverted to existing components or the missing component modules are added.

Useful? React with 👍 / 👎.

import VisualValidation from '@site/src/components/VisualValidation';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing component files — build will fail

FigmaShowcase, VisualValidation, and AgentEcosystem are imported here but none of these files exist anywhere under docs/src/components/. The directory currently contains only:

AIToggle, AutoMode, ClientShowcase, DownloadDocs, FeatureSections, HeroSection, HomepageFeatures, IntegrationShowcase, LLMProviders, PresetsShowcase, QuickStart, SkillsShowcase, UseCases.

Running pnpm build in docs/ will fail with a module-not-found error for each of these three imports. They need to be created (or the imports need to be removed) before this PR is mergeable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/src/pages/index.tsx
Line: 5-7

Comment:
**Missing component files — build will fail**

`FigmaShowcase`, `VisualValidation`, and `AgentEcosystem` are imported here but none of these files exist anywhere under `docs/src/components/`. The directory currently contains only:

`AIToggle`, `AutoMode`, `ClientShowcase`, `DownloadDocs`, `FeatureSections`, `HeroSection`, `HomepageFeatures`, `IntegrationShowcase`, `LLMProviders`, `PresetsShowcase`, `QuickStart`, `SkillsShowcase`, `UseCases`.

Running `pnpm build` in `docs/` will fail with a module-not-found error for each of these three imports. They need to be created (or the imports need to be removed) before this PR is mergeable.

How can I resolve this? If you propose a fix, please make it concise.

import FeatureSections from '@site/src/components/FeatureSections';
import QuickStart from '@site/src/components/QuickStart';
import UseCases from '@site/src/components/UseCases';
import ClientShowcase from '@site/src/components/ClientShowcase';
import LLMProviders from '@site/src/components/LLMProviders';
import IntegrationShowcase from '@site/src/components/IntegrationShowcase';
import AutoMode from '@site/src/components/AutoMode';
import QuickStart from '@site/src/components/QuickStart';
import PresetsShowcase from '@site/src/components/PresetsShowcase';
import SkillsShowcase from '@site/src/components/SkillsShowcase';
import UseCases from '@site/src/components/UseCases';
import AgentEcosystem from '@site/src/components/AgentEcosystem';
import IntegrationShowcase from '@site/src/components/IntegrationShowcase';

export default function Home(): ReactNode {
useDocusaurusContext();
Expand All @@ -27,17 +28,18 @@ export default function Home(): ReactNode {
return (
<Layout
title="Home"
description="Connect your tools like Figma, GitHub, Linear, and Notion. Fetch specs from anywhere and let AI coding agents build production-ready code automatically with autonomous loops.">
description="AI-powered autonomous coding from specs to production. Connect Figma, GitHub, Linear, and Notion to run AI coding loops with visual validation.">
<HeroSection />
<main>
<FigmaShowcase />
<VisualValidation />
<FeatureSections />
<AutoMode />
<QuickStart />
<PresetsShowcase />
<SkillsShowcase />
<QuickStart />
<UseCases />
<ClientShowcase />
<LLMProviders />
<AgentEcosystem />
<IntegrationShowcase />
</main>
</Layout>
Expand Down
Loading