Skip to content

Conversation

iNerdStack
Copy link
Contributor

@iNerdStack iNerdStack commented Jun 9, 2025

Description

This PR introduces import from Figma using MCP, it connects with Figma desktop SSE service.
Adds new context option for import from figma in AI chat

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Release
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes


Important

Introduces Figma import feature using MCP, adding new components, context management, and documentation updates.

  • Behavior:
    • Adds FigmaInput component in action-buttons.tsx for importing Figma designs.
    • Connects to Figma desktop SSE service via figmaRouter in routers/figma.ts.
    • Supports link-based and selection-based imports.
  • Context Management:
    • Adds FigmaMessageContext to context.ts for managing Figma design data.
    • Updates getHydratedUserMessage() in provider.ts to include Figma context.
  • Icons:
    • Adds FigmaLogo icon to icons/index.tsx.
  • Documentation:
    • Updates figma-to-onlook/index.mdx and features/index.mdx to include Figma import instructions.

This description was created by Ellipsis for dec7bcc. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • New Features

    • Import Figma designs into chat via URL, current selection, or clipboard; add and remove Figma design contexts shown as context pills.
  • Backend

    • New resilient Figma service and API to fetch design assets, code, variables, extract node IDs, and report connection health.
  • UI/Style

    • “Add Figma Design” action and updated tooltip, loading states, success/error toasts, and new Figma icons.
  • Documentation

    • Reworked tutorial covering Figma import workflow, prerequisites, steps, FAQs, and troubleshooting.

Copy link

vercel bot commented Jun 9, 2025

@iNerdStack is attempting to deploy a commit to the Onlook Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Caution

Changes requested ❌

Reviewed everything up to 871408c in 3 minutes and 12 seconds. Click for details.
  • Reviewed 1023 lines of code in 10 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx:139
  • Draft comment:
    The clipboard URL validation uses a simple 'includes("figma.com")' check; consider using a more robust URL validation or proper URL parsing to ensure the pasted value is a valid Figma URL.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The simple check is just for the clipboard paste feature. The actual URL validation will happen server-side when the URL is used. The clipboard check is just a UX feature to give immediate feedback. A more complex validation here would be unnecessary since the real validation happens later. The current approach is reasonable for this use case. The comment has a point that the validation could be more robust. Malicious URLs containing "figma.com" somewhere could potentially pass this check. The risk is very low since this is just initial feedback - the actual URL will be validated server-side before any real processing happens. The simple check is appropriate for this UX-focused clipboard feature. The comment should be deleted. The simple URL check is appropriate for this UX feature since proper validation happens server-side. Making it more complex would be overengineering.
2. apps/web/client/src/server/api/routers/figma.ts:177
  • Draft comment:
    Similarly, in waitForMCPResponse, using an AbortController for the SSE fetch could improve cancellation and timeout handling.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% The current implementation already has a working timeout mechanism with cleanup. While AbortController could provide a more modern way to handle cancellation, the existing solution with reader.cancel() is functionally complete and clear. The suggestion is more of a style preference than a critical improvement. The current code handles both timeout and cleanup effectively. AbortController is indeed a more modern API that could simplify the code slightly. The current implementation could potentially leak resources if cleanup isn't called in all edge cases. The current implementation already has thorough cleanup handling in all code paths - normal completion, timeout, and error cases. The benefit of switching to AbortController would be minimal. While using AbortController is a valid suggestion, the current implementation is already robust and clear. The suggested change would be more of a style refactor than a meaningful improvement.

Workflow ID: wflow_EQdWNpPe84awAH5g

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@drfarrell drfarrell requested a review from Kitenite June 15, 2025 01:08
@iNerdStack iNerdStack closed this Jul 19, 2025
@iNerdStack iNerdStack deleted the figma-mcp branch July 19, 2025 17:19
@iNerdStack iNerdStack restored the figma-mcp branch July 20, 2025 08:20
@iNerdStack iNerdStack reopened this Jul 20, 2025
Copy link

coderabbitai bot commented Aug 16, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds end-to-end Figma import: UI action and modal, new Figma message context and icons, chat-context add/remove APIs, TRPC figma router with an MCP SSE + JSON-RPC client, API wiring, prompt/hydration support, and updated docs for the import workflow.

