feat(docs): randomize hero terminal demo across integrations#263
feat(docs): randomize hero terminal demo across integrations#263rubenmarcus wants to merge 2 commits intomainfrom
Conversation
The hero section now randomly shows one of four integration workflows (Figma, GitHub, Linear, Notion) on each page load, with matching taglines and highlighted integration logos. Figma is the SSR default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Issue Linking ReminderThis PR doesn't appear to have a linked issue. Consider linking to:
Using If this PR doesn't need an issue, you can ignore this message. |
Greptile SummaryThis PR makes the hero section's terminal demo dynamic: on each client-side page load one of four integration scenarios (Figma, GitHub, Linear, Notion) is randomly selected, updating the tagline, subtitle, command output, and the highlighted integration logo. Figma remains the SSR default (index The approach is clean and low-risk for the Key observations:
Confidence Score: 2/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant SSR as SSR / Crawler
participant Browser as Browser (Client)
participant HeroSection as HeroSection Component
SSR->>HeroSection: Render (scenarioIndex = 0 → Figma)
HeroSection-->>SSR: Static HTML with Figma tagline/terminal
Browser->>HeroSection: Hydrate
HeroSection->>HeroSection: useEffect fires
HeroSection->>HeroSection: setScenarioIndex(Math.random() * 4)
HeroSection->>HeroSection: setTimeout → setIsVisible(true)
HeroSection-->>Browser: Re-render with random scenario (Figma/GitHub/Linear/Notion)
HeroSection-->>Browser: Highlight active integration logo (integrationLogoActive)
Last reviewed commit: a24245d |
| interface DemoScenario { | ||
| id: 'figma' | 'github' | 'linear' | 'notion'; | ||
| tagline: [string, string]; | ||
| subtitle: string; | ||
| command: string; | ||
| outputLines: string[]; | ||
| successLine: string; | ||
| } |
There was a problem hiding this 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.
| 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 [scenarioIndex, setScenarioIndex] = useState(0); | ||
|
|
||
| useEffect(() => { | ||
| setScenarioIndex(Math.floor(Math.random() * DEMO_SCENARIOS.length)); | ||
| const timer = setTimeout(() => setIsVisible(true), 100); | ||
| return () => clearTimeout(timer); | ||
| }, []); |
There was a problem hiding this 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:
| 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.| {scenario.subtitle} Also works with { | ||
| ['Figma', 'GitHub', 'Linear', 'Notion'] | ||
| .filter(name => name.toLowerCase() !== scenario.id) | ||
| .join(', ') | ||
| } specs. | ||
| </p> |
There was a problem hiding this 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.
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.
docs/src/pages/index.tsx
Outdated
| import HeroSection from '@site/src/components/HeroSection'; | ||
| import FigmaShowcase from '@site/src/components/FigmaShowcase'; | ||
| import VisualValidation from '@site/src/components/VisualValidation'; |
There was a problem hiding this 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.
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.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a24245d22c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
docs/src/pages/index.tsx
Outdated
| import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; | ||
| import Layout from '@theme/Layout'; | ||
| import HeroSection from '@site/src/components/HeroSection'; | ||
| import FigmaShowcase from '@site/src/components/FigmaShowcase'; |
There was a problem hiding this comment.
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 👍 / 👎.
| /> | ||
| </Link> | ||
| {[ | ||
| { id: 'figma' as const, to: '/docs/cli/figma', src: '/img/figma-logo.svg', alt: 'Figma' }, |
There was a problem hiding this comment.
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 👍 / 👎.
The index.tsx referenced FigmaShowcase, VisualValidation, and AgentEcosystem components that were never created. Restored the original ClientShowcase and LLMProviders components that exist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Summary
Test plan
pnpm buildin docs/ passes🤖 Generated with Claude Code