From 0a0f1e6888096d461564d9b3067707b9a30ae4c7 Mon Sep 17 00:00:00 2001
From: vgcman16 <155417613+vgcman16@users.noreply.github.com>
Date: Thu, 5 Jun 2025 18:47:35 -0500
Subject: [PATCH] feat: add Figma import feature
---
CHANGES.md | 20 +++++
README.md | 2 +
app/components/figma/FigmaImport.client.tsx | 58 ++++++++++++++
app/routes/figma.tsx | 28 +++++++
app/utils/figmaImport.ts | 84 +++++++++++++++++++++
docs/docs/index.md | 1 +
6 files changed, 193 insertions(+)
create mode 100644 app/components/figma/FigmaImport.client.tsx
create mode 100644 app/routes/figma.tsx
create mode 100644 app/utils/figmaImport.ts
diff --git a/CHANGES.md b/CHANGES.md
index 0b706640..cd338136 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -90,3 +90,23 @@ This implementation adds persistent file and folder locking functionality to the
2. **Contextual Icons**: Different icons and colors for different types of alerts
3. **Improved Error Details**: Better formatting of error details with monospace font and left border
4. **Responsive Buttons**: Better positioned and styled buttons with appropriate hover effects
+
+# Built-in Figma Import Feature
+
+## Overview
+
+This update adds the ability to import a Figma URL directly into BoltDIY. The application fetches the Figma file and generates starter React component files for each top-level frame, creating a new chat with the generated code ready for editing.
+
+## New Files
+
+### 1. `app/utils/figmaImport.ts`
+
+- Fetches Figma files and converts frames to simple React components
+
+### 2. `app/components/figma/FigmaImport.client.tsx`
+
+- Client component that imports a Figma design using query parameters
+
+### 3. `app/routes/figma.tsx`
+
+- Route to initiate the Figma import flow
diff --git a/README.md b/README.md
index 400d07e1..f0ea1d78 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,7 @@ project, please check the [project management guide](./PROJECT.md) to get starte
- ⬜ Granite Integration
- ✅ Popout Window for Web Container(@stijnus)
- ✅ Ability to change Popout window size (@stijnus)
+- ✅ Import from Figma (@open-source)
## Features
@@ -107,6 +108,7 @@ project, please check the [project management guide](./PROJECT.md) to get starte
- **Download projects as ZIP** for easy portability Sync to a folder on the host.
- **Integration-ready Docker support** for a hassle-free setup.
- **Deploy** directly to **Netlify**, **Vercel**, or **Cloudflare Pages**
+- **Import Figma designs** to generate starter UI code.
## Setup
diff --git a/app/components/figma/FigmaImport.client.tsx b/app/components/figma/FigmaImport.client.tsx
new file mode 100644
index 00000000..295d856d
--- /dev/null
+++ b/app/components/figma/FigmaImport.client.tsx
@@ -0,0 +1,58 @@
+import { useSearchParams } from '@remix-run/react';
+import { useEffect, useState } from 'react';
+import { ClientOnly } from 'remix-utils/client-only';
+import { BaseChat } from '~/components/chat/BaseChat';
+import { Chat } from '~/components/chat/Chat.client';
+import { useChatHistory } from '~/lib/persistence';
+import { createChatFromFigma } from '~/utils/figmaImport';
+import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
+import { toast } from 'react-toastify';
+
+export function FigmaImport() {
+ const [searchParams] = useSearchParams();
+ const { ready, importChat } = useChatHistory();
+ const [imported, setImported] = useState(false);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (!ready || imported) {
+ return;
+ }
+
+ const url = searchParams.get('url');
+ const token = searchParams.get('token');
+
+ if (!url || !token) {
+ window.location.href = '/';
+ return;
+ }
+
+ createChatFromFigma(url, token)
+ .then(async (messages) => {
+ if (importChat) {
+ const name = url.split('/').slice(-1)[0];
+ await importChat(`Figma:${name}`, messages);
+ }
+ })
+ .catch((error) => {
+ console.error('Error importing Figma design:', error);
+ toast.error('Failed to import Figma design');
+ window.location.href = '/';
+ })
+ .finally(() => {
+ setLoading(false);
+ setImported(true);
+ });
+ }, [ready, imported, searchParams, importChat]);
+
+ return (
+