Changes

Cohort / File(s) Summary of Changes
Chat Input UI
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx, apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx
Adds "Add Figma Design" dropdown item and new FigmaInput component. FigmaInput supports URL, selection, and clipboard flows, uses TRPC calls, loading states, toasts, and can be controlled externally or internally.
Context Pills UI
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/context-pills/helpers.tsx
Adds handling for MessageContextType.FIGMA in truncation fallback and maps it to a Figma icon for rendering.
Chat Context Store
apps/web/client/src/components/store/editor/chat/context.ts
Adds Figma contexts support, public addFigmaContext / removeFigmaContext methods, deduplication by nodeId, inserts figma contexts into context composition, and makes image context retrieval synchronous.
Server API: Figma Router & Index/Root
apps/web/client/src/server/api/routers/figma.ts, apps/web/client/src/server/api/routers/index.ts, apps/web/client/src/server/api/root.ts
New figmaRouter exposing endpoints (getDesignFromUrl, getCurrentSelection, checkConnection, extractNodeId, getHealthStatus). Implements ServerSideFigmaMCP with SSE session maintenance, JSON-RPC over HTTP, request tracking/timeouts, helper methods (getCode/getImage/getVariableDefs), and wires router into appRouter; re-exports router.
Models: Message Context Types
packages/models/src/chat/message/context.ts
Adds MessageContextType.FIGMA, defines FigmaMessageContext type, and extends the MessageContext union to include Figma contexts.
UI Icons
packages/ui/src/components/icons/index.tsx
Adds Figma icon exports: Figma (alias to external icon) and inline FigmaLogo SVG component.
AI Prompt Contexts
packages/ai/src/prompt/context.ts, packages/ai/src/prompt/provider.ts
Adds figmaContentPrefix to CONTEXT_PROMPTS. Hydration collects FigmaMessageContext items and appends a dedicated figma-context block via new getFigmaContent helper; adapts prompt assembly to include Figma content.
Docs
docs/content/docs/tutorials/figma-to-onlook.mdx
Rewrites tutorial to cover importing Figma designs: prerequisites, connection/setup, selection vs URL workflows, FAQs, and updated images and guidance.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant WC as Web Client (Chat UI)
  participant TRPC as TRPC figma.getDesignFromUrl
  participant MCP as Figma MCP (SSE + HTTP)
  participant Ctx as ChatContext

  U->>WC: Click "Add Figma Design" (URL)
  WC->>TRPC: getDesignFromUrl(figmaUrl)
  TRPC->>MCP: ensure session + JSON-RPC calls (code/image/vars)
  MCP-->>TRPC: aggregated design data
  TRPC-->>WC: {success, data, nodeId}
  WC->>Ctx: addFigmaContext(figmaUrl, nodeId, displayName, content)
  Ctx-->>WC: context updated
  WC-->>U: Success toast, modal closes
Loading
sequenceDiagram
  participant U as User
  participant WC as Web Client (Chat UI)
  participant TRPC as TRPC figma.getCurrentSelection
  participant MCP as Figma MCP
  participant Ctx as ChatContext

  U->>WC: Click "Add Selected Frame from Figma"
  WC->>TRPC: getCurrentSelection()
  TRPC->>MCP: JSON-RPC calls (code/image/vars)
  MCP-->>TRPC: selection design data
  TRPC-->>WC: {success, data}
  WC->>Ctx: addFigmaContext(figma://selection/..., nodeId, displayName, content)
  Ctx-->>WC: context updated
  WC-->>U: Success toast, modal closes
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~110 minutes

Poem

I hop through frames and URL strings bright,
I listen to SSE through the night.
I paste, I fetch, I stitch code and scheme,
Designs become components—what a dream!
Carrots, canvases, and MCP delight. 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 61cff8a and adb53b7.

📒 Files selected for processing (2)
  • apps/web/client/src/server/api/routers/figma.ts (1 hunks)
  • packages/ai/src/prompt/context.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/client/src/server/api/routers/figma.ts
  • packages/ai/src/prompt/context.ts
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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: 9

♻️ Duplicate comments (3)
packages/ui/src/components/icons/index.tsx (1)

3505-3517: Great: inline FigmaLogo uses currentColor (past remark addressed)

The inline FigmaLogo uses fill="currentColor", resolving the prior suggestion to avoid hard-coded white. Naming and sizing are consistent with the rest of the set.

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1)

