Skip to content

feat: add mcp page#7687

Open
AmanVarshney01 wants to merge 9 commits intomainfrom
dr-7669-mcp-2026
Open

feat: add mcp page#7687
AmanVarshney01 wants to merge 9 commits intomainfrom
dr-7669-mcp-2026

Conversation

@AmanVarshney01
Copy link
Member

@AmanVarshney01 AmanVarshney01 commented Mar 21, 2026

Summary by CodeRabbit

  • New Features

    • Added a Prisma MCP Server page with hero, CTA, agents showcase, capability cards, prompt bubbles, typed-text effect, and an embedded demo video for improved MCP discovery/onboarding.
  • Style

    • Added a blinking cursor animation and class for typed text; adjusted a display font weight.
  • Chores

    • Standardized Tailwind/global stylesheet input paths across apps to unify build-time stylesheet resolution.

@vercel
Copy link

vercel bot commented Mar 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Mar 25, 2026 5:11pm
docs Ready Ready Preview, Comment Mar 25, 2026 5:11pm
eclipse Ready Ready Preview, Comment Mar 25, 2026 5:11pm
site Ready Ready Preview, Comment Mar 25, 2026 5:11pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new MCP marketing page with multiple React UI components and types to the site app; updates several apps' Shadcn/Tailwind CSS input paths and one Eclipse Tailwind field; adjusts a shared UI global CSS font weight; and adds typing/cursor CSS and animation.

Changes

Cohort / File(s) Summary
Shadcn/Tailwind configs (point to shared globals)
apps/blog/components.json, apps/docs/components.json, apps/site/components.json
Repoint Tailwind CSS input from app-local src/app/global.css to shared ../../packages/ui/src/styles/globals.css.
Eclipse Tailwind config
apps/eclipse/components.json
Cleared tailwind.config (set to "") and changed Tailwind CSS input from src/styles/globals.css to src/app/global.css.
MCP components (site app)
apps/site/src/app/mcp/_components/agent-card.tsx, apps/site/src/app/mcp/_components/capability-cards.tsx, apps/site/src/app/mcp/_components/mcp-agents-section.tsx, apps/site/src/app/mcp/_components/mcp-bubble.tsx, apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx, apps/site/src/app/mcp/_components/mcp-cta-section.tsx, apps/site/src/app/mcp/_components/mcp-hero-section.tsx, apps/site/src/app/mcp/_components/mcp-video-section.tsx, apps/site/src/app/mcp/_components/mcp-type-text.tsx
Added multiple new React/TSX components and exported types for MCP marketing: agent cards, capability cards, bubble UI (with SVG tails), prompt bubbles, hero/video/CTA sections, agents/capabilities sections, and a typed-text component.
MCP page route (site app)
apps/site/src/app/mcp/page.tsx
Added new Next.js App Router page composing the MCP sections, exporting route metadata and static data arrays for features, agents, and capabilities.
Site global CSS (typing cursor)
apps/site/src/app/global.css
Added @keyframes mcp-cursor-blink and .mcp-type-cursor animation class for typing cursor behavior.
Shared UI globals (font weight tweak)
packages/ui/src/styles/globals.css
Adjusted .stretch-display font-variation-settings: changed "wght" from 700 to 900 (keeps "wdth" 125).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add mcp page' directly and accurately summarizes the main change: a new MCP page component has been added to the application.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@argos-ci
Copy link

argos-ci bot commented Mar 21, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Mar 25, 2026, 5:09 PM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
apps/site/src/app/mcp/_components/mcp-bubble.tsx (1)

63-69: Minor cleanup: remove duplicate utility tokens in shell config strings.

Line 63 and Line 69 repeat py-2; trimming duplicates makes these variant definitions easier to maintain.

