-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: Introduce Import from Figma using MCP Functionality #2129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@iNerdStack is attempting to deploy a commit to the Onlook Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this 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 in10
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 by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
.../web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx
Outdated
Show resolved
Hide resolved
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds 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
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
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
Estimated code review effort🎯 5 (Critical) | ⏱️ ~110 minutes Poem
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 detailsConfiguration used: CodeRabbit UI 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
usesfill="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 anyDefining 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 socketsCurrently 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 explicitas 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 accessibilityScreen 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 consistencyIf “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 URLSmall 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 receptionisSessionValid 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.
⛔ 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 goodThe symbol is correctly added to the Radix import list with no side effects on existing icons.
1539-1541
: Public alias Icons.Figma wired correctlyExposing 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
andFigmaMessageContext
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 contextsProviding 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 correctKeeps 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 dialogIntroducing isFigmaOpen with useState is straightforward and keeps ActionButtons’ public API unchanged.
86-91
: Controlled dialog wiring looks correctPassing 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 LGTMfigmaRouter is correctly imported and mounted on appRouter.figma. AppRouter type will naturally include the new route.
Also applies to: 42-43
.../web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-input/figma-input.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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 itemsUse "Link-based" and "Selection-based", and tighten wording slightly.
79-79
: Hyphenation for section titleBe consistent with "Selection-based".
85-85
: Complete the sentenceThis line ends mid-sentence. Clarify expected behavior after submission.
118-121
: Minor grammar: articles and clarityAdd 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," prefixdesignData.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 parsingThe 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 usingAbortController
for fetch requestsThe 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 interfacesThe 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 patternThe 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 cleanupWhen 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 failuresThe
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.
📒 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 managementThe 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'; |
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
📒 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 correctVerified that in
packages/models/src/chat/message/context.ts
:
MessageContextType.FIGMA
is defined as'figma'
, matching the literal used inprovider.ts
.- The filter
c.type === 'figma'
will not drop any valid Figma contexts.No changes needed.
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
Testing
Screenshots (if applicable)
Additional Notes
Important
Introduces Figma import feature using MCP, adding new components, context management, and documentation updates.
FigmaInput
component inaction-buttons.tsx
for importing Figma designs.figmaRouter
inrouters/figma.ts
.FigmaMessageContext
tocontext.ts
for managing Figma design data.getHydratedUserMessage()
inprovider.ts
to include Figma context.FigmaLogo
icon toicons/index.tsx
.figma-to-onlook/index.mdx
andfeatures/index.mdx
to include Figma import instructions.This description was created by
for dec7bcc. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
Backend
UI/Style
Documentation