12-25: Good upgrade: explicit types for Figma data replace any

Defining FigmaNode and FigmaDesignData addresses prior feedback about avoiding any. Improves safety in buildDesignContent and handlers.

apps/web/client/src/server/api/routers/figma.ts (1)

197-221: Consider aborting JSON-RPC POSTs on timeout to free sockets

Currently the pending promise times out, but the underlying fetch may still hang until the OS/network times out. Add an AbortController with a matching timeout.

     private async sendJSONRPCOverHTTP(request: any): Promise<void> {
         if (!this.sessionId) {
             throw new Error('No session ID available');
         }
 
         const endpoint = `${this.MCP_BASE_URL}/messages?sessionId=${this.sessionId}`;
         
         try {
-            const response = await fetch(endpoint, {
+            const controller = new AbortController();
+            const timer = setTimeout(() => controller.abort(), 30000); // align with pendingRequests timeout
+            const response = await fetch(endpoint, {
                 method: 'POST',
                 headers: {
                     'Content-Type': 'application/json',
                 },
-                body: JSON.stringify(request)
+                body: JSON.stringify(request),
+                signal: controller.signal,
             });
+            clearTimeout(timer);
 
             if (!response.ok) {
                 const responseText = await response.text();
                 throw new Error(`HTTP request failed: ${response.status} ${response.statusText} - ${responseText}`);
             }
         } catch (error) {
             console.error('Figma MCP: Failed to send JSON-RPC:', error);
             throw error;
         }
     }
🧹 Nitpick comments (5)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/context-pills/helpers.tsx (1)

34-36: Unnecessary type cast on icon

Icons.FigmaLogo is already a React component; the explicit as React.ComponentType cast is redundant. Removing it simplifies the code.

Apply this diff:

-        case MessageContextType.FIGMA:
-            icon = Icons.FigmaLogo as React.ComponentType;
-            break;
+        case MessageContextType.FIGMA:
+            icon = Icons.FigmaLogo;
+            break;
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx (1)

44-61: Add an aria-label to the icon-only trigger for accessibility

Screen readers won’t get context from an icon-only button. Tooltip content isn’t a substitute for accessible names.

Apply this minimal change to provide an accessible name:

-                            <Button
+                            <Button
                                 variant={'ghost'}
                                 size={'icon'}
                                 className="w-9 h-9 text-foreground-tertiary group hover:bg-transparent cursor-pointer"
                                 disabled={disabled}
+                                aria-label={disabled ? 'Select an element to start' : 'Add Image, Screenshot, or Figma Design'}
                                 onMouseDown={(e) => {
                                     e.currentTarget.blur();
                                 }}
                             >
apps/web/client/src/components/store/editor/chat/context.ts (1)

251-253: Consider clearing FIGMA contexts in clearAttachments for consistency

If “attachments” now include Figma designs, clearAttachments should also remove FIGMA entries to match user expectations.

Suggested update (outside the changed hunk):

clearAttachments() {
  this.context = this.context.filter(
    (context) =>
      context.type !== MessageContextType.IMAGE &&
      context.type !== MessageContextType.FIGMA
  );
}
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1)

204-211: Enable Enter to submit the URL

Small UX boost: let users press Enter in the URL input to trigger “Add from URL.”

                                 <Input
                                     id="figma-url"
                                     placeholder="https://www.figma.com/file/..."
                                     value={figmaUrl}
                                     onChange={(e) => setFigmaUrl(e.target.value)}
+                                    onKeyDown={(e) => {
+                                        if (e.key === 'Enter' && figmaUrl.trim() && !isLoading) {
+                                            e.preventDefault();
+                                            handleAddFigmaUrl();
+                                        }
+                                    }}
                                     className="text-xs"
                                 />
apps/web/client/src/server/api/routers/figma.ts (1)

90-121: Refresh session liveness on any SSE message, not only on sessionId reception

isSessionValid hinges on lastConnectionTime; updating it only when the sessionId first appears risks invalidation during long-running sessions. Touch it on every valid data event.

                 if (line.startsWith('data: ')) {
                     const eventData = line.substring(6).trim();
                     
                     // Checks if this is session establishment
                     if (eventData.includes('sessionId=')) {
                         const sessionMatch = /sessionId=([^&]+)/.exec(eventData);
                         if (sessionMatch?.[1]) {
                             this.sessionId = sessionMatch[1];
-                            this.lastConnectionTime = Date.now();
                             this.isConnected = true;
                             continue;
                         }
                     }
                     
                     // Try to parse as JSON-RPC response
                     try {
                         const mcpResponse = JSON.parse(eventData);
                         if (mcpResponse.jsonrpc === '2.0' && mcpResponse.id) {
+                            this.lastConnectionTime = Date.now();
                             this.handleMCPResponse(mcpResponse);
                         }
                     } catch (parseError) {
                         // Not a JSON-RPC response, continue
                     }
                 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ba4ba61 and 53acf51.

⛔ Files ignored due to path filters (4)
  • docs/public/images/figma-check-for-updates.png is excluded by !**/*.png
  • docs/public/images/figma-link-to-selection.png is excluded by !**/*.png
  • docs/public/images/figma-selection.png is excluded by !**/*.png
  • docs/public/images/figma-to-onlook-banner.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx (3 hunks)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1 hunks)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/context-pills/helpers.tsx (2 hunks)
  • apps/web/client/src/components/store/editor/chat/context.ts (4 hunks)
  • apps/web/client/src/server/api/root.ts (2 hunks)
  • apps/web/client/src/server/api/routers/figma.ts (1 hunks)
  • apps/web/client/src/server/api/routers/index.ts (1 hunks)
  • docs/content/docs/tutorials/figma-to-onlook.mdx (3 hunks)
  • packages/models/src/chat/message/context.ts (2 hunks)
  • packages/ui/src/components/icons/index.tsx (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx (4)
packages/ui/src/components/dropdown-menu.tsx (4)
  • DropdownMenu (214-214)
  • DropdownMenuTrigger (228-228)
  • DropdownMenuContent (216-216)
  • DropdownMenuItem (218-218)
packages/ui/src/components/icons/index.tsx (1)
  • Icons (139-3518)
apps/web/template/lib/utils.ts (1)
  • cn (4-6)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1)
  • FigmaInput (27-270)
apps/web/client/src/server/api/routers/figma.ts (1)
apps/web/client/src/server/api/trpc.ts (1)
  • createTRPCRouter (88-88)
apps/web/client/src/server/api/root.ts (1)
apps/web/client/src/server/api/routers/figma.ts (1)
  • figmaRouter (311-473)
apps/web/client/src/components/store/editor/chat/context.ts (1)
packages/models/src/chat/message/context.ts (3)
  • ImageMessageContext (29-32)
  • FigmaMessageContext (43-48)
  • MessageContext (50-56)
packages/ui/src/components/icons/index.tsx (1)
apps/web/template/lib/utils.ts (1)
  • cn (4-6)
🪛 LanguageTool
docs/content/docs/tutorials/figma-to-onlook.mdx

[grammar] ~67-~67: There might be a mistake here.
Context: ... you can import your design into Onlook: 1. Link based 2. Selection based #### Link bas...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... your design into Onlook: 1. Link based 2. Selection based #### Link based import 1. Copy t...

(QB_NEW_EN)


[grammar] ~99-~99: There might be a mistake here.
Context: ...# 4. Deploy Your App When you're ready: - Push your app live with one click - Shar...

(QB_NEW_EN)


[grammar] ~107-~107: There might be a mistake here.
Context: ...gma designs into Onlook, you'll need to: 1. Be on Figma's Professional or Developer ...

(QB_NEW_EN)


[grammar] ~117-~117: There might be a mistake here.
Context: ...for importing Figma to Onlook? You need: - A Figma Professional or Developer Plan s...

(QB_NEW_EN)


[grammar] ~118-~118: There might be a mistake here.
Context: ...fessional or Developer Plan subscription - The latest version of Figma desktop app ...

(QB_NEW_EN)


[grammar] ~119-~119: There might be a mistake here.
Context: ... Plan subscription - The latest version of Figma desktop app - Dev Mode MCP Server...

(QB_NEW_EN)


[grammar] ~119-~119: There might be a mistake here.
Context: ... The latest version of Figma desktop app - Dev Mode MCP Server enabled in Figma - A...

(QB_NEW_EN)


[grammar] ~120-~120: There might be a mistake here.
Context: ...p - Dev Mode MCP Server enabled in Figma - An Onlook account ### How do I enable F...

(QB_NEW_EN)


[grammar] ~131-~131: There might be a mistake here.
Context: ...an import specific elements in two ways: 1. Link-based: Copy the link to a specific ...

(QB_NEW_EN)


[grammar] ~136-~136: There might be a mistake here.
Context: ... it to Onlook? After importing, you can: - Add animations to the design - Make it i...

(QB_NEW_EN)


[grammar] ~152-~152: There might be a mistake here.
Context: ...er importing, you can use AI prompts to: - Modify the design - Add new elements - C...

(QB_NEW_EN)


[grammar] ~163-~163: There might be a mistake here.
Context: ...add interactivity. Simply ask Onlook to: - Add click interactions - Create hover ef...

(QB_NEW_EN)


[grammar] ~174-~174: There might be a mistake here.
Context: ...be able to use the Figma Import feature.

(QB_NEW_EN)

🔇 Additional comments (8)
packages/ui/src/components/icons/index.tsx (2)

59-59: Importing Figma icon from Radix looks good

The symbol is correctly added to the Radix import list with no side effects on existing icons.


1539-1541: Public alias Icons.Figma wired correctly

Exposing the Radix Figma icon via Icons.Figma aligns with existing patterns and keeps the API consistent.

packages/models/src/chat/message/context.ts (1)

7-8: FIGMA context type addition is cohesive and non-breaking

  • Enum discriminant FIGMA and FigmaMessageContext are well integrated.
  • The union type is updated; exhaustiveness checks downstream (e.g., context pills) are covered in this PR.

No issues spotted.

Also applies to: 43-49, 55-56

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/context-pills/helpers.tsx (1)

16-18: Sensible fallback name for Figma contexts

Providing a default label when displayName is falsy improves UX and avoids empty pills.

apps/web/client/src/server/api/routers/index.ts (1)

4-4: Re-export of figma router is correct

Keeps public API consistent with other routers. No conflicts apparent.

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx (2)

18-18: Nice, local state cleanly gates the Figma dialog

Introducing isFigmaOpen with useState is straightforward and keeps ActionButtons’ public API unchanged.


86-91: Controlled dialog wiring looks correct

Passing isOpen/onOpenChange through to FigmaInput ensures a single source of truth for dialog state. Mounting outside of the DropdownMenu avoids focus/portal conflicts.

apps/web/client/src/server/api/root.ts (1)

6-7: Route registration LGTM

figmaRouter is correctly imported and mounted on appRouter.figma. AppRouter type will naturally include the new route.

Also applies to: 42-43

Copy link

@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

♻️ Duplicate comments (9)
docs/content/docs/tutorials/figma-to-onlook.mdx (6)

3-3: Fix front-matter description: "Export" → "Import"

The page is about importing; the description still says "Export". Align it to avoid confusion.


8-8: Correct terminology in intro: "Export" → "Import"

The first sentence should say "Import" to match the feature and the rest of the page.


67-71: Hyphenation and style for list items

Use "Link-based" and "Selection-based", and tighten wording slightly.


79-79: Hyphenation for section title

Be consistent with "Selection-based".


85-85: Complete the sentence

This line ends mid-sentence. Clarify expected behavior after submission.


118-121: Minor grammar: articles and clarity

Add missing articles for readability.

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1)

73-78: Guard against double "data:image/png;base64," prefix

designData.image may already be a data URL depending on the MCP tool response. Unconditionally prefixing risks producing an invalid URL like data:image/png;base64,data:image/png;base64,....

apps/web/client/src/server/api/routers/figma.ts (2)

257-285: Make nodeId extraction robust using URL parsing

The regex fallback /\/([^\/]+)\?/ is broad and could capture the file key or other path segments, not the node-id. Prefer URL and URLSearchParams for correctness.


12-12: Consider using AbortController for fetch requests

The SSE connection uses an AbortController, but individual HTTP requests could benefit from using AbortController for better timeout handling instead of relying solely on setTimeout.

🧹 Nitpick comments (4)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (2)

12-24: Consider using proper types for the Figma data interfaces

The interfaces are defined locally but could be shared across the codebase since they represent API response structures.

Consider moving these interfaces to a shared types file (e.g., types/figma.ts) if they're used elsewhere in the codebase, to maintain consistency and enable reusability.


224-224: Consistent async error handling pattern

The component uses void with .catch(console.error) for button onClick handlers to handle promises. While this works, it's a bit verbose and could be simplified.

Consider creating a wrapper function to reduce repetition:

+const handleAsyncAction = (action: () => Promise<void>) => {
+    return () => void action().catch(console.error);
+};

 // Then use it like:
-onClick={() => void handlePasteFromClipboard().catch(console.error)}
+onClick={handleAsyncAction(handlePasteFromClipboard)}

Also applies to: 237-237, 259-259

apps/web/client/src/server/api/routers/figma.ts (2)

158-162: Potential memory leak in pending requests cleanup

When cleaning up pending requests during connection closure, the for...of loop modifies the Map while iterating over it.

Consider using Array.from to avoid potential issues:

-// Reject all pending requests
-for (const [id, pending] of this.pendingRequests) {
-    clearTimeout(pending.timeout);
-    pending.reject(new Error('Connection closed'));
-}
-this.pendingRequests.clear();
+// Reject all pending requests
+const requests = Array.from(this.pendingRequests.entries());
+this.pendingRequests.clear();
+for (const [id, pending] of requests) {
+    clearTimeout(pending.timeout);
+    pending.reject(new Error('Connection closed'));
+}

319-326: Consider adding retry logic for transient failures

The safeRequest helper catches errors but doesn't retry. For network-related operations, adding retry logic could improve reliability.

Consider implementing exponential backoff retry logic for transient failures:

async safeRequest<T>(
    requestFn: () => Promise<T>, 
    requestName: string,
    maxRetries = 2
): Promise<T | null> {
    for (let i = 0; i <= maxRetries; i++) {
        try {
            return await requestFn();
        } catch (error) {
            if (i === maxRetries) {
                console.error(`Figma MCP ${requestName} failed after ${maxRetries} retries:`, error);
                return null;
            }
            await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
        }
    }
    return null;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 53acf51 and 59805de.

📒 Files selected for processing (5)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx (3 hunks)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1 hunks)
  • apps/web/client/src/components/store/editor/chat/context.ts (4 hunks)
  • apps/web/client/src/server/api/routers/figma.ts (1 hunks)
  • docs/content/docs/tutorials/figma-to-onlook.mdx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/action-buttons.tsx
  • apps/web/client/src/components/store/editor/chat/context.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (4)
apps/web/client/src/components/store/editor/index.tsx (1)
  • useEditorEngine (9-13)
apps/web/client/src/trpc/react.tsx (1)
  • api (23-23)
packages/ui/src/components/sonner.tsx (1)
  • toast (19-19)
packages/ui/src/components/icons/index.tsx (1)
  • Icons (139-3518)
apps/web/client/src/server/api/routers/figma.ts (1)
apps/web/client/src/server/api/trpc.ts (1)
  • createTRPCRouter (88-88)
🪛 LanguageTool
docs/content/docs/tutorials/figma-to-onlook.mdx

[grammar] ~99-~99: There might be a mistake here.
Context: ...# 4. Deploy Your App When you're ready: - Push your app live with one click - Shar...

(QB_NEW_EN)


[grammar] ~107-~107: There might be a mistake here.
Context: ...gma designs into Onlook, you'll need to: 1. Be on Figma's Professional or Developer ...

(QB_NEW_EN)


[grammar] ~117-~117: There might be a mistake here.
Context: ...for importing Figma to Onlook? You need: - A Figma Professional or Developer Plan s...

(QB_NEW_EN)


[grammar] ~118-~118: There might be a mistake here.
Context: ...fessional or Developer Plan subscription - The latest version of the Figma desktop ...

(QB_NEW_EN)


[grammar] ~119-~119: There might be a mistake here.
Context: ... latest version of the Figma desktop app - The Dev Mode MCP Server enabled in Figma...

(QB_NEW_EN)


[grammar] ~120-~120: There might be a mistake here.
Context: ...The Dev Mode MCP Server enabled in Figma - An Onlook account ### How do I enable F...

(QB_NEW_EN)


[grammar] ~131-~131: There might be a mistake here.
Context: ...an import specific elements in two ways: 1. Link-based: Copy the link to a specific ...

(QB_NEW_EN)


[grammar] ~136-~136: There might be a mistake here.
Context: ... it to Onlook? After importing, you can: - Add animations to the design - Make it i...

(QB_NEW_EN)


[grammar] ~152-~152: There might be a mistake here.
Context: ...er importing, you can use AI prompts to: - Modify the design - Add new elements - C...

(QB_NEW_EN)


[grammar] ~153-~153: There might be a mistake here.
Context: ...n use AI prompts to: - Modify the design - Add new elements - Change the styling - ...

(QB_NEW_EN)


[grammar] ~154-~154: There might be a mistake here.
Context: ...: - Modify the design - Add new elements - Change the styling - Make it interactive...

(QB_NEW_EN)


[grammar] ~155-~155: There might be a mistake here.
Context: ... - Add new elements - Change the styling - Make it interactive - Add animations ##...

(QB_NEW_EN)


[grammar] ~156-~156: There might be a mistake here.
Context: ...Change the styling - Make it interactive - Add animations ### Do I need to be a de...

(QB_NEW_EN)


[grammar] ~163-~163: There might be a mistake here.
Context: ...add interactivity. Simply ask Onlook to: - Add click interactions - Create hover ef...

(QB_NEW_EN)


[grammar] ~174-~174: There might be a mistake here.
Context: ...be able to use the Figma Import feature.

(QB_NEW_EN)

🔇 Additional comments (2)
apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx (1)

1-279: Figma import component implementation looks good!

The component provides a clean UI for importing Figma designs with three well-structured workflows (URL-based, selection-based, and clipboard). The state management, error handling, and user feedback mechanisms are well implemented.

apps/web/client/src/server/api/routers/figma.ts (1)

1-493: Well-structured Figma MCP integration with robust session management

The implementation provides a comprehensive SSE-based connection management system with proper error handling, timeout management, and request tracking. The router endpoints are well-designed to support the Figma import functionality.

import { createTRPCRouter, publicProcedure } from '../trpc';

class ServerSideFigmaMCP {
private readonly MCP_BASE_URL = process.env.MCP_SERVER_URL || 'http://127.0.0.1:3845';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify MCP server URL environment variable

The MCP server URL defaults to localhost but should be configurable via environment variable for production deployments.


🏁 Script executed:

#!/bin/bash
# Check if MCP_SERVER_URL is documented in environment files
fd -e env -e example -e md -e mdx | xargs rg -l "MCP_SERVER_URL" || echo "MCP_SERVER_URL not documented"

# Check for any existing env configuration files
fd "\.env" --type f --max-depth 3

Length of output: 169


Document MCP_SERVER_URL environment variable

The MCP_BASE_URL in apps/web/client/src/server/api/routers/figma.ts (line 5) falls back to localhost but the corresponding MCP_SERVER_URL isn’t documented anywhere. Please add it to:

  • .env.example (or your primary env template)
  • Project documentation (e.g., README.md or docs folder)

This will ensure production deployments can override the default URL.

🤖 Prompt for AI Agents
In apps/web/client/src/server/api/routers/figma.ts around line 5, the
MCP_BASE_URL reads from MCP_SERVER_URL but that env var isn’t documented; update
the project’s environment template and docs by adding MCP_SERVER_URL to
.env.example (set to the current default "http://127.0.0.1:3845" and a short
description like "Base URL for MCP server, override in production"), and add the
same entry and usage note to the README.md (or docs folder) so deployers know to
set MCP_SERVER_URL for production.

Copy link

@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: 0

🧹 Nitpick comments (3)
packages/ai/src/prompt/context.ts (1)

26-27: Polish copy: fix grammar and clarity of the Figma prefix.

Wording is a bit awkward. Recommend tightening for clarity and consistency with other prefixes.

Apply this diff:

-const figmaContentPrefix = `This is included Figma design files or selection that you can use the Figma tool to fetch the content.`;
+const figmaContentPrefix = `The following Figma design files or selections are included. Use the Figma tool to fetch their contents.`;
packages/ai/src/prompt/provider.ts (2)

90-97: Consider including Figma context even when file context is truncated.

Currently, figma-context is emitted only in the non-truncated branch. If the goal is to keep Figma references available regardless of file-context truncation, emit the figma block unconditionally (or add a separate truncation policy for it).

Example adjustment for the surrounding block:

let prompt = '';
if (truncateFileContext) {
  const contextPrompt = getTruncatedFilesContent(files);
  if (contextPrompt) {
    prompt += wrapXml('truncated-context', contextPrompt);
  }
} else {
  const fileContextPrompt = getFilesContent(files, highlights);
  if (fileContextPrompt) {
    prompt += wrapXml('context', fileContextPrompt);
  }
}

// Always include Figma context
{
  const figmaContextPrompt = getFigmaContent(figma);
  if (figmaContextPrompt) {
    prompt += wrapXml('figma-context', figmaContextPrompt);
  }
}

177-187: Limit serialized fields and avoid local name shadowing.

Minor: avoid shadowing the outer “figma” identifier and trim the JSON payload to just the fields consumers need. This reduces prompt bloat and keeps ordering stable.

Apply this diff:

 export function getFigmaContent(figmaContext: FigmaMessageContext[]) {
     if (figmaContext.length === 0) {
         return '';
     }
     let prompt = '';
     prompt += `${CONTEXT_PROMPTS.figmaContentPrefix}\n`;
-    for (const figma of figmaContext) {
-        prompt += `${JSON.stringify(figma)}\n`;
+    for (const item of figmaContext) {
+        // Keep the payload minimal and stable
+        const payload = {
+            figmaUrl: item.figmaUrl,
+            nodeId: item.nodeId,
+            ...(item.fileName ? { fileName: item.fileName } : {}),
+        };
+        prompt += `${JSON.stringify(payload)}\n`;
     }
     return prompt;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 59805de and 61cff8a.

📒 Files selected for processing (3)
  • apps/web/client/src/components/store/editor/chat/context.ts (4 hunks)
  • packages/ai/src/prompt/context.ts (1 hunks)
  • packages/ai/src/prompt/provider.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/client/src/components/store/editor/chat/context.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/ai/src/prompt/provider.ts (3)
packages/ai/src/prompt/helpers.ts (1)
  • wrapXml (1-3)
packages/models/src/chat/message/context.ts (1)
  • FigmaMessageContext (43-48)
packages/ai/src/prompt/context.ts (1)
  • CONTEXT_PROMPTS (28-35)
🔇 Additional comments (3)
packages/ai/src/prompt/context.ts (1)

34-35: Exposing figmaContentPrefix looks good.

The new prefix is correctly exported alongside the other context prompts.

packages/ai/src/prompt/provider.ts (2)

3-3: Importing FigmaMessageContext: LGTM.

The type import is correct and scoped as a type-only import.


76-76: Discriminant values for Figma contexts are correct

Verified that in packages/models/src/chat/message/context.ts:

  • MessageContextType.FIGMA is defined as 'figma', matching the literal used in provider.ts.
  • The filter c.type === 'figma' will not drop any valid Figma contexts.

No changes needed.

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.

2 participants