Suggested cleanup
   "prompt-wide": {
     fill: fillTeal,
     monoPrompt: true,
     shell:
-      "items-center rounded-[10px] border border-stroke-ppg px-3.5 py-2 shadow-none sm:px-4 min-h-[41px] py-2 md:min-h-[45px]",
+      "items-center rounded-[10px] border border-stroke-ppg px-3.5 py-2 shadow-none sm:px-4 min-h-[41px] md:min-h-[45px]",
   },
   "prompt-compact": {
     fill: fillTeal,
     monoPrompt: true,
     shell:
-      "items-center rounded-[10px] border border-stroke-ppg px-3.5 py-2 shadow-none sm:px-4 min-h-[44px] py-2 md:min-h-[50px]",
+      "items-center rounded-[10px] border border-stroke-ppg px-3.5 py-2 shadow-none sm:px-4 min-h-[44px] md:min-h-[50px]",
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-bubble.tsx` around lines 63 - 69, The
shell variant strings contain duplicate utility tokens ("py-2")—update the
"shell" value in both the default variant and the "prompt-compact" variant
(referencing the "shell" keys inside the component config and the
"prompt-compact" object) to remove the repeated "py-2" so each utility class
appears only once; ensure you keep the rest of the classes (e.g.,
"items-center", "rounded-[10px]", "border-stroke-ppg", "px-3.5", "min-h-[...]")
intact and preserve the "fill: fillTeal" and "monoPrompt: true" properties for
"prompt-compact".
apps/site/src/app/mcp/_components/mcp-video-section.tsx (1)

6-13: Consider privacy/performance hardening for the iframe embed.

Line 8 currently uses standard YouTube embed; switching to youtube-nocookie.com and adding loading="lazy" reduces early third-party tracking/cost.

Suggested update
           <iframe
             className="size-full"
-            src="https://www.youtube.com/embed/jFm41OPnOUc"
+            src="https://www.youtube-nocookie.com/embed/jFm41OPnOUc"
             title="Prisma MCP video"
+            loading="lazy"
             allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
             referrerPolicy="strict-origin-when-cross-origin"
             allowFullScreen
           />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-video-section.tsx` around lines 6 - 13,
Update the iframe in the mcp-video-section component to use the privacy-enhanced
YouTube domain and lazy loading: change the src from
"https://www.youtube.com/embed/jFm41OPnOUc" to
"https://www.youtube-nocookie.com/embed/jFm41OPnOUc" and add loading="lazy" to
the <iframe> element (keep existing attributes like title, referrerPolicy, and
allowFullScreen intact).
apps/site/src/app/mcp/_components/mcp-cta-section.tsx (1)

33-56: Optional: split CTA destinations instead of reusing one URL.

Lines 33-56 wire both “Add MCP server” and “Read Docs” to docsHref. Consider separate props (e.g., setupHref + docsHref) so each CTA can point to the most specific target and be tracked independently.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-cta-section.tsx` around lines 33 - 56,
The two CTAs currently both use docsHref; change the component API to accept a
separate setupHref (or setupUrl) prop and use that for the “Add MCP server”
anchor while leaving docsHref for “Read Docs”; update the component
props/interface (e.g., the MCP CTA component in mcp-cta-section.tsx), replace
the first anchor's href to setupHref (falling back to docsHref if undefined),
and update any call sites/tests to pass a setupHref where appropriate so
tracking and destinations are independent.
apps/site/src/app/mcp/_components/capability-cards.tsx (1)

17-40: Consider extracting a shared card shell to remove duplication.

Both components repeat nearly identical container/header/description markup; extracting a shared internal primitive would reduce drift risk when styles evolve.

Also applies to: 60-81

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/capability-cards.tsx` around lines 17 - 40,
The container/header/description layout is duplicated—extract a shared internal
primitive (e.g., CapabilityCardShell or CardShell) that accepts props: icon,
title, description, prompt (or children), and mobileTall; move the repeated JSX
(outer div with className, inner header block with icon and h4, description
paragraph, and the bottom McpBubble wrapper) into that component, preserve the
exact className strings and aria-hidden on the icon, and then refactor the two
places (the current capability-cards rendering and the other block at lines
60-81) to render this new primitive, passing through mobileTall to choose the
height variant and the prompt content to the McpBubble.
apps/site/src/app/mcp/_components/mcp-hero-section.tsx (1)

5-10: Use a stable id for feature keys instead of mutable text.

On line 60 and line 112, key={line1} ties component identity to text that could change. React keys should be stable and unique—when UI text becomes a key, any change to that text breaks component state preservation. Add an explicit id field to McpHeroFeature and key by that instead.

♻️ Suggested update
 export type McpHeroFeature = {
+  id: string;
   icon: LucideIcon;
   line1: string;
   line2: string;
   mobileText?: string;
 };
@@
-              <div key={feature.line1} className="flex items-center gap-4 text-left">
+              <div key={feature.id} className="flex items-center gap-4 text-left">
@@
-            <div key={line1} className="flex items-center gap-4 text-left">
+            <div key={id} className="flex items-center gap-4 text-left">

Update the features array in page.tsx to include id values for each feature:

 const heroFeatures: McpHeroFeature[] = [
   {
+    id: "natural-language",
     icon: MessagesSquare,
     line1: "Natural language",
     line2: "database operations",
     mobileText: "Natural language db operations",
   },
   { 
+    id: "works-any-agent",
     icon: Rocket, 
     line1: "Works with any", 
     line2: "AI agent" 
   },
   { 
+    id: "quick-setup",
     icon: Zap, 
     line1: "Super quick", 
     line2: "2-minute setup" 
   },
   { 
+    id: "enterprise-security",
     icon: Lock, 
     line1: "Enterprise-grade", 
     line2: "security & OAuth" 
   },
 ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-hero-section.tsx` around lines 5 - 10,
The McpHeroFeature type and the render that uses key={line1} must use a stable
unique id: add an id: string field to the McpHeroFeature type, update the
features data (where the features array is created, e.g., in page.tsx) to
include stable id values for each feature, and change the component render to
use key={feature.id} (or feature.id as the key) instead of key={line1}; update
any places that destructure McpHeroFeature (e.g., mapping callback parameters)
to accept the id as well so type-checking passes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/site/src/app/mcp/_components/capability-cards.tsx`:
- Around line 17-40: The container/header/description layout is
duplicated—extract a shared internal primitive (e.g., CapabilityCardShell or
CardShell) that accepts props: icon, title, description, prompt (or children),
and mobileTall; move the repeated JSX (outer div with className, inner header
block with icon and h4, description paragraph, and the bottom McpBubble wrapper)
into that component, preserve the exact className strings and aria-hidden on the
icon, and then refactor the two places (the current capability-cards rendering
and the other block at lines 60-81) to render this new primitive, passing
through mobileTall to choose the height variant and the prompt content to the
McpBubble.

In `@apps/site/src/app/mcp/_components/mcp-bubble.tsx`:
- Around line 63-69: The shell variant strings contain duplicate utility tokens
("py-2")—update the "shell" value in both the default variant and the
"prompt-compact" variant (referencing the "shell" keys inside the component
config and the "prompt-compact" object) to remove the repeated "py-2" so each
utility class appears only once; ensure you keep the rest of the classes (e.g.,
"items-center", "rounded-[10px]", "border-stroke-ppg", "px-3.5", "min-h-[...]")
intact and preserve the "fill: fillTeal" and "monoPrompt: true" properties for
"prompt-compact".

In `@apps/site/src/app/mcp/_components/mcp-cta-section.tsx`:
- Around line 33-56: The two CTAs currently both use docsHref; change the
component API to accept a separate setupHref (or setupUrl) prop and use that for
the “Add MCP server” anchor while leaving docsHref for “Read Docs”; update the
component props/interface (e.g., the MCP CTA component in mcp-cta-section.tsx),
replace the first anchor's href to setupHref (falling back to docsHref if
undefined), and update any call sites/tests to pass a setupHref where
appropriate so tracking and destinations are independent.

In `@apps/site/src/app/mcp/_components/mcp-hero-section.tsx`:
- Around line 5-10: The McpHeroFeature type and the render that uses key={line1}
must use a stable unique id: add an id: string field to the McpHeroFeature type,
update the features data (where the features array is created, e.g., in
page.tsx) to include stable id values for each feature, and change the component
render to use key={feature.id} (or feature.id as the key) instead of
key={line1}; update any places that destructure McpHeroFeature (e.g., mapping
callback parameters) to accept the id as well so type-checking passes.

In `@apps/site/src/app/mcp/_components/mcp-video-section.tsx`:
- Around line 6-13: Update the iframe in the mcp-video-section component to use
the privacy-enhanced YouTube domain and lazy loading: change the src from
"https://www.youtube.com/embed/jFm41OPnOUc" to
"https://www.youtube-nocookie.com/embed/jFm41OPnOUc" and add loading="lazy" to
the <iframe> element (keep existing attributes like title, referrerPolicy, and
allowFullScreen intact).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2088231c-2575-49b3-9a94-9b4bb392be20

📥 Commits

Reviewing files that changed from the base of the PR and between 1a02c1b and 400a1f4.

📒 Files selected for processing (14)
  • apps/blog/components.json
  • apps/docs/components.json
  • apps/eclipse/components.json
  • apps/site/components.json
  • apps/site/src/app/mcp/_components/agent-card.tsx
  • apps/site/src/app/mcp/_components/capability-cards.tsx
  • apps/site/src/app/mcp/_components/index.ts
  • apps/site/src/app/mcp/_components/mcp-agents-section.tsx
  • apps/site/src/app/mcp/_components/mcp-bubble.tsx
  • apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx
  • apps/site/src/app/mcp/_components/mcp-cta-section.tsx
  • apps/site/src/app/mcp/_components/mcp-hero-section.tsx
  • apps/site/src/app/mcp/_components/mcp-video-section.tsx
  • apps/site/src/app/mcp/page.tsx

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx (1)

10-10: Align mobileTall typing with CapabilityCard defaulting behavior.

Line 10 requires mobileTall, but the child component treats it as optional with a default of false. Making it optional here keeps contracts aligned and reduces data boilerplate.

Suggested patch
-  mobileTall: boolean;
+  mobileTall?: boolean;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx` at line 10,
The props type for the parent component currently requires mobileTall but the
child CapabilityCard treats mobileTall as optional (defaults to false); update
the props/interface in mcp-capabilities-section (the declaration that includes
mobileTall) to make mobileTall optional (mobileTall?: boolean) so it matches
CapabilityCard's defaulting behavior and avoids unnecessary required data
plumbing.
apps/site/src/app/mcp/_components/mcp-bubble.tsx (2)

18-24: Remove the unused monoPrompt field from bubble configuration.

monoPrompt is defined in BubbleConfig and set for every variant, but never read. It adds dead surface and implies behavior that doesn’t exist.

Proposed cleanup
 type BubbleConfig = {
   shell: string;
   fill: string;
   stroke: string;
-  monoPrompt: boolean;
   tailSide: "left" | "right";
 };
@@
   "hero-desktop-title": {
     fill: fillTitle,
     stroke: strokeTeal,
-    monoPrompt: false,
     tailSide: "right",
@@
   "hero-desktop-description": {
     fill: fillTeal,
     stroke: strokeTeal,
-    monoPrompt: false,
     tailSide: "left",
@@
   "hero-mobile-title": {
     fill: fillTitle,
     stroke: strokeTeal,
-    monoPrompt: false,
     tailSide: "right",
@@
   "hero-mobile-description": {
     fill: fillTeal,
     stroke: strokeTeal,
-    monoPrompt: false,
     tailSide: "left",

Also applies to: 26-55

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-bubble.tsx` around lines 18 - 24, The
BubbleConfig type contains an unused field monoPrompt; remove monoPrompt from
the BubbleConfig definition and from all bubble variant objects where it is
being set (look for the BubbleConfig type and the variants/instances that assign
monoPrompt in this file, e.g., the variant objects around lines 26-55). After
removing those assignments, run a quick search in this component for any
references to monoPrompt and delete or refactor them if found so the code
compiles without dead fields.

114-116: Consider narrowing prompt children to plain text.

Line 123 renders children inside <code>, but children is typed as ReactNode. If this bubble is text-only by design, using string is safer and clearer.

Type-tightening option
 export function McpPromptBubble({
   variant,
   children,
 }: {
   variant: McpPromptBubbleVariant;
-  children: ReactNode;
+  children: string;
 }) {

Also applies to: 123-123

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-bubble.tsx` around lines 114 - 116, The
children prop for the prompt bubble is currently typed as ReactNode but is
rendered inside <code>, so tighten the prop to string to enforce plain-text
prompts: update the component signature in mcp-bubble.tsx (the children prop)
from ReactNode to string, adjust any internal usages assuming a string, and
update callers that pass non-string children to pass a string (e.g., use
.toString() or extract text). Keep the rest of the component (rendering inside
<code>) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx`:
- Line 28: The CapabilityCard list uses cap.title as the React key which can
collide; replace it with a stable unique identifier (e.g., cap.id) when
rendering in the map inside mcp-capabilities-section.tsx so reconciliation is
reliable—find the map that returns <CapabilityCard key={cap.title} {...cap}
size={size} /> and change the key to a guaranteed unique property (cap.id) or
fall back to a stable generated id on the capability object if id is absent.

In `@apps/site/src/app/mcp/_components/mcp-hero-section.tsx`:
- Around line 7-12: The feature card list is keyed by a non-unique field
(line1); add a stable unique id to the McpHeroFeature type and populate it for
each feature, then update the component that renders the feature cards (the map
rendering that currently keys by line1) to use that id as the React key;
reference the McpHeroFeature type and the feature-rendering map (where keys are
currently line1) when making the change so all usages and tests are updated to
supply the new id.

---

Nitpick comments:
In `@apps/site/src/app/mcp/_components/mcp-bubble.tsx`:
- Around line 18-24: The BubbleConfig type contains an unused field monoPrompt;
remove monoPrompt from the BubbleConfig definition and from all bubble variant
objects where it is being set (look for the BubbleConfig type and the
variants/instances that assign monoPrompt in this file, e.g., the variant
objects around lines 26-55). After removing those assignments, run a quick
search in this component for any references to monoPrompt and delete or refactor
them if found so the code compiles without dead fields.
- Around line 114-116: The children prop for the prompt bubble is currently
typed as ReactNode but is rendered inside <code>, so tighten the prop to string
to enforce plain-text prompts: update the component signature in mcp-bubble.tsx
(the children prop) from ReactNode to string, adjust any internal usages
assuming a string, and update callers that pass non-string children to pass a
string (e.g., use .toString() or extract text). Keep the rest of the component
(rendering inside <code>) unchanged.

In `@apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx`:
- Line 10: The props type for the parent component currently requires mobileTall
but the child CapabilityCard treats mobileTall as optional (defaults to false);
update the props/interface in mcp-capabilities-section (the declaration that
includes mobileTall) to make mobileTall optional (mobileTall?: boolean) so it
matches CapabilityCard's defaulting behavior and avoids unnecessary required
data plumbing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1fa1d07a-f780-4bbe-93d1-196c987d8b57

📥 Commits

Reviewing files that changed from the base of the PR and between ee727bf and 61d8a12.

📒 Files selected for processing (6)
  • apps/site/src/app/mcp/_components/capability-cards.tsx
  • apps/site/src/app/mcp/_components/mcp-agents-section.tsx
  • apps/site/src/app/mcp/_components/mcp-bubble.tsx
  • apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx
  • apps/site/src/app/mcp/_components/mcp-hero-section.tsx
  • apps/site/src/app/mcp/page.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/site/src/app/mcp/_components/mcp-agents-section.tsx
  • apps/site/src/app/mcp/page.tsx
  • apps/site/src/app/mcp/_components/capability-cards.tsx

<div className="mx-auto mt-6 grid max-w-[368px] grid-cols-1 gap-4 sm:max-w-none sm:grid-cols-2 xl:max-w-[1200px] xl:grid-cols-6 xl:gap-[16px]">
{capabilities.map((cap, index) => {
const size = index < 2 ? "wide" : "compact";
return <CapabilityCard key={cap.title} {...cap} size={size} />;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a stable unique key for card mapping.

Line 28 uses cap.title as the React key. If two capabilities share a title, reconciliation can become unstable. Prefer a guaranteed-unique stable identifier (e.g., id).

Suggested patch
 export type McpCapability = {
+  id: string;
   icon: LucideIcon;
   title: string;
   description: string;
   prompt: string;
   mobileTall: boolean;
 };
@@
-            return <CapabilityCard key={cap.title} {...cap} size={size} />;
+            return <CapabilityCard key={cap.id} {...cap} size={size} />;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx` at line 28,
The CapabilityCard list uses cap.title as the React key which can collide;
replace it with a stable unique identifier (e.g., cap.id) when rendering in the
map inside mcp-capabilities-section.tsx so reconciliation is reliable—find the
map that returns <CapabilityCard key={cap.title} {...cap} size={size} /> and
change the key to a guaranteed unique property (cap.id) or fall back to a stable
generated id on the capability object if id is absent.

Comment on lines +7 to +12
export type McpHeroFeature = {
icon: LucideIcon;
line1: string;
line2: string;
mobileText?: string;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a stable unique key for feature cards.

Line 75 keys by line1, which is not guaranteed unique. Duplicate values can cause subtle UI reconciliation bugs. Add an explicit id to McpHeroFeature and key by it.

Suggested change
 export type McpHeroFeature = {
+  id: string;
   icon: LucideIcon;
   line1: string;
   line2: string;
   mobileText?: string;
 };
@@
-          {features.map(({ icon: FeatureIcon, line1, line2, mobileText }) => (
-            <div key={line1} className="flex items-center gap-4 text-left">
+          {features.map(({ id, icon: FeatureIcon, line1, line2, mobileText }) => (
+            <div key={id} className="flex items-center gap-4 text-left">

Also applies to: 74-76

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-hero-section.tsx` around lines 7 - 12,
The feature card list is keyed by a non-unique field (line1); add a stable
unique id to the McpHeroFeature type and populate it for each feature, then
update the component that renders the feature cards (the map rendering that
currently keys by line1) to use that id as the React key; reference the
McpHeroFeature type and the feature-rendering map (where keys are currently
line1) when making the change so all usages and tests are updated to supply the
new id.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/site/src/app/mcp/_components/mcp-type-text.tsx`:
- Around line 7-8: Add defensive validation for the optional props speed and
delay in the mcp-type-text component: ensure speed and delay are finite numbers
and non-negative (use Number.isFinite(value) && value >= 0) and fall back to
defaults (speed = 20, delay = 0) before any setTimeout or interval usage; also
short-circuit early if text is empty (if (!text) return) to avoid starting
timers, and ensure any timer created with setTimeout is cleared on cleanup to
prevent unexpected rapid updates when invalid values are passed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 48b3457b-7b5f-4645-a60b-d2a2fa081afc

📥 Commits

Reviewing files that changed from the base of the PR and between 9c86ae3 and 807de09.

⛔ Files ignored due to path filters (7)
  • apps/site/public/mcp/logos/chatgpt.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/claude-code.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/cursor.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/gemini.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/vscode.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/warp.svg is excluded by !**/*.svg
  • apps/site/public/mcp/logos/windsurf.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • apps/site/src/app/global.css
  • apps/site/src/app/mcp/_components/agent-card.tsx
  • apps/site/src/app/mcp/_components/capability-cards.tsx
  • apps/site/src/app/mcp/_components/mcp-agents-section.tsx
  • apps/site/src/app/mcp/_components/mcp-bubble.tsx
  • apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx
  • apps/site/src/app/mcp/_components/mcp-cta-section.tsx
  • apps/site/src/app/mcp/_components/mcp-hero-section.tsx
  • apps/site/src/app/mcp/_components/mcp-type-text.tsx
  • apps/site/src/app/mcp/page.tsx
  • packages/ui/src/styles/globals.css
✅ Files skipped from review due to trivial changes (2)
  • packages/ui/src/styles/globals.css
  • apps/site/src/app/mcp/_components/mcp-hero-section.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/site/src/app/global.css
  • apps/site/src/app/mcp/_components/mcp-cta-section.tsx
  • apps/site/src/app/mcp/_components/agent-card.tsx
  • apps/site/src/app/mcp/_components/mcp-capabilities-section.tsx
  • apps/site/src/app/mcp/_components/capability-cards.tsx
  • apps/site/src/app/mcp/_components/mcp-bubble.tsx
  • apps/site/src/app/mcp/_components/mcp-agents-section.tsx

Comment on lines +7 to +8
speed = 20,
delay = 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current call-sites and passed timing props for McpTypeText.
# Expectation: speed > 0 and delay >= 0 (or omitted defaults).
rg -nP --type=tsx -C2 '<McpTypeText\b|speed\s*=|delay\s*='

Repository: prisma/web

Length of output: 81


🏁 Script executed:

#!/bin/bash
# Find and inspect the McpTypeText component
find . -name "mcp-type-text.tsx" -o -name "*mcp-type-text*"

Repository: prisma/web

Length of output: 107


🏁 Script executed:

#!/bin/bash
# Search for McpTypeText usage across the codebase
# Using rg without the problematic --type=tsx flag
rg -l "McpTypeText" --max-count=20

Repository: prisma/web

Length of output: 160


🏁 Script executed:

#!/bin/bash
# Also search for the component file with a broader pattern
fd "mcp-type-text" . -type f

Repository: prisma/web

Length of output: 224


🏁 Script executed:

cat -n apps/site/src/app/mcp/_components/mcp-type-text.tsx

Repository: prisma/web

Length of output: 1257


🏁 Script executed:

# Search for all usages of McpTypeText in the codebase
rg "McpTypeText" -B 2 -A 5

Repository: prisma/web

Length of output: 4603


🏁 Script executed:

cat -n apps/site/src/app/mcp/_components/mcp-hero-section.tsx

Repository: prisma/web

Length of output: 5761


Add defensive guards for speed and delay to prevent unexpected timer behavior.

The function accepts speed?: number and delay?: number without validation. If invalid values (NaN, Infinity, or negative numbers) are passed, setTimeout coerces them unpredictably—negative delays become 0, creating rapid update bursts. While current usages pass safe positive values, defensive checks ensure robustness as the component evolves.

The proposed fix with Number.isFinite() guards and fallback defaults is sound. Also consider the empty text guard (if (!text) return) to avoid unnecessary timer setup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/mcp/_components/mcp-type-text.tsx` around lines 7 - 8, Add
defensive validation for the optional props speed and delay in the mcp-type-text
component: ensure speed and delay are finite numbers and non-negative (use
Number.isFinite(value) && value >= 0) and fall back to defaults (speed = 20,
delay = 0) before any setTimeout or interval usage; also short-circuit early if
text is empty (if (!text) return) to avoid starting timers, and ensure any timer
created with setTimeout is cleared on cleanup to prevent unexpected rapid
updates when invalid values are passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant