diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0d270a6de6..c03c31a377 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -31,8 +31,8 @@ }, "vscode": { "settings": { - "chat.mcp.autoStart": false, - "workbench.startupEditor": "welcomePageInEmptyWorkbench", + "chat.mcp.autoStart": true, + "workbench.startupEditor": "none", "workbench.tips.enabled": false, "workbench.welcome.enabled": false, "github.copilot.chat.openAtStartup": true diff --git a/.devcontainer/storybook-launcher/extension/extension.js b/.devcontainer/storybook-launcher/extension/extension.js index 32577ba606..b01432912d 100644 --- a/.devcontainer/storybook-launcher/extension/extension.js +++ b/.devcontainer/storybook-launcher/extension/extension.js @@ -64,20 +64,7 @@ async function waitForServer(port, maxWait) { return false; } -const WALKTHROUGH_SEEN_KEY = "storybookLauncher.walkthroughSeen"; - function activate(context) { - const walkthroughSeen = context.globalState.get(WALKTHROUGH_SEEN_KEY, false); - - if (!walkthroughSeen) { - context.globalState.update(WALKTHROUGH_SEEN_KEY, true); - vscode.commands.executeCommand( - "workbench.action.openWalkthrough", - { category: "element-hq.storybook-launcher#storybookLauncher.gettingStarted", step: "wait" }, - false, - ); - } - // --- Storybook status bar --- const sbItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100); sbItem.text = "$(loading~spin) Storybook: Starting\u2026"; @@ -106,7 +93,7 @@ function activate(context) { sbItem.text = "$(beaker) Storybook: Open \u25b8"; sbItem.tooltip = "Storybook Playground is ready — click to open"; sbItem.command = "storybookLauncher.openPreview"; - if (walkthroughSeen) await openStorybookPreview(); + await openStorybookPreview(); } else { sbItem.text = "$(warning) Storybook: Not Started"; sbItem.tooltip = "Storybook did not start. Try: pnpm run storybook:design"; diff --git a/.devcontainer/storybook-launcher/extension/media/walkthrough-welcome.md b/.devcontainer/storybook-launcher/extension/media/walkthrough-welcome.md deleted file mode 100644 index 7e1c8aab55..0000000000 --- a/.devcontainer/storybook-launcher/extension/media/walkthrough-welcome.md +++ /dev/null @@ -1,20 +0,0 @@ -# Welcome to the Storybook Playground - -Your Codespace is setting up right now — this usually takes about -**20–25 seconds**. - -### What's happening - -1. **Dependencies** are being installed automatically. -2. **Storybook** starts as soon as they're ready. - -### How you'll know it's ready - -Look at the **status bar** at the bottom of the editor. -When it changes to **Storybook: Open ▸** you're good to go. - -### Opening Storybook - -Click the **Element** icon in the Activity Bar on the left to open -the Storybook Playground panel, then press the button to launch -the preview. diff --git a/.devcontainer/storybook-launcher/extension/package.json b/.devcontainer/storybook-launcher/extension/package.json index ab9634778c..4cacece3c5 100644 --- a/.devcontainer/storybook-launcher/extension/package.json +++ b/.devcontainer/storybook-launcher/extension/package.json @@ -77,21 +77,6 @@ "group": "navigation" } ] - }, - "walkthroughs": [ - { - "id": "storybookLauncher.gettingStarted", - "title": "Welcome to the Storybook Playground", - "description": "Your Codespace is getting ready.", - "steps": [ - { - "id": "wait", - "title": "Hang tight — setting things up", - "description": "Dependencies are installing and Storybook is starting. This usually takes **20–25 seconds**.\n\nWatch the **status bar** at the bottom — when it says **Storybook: Open ▸** everything is ready.\n\nUse the **Element** icon in the Activity Bar on the left to open Storybook or Element Web at any time.\n\n[Open Storybook Panel](command:storybookLauncher.welcome.focus)", - "media": { "markdown": "media/walkthrough-welcome.md" } - } - ] - } - ] + } } } diff --git a/.github/agents/designer.agent.md b/.github/agents/designer.agent.md index 413ff10bb3..dd25832678 100644 --- a/.github/agents/designer.agent.md +++ b/.github/agents/designer.agent.md @@ -10,7 +10,7 @@ Your job is to help designers turn Figma designs into interactive prototypes — 1. **Parse Figma URLs** — Extract the file key and node ID from any Figma URL the designer shares. 2. **Validate the connection** — Check that `FIGMA_TOKEN` is set and the Figma API is reachable before doing anything else. -3. **Inspect designs** — Use the Figma MCP tools (or CLI fallback scripts) to explore files, frames, and components. +3. **Inspect designs** — Use the Figma MCP tools to explore files, frames, and components. 4. **Generate prototypes** — Create Storybook stories or modify Element Web components to recreate Figma layouts using existing shared-components and Compound Web primitives. ## Before You Start — Read the Guidelines @@ -39,37 +39,17 @@ When a node ID is present, **go directly to that node** — call `get_figma_node ## Calling Figma Tools -You have two ways to fetch Figma data. **Try MCP tools first**, fall back to CLI scripts if MCP is unavailable. +The `element-web-figma` MCP server starts automatically with the Codespace. Use these tools to fetch Figma data: -### Option A — MCP tools (preferred) - -If the `element-web-figma` MCP server is registered, call: - `get_figma_file` with `{ "fileKey": "" }` - `get_figma_node` with `{ "fileKey": "", "nodeId": "", "depth": 4 }` - `get_figma_components` with `{ "fileKey": "" }` -### Option B — CLI scripts (fallback) - -If MCP tools are not available or return an error about unknown tools, use the terminal instead. These scripts produce the same JSON output: - -```bash -# Fetch file overview -node scripts/design/figma-file.mjs - -# Fetch a specific node (depth default 4) -node scripts/design/figma-node.mjs [depth] - -# List components -node scripts/design/figma-components.mjs [limit] -``` - -**Always try MCP first.** If the first MCP call fails with a tool-not-found error, switch to CLI for all subsequent calls in the same conversation — don't retry MCP. - ## Connection Validation Before inspecting any design, verify the Figma connection: -1. Call `get_figma_file` (MCP) or `node scripts/design/figma-file.mjs ` (CLI) with the extracted file key. +1. Call `get_figma_file` with `{ "fileKey": "" }` using the extracted file key. 2. If it succeeds, report the file name and number of frames/pages to the designer and proceed. 3. If it fails with a token error, guide the designer: diff --git a/docs/ai-prototyping/README.md b/docs/ai-prototyping/README.md index dc814f709a..05bd894997 100644 --- a/docs/ai-prototyping/README.md +++ b/docs/ai-prototyping/README.md @@ -4,18 +4,24 @@ This workflow gives designers a no-local-setup path for turning Figma designs in ## 1. Create a Figma API token -1. Open Figma and go to Settings → Security → Personal access tokens. +1. Open Figma and go to **Settings → Security → Personal access tokens**. 2. Generate a new token and copy it immediately (Figma only shows it once). -## 2. Add the Codespace secret +## 2. Add the Codespace secret (before creating the Codespace) -Create **one** user secret in GitHub Codespaces before launching the workspace: +> **Important:** You must add this secret **before** creating the Codespace. +> The Figma MCP server reads `FIGMA_TOKEN` at startup. If the secret is +> missing when the Codespace is created, the server will start without a +> valid token and Figma tools will not work. -- `FIGMA_TOKEN`: your Figma personal access token. +1. Go to [GitHub → Settings → Codespaces → Secrets](https://github.com/settings/codespaces). +2. Add a secret named `FIGMA_TOKEN` with the token you copied. +3. Under **Repository access**, allow the `element-hq/element-web` repository. -Go to [GitHub → Settings → Codespaces → Secrets](https://github.com/settings/codespaces), add `FIGMA_TOKEN`, and allow the `element-hq/element-web` repository. - -> **No per-file secret needed.** The Designer agent extracts the file key from whatever Figma URL you paste in chat. You can work with any Figma file using the same token. +> **Already created a Codespace without the token?** You can add the secret +> and then rebuild the Codespace: open the Command Palette (⌘⇧P / Ctrl+Shift+P) +> and run **Codespaces: Rebuild Container**. This will restart the environment +> with the secret available. ## 3. Open the Codespace @@ -23,7 +29,7 @@ Go to [GitHub → Settings → Codespaces → Secrets](https://github.com/settin 2. Wait for the dev container to finish installing dependencies with `pnpm`. 3. Storybook starts automatically in the existing shared-components package and forwards port `6007` for preview. 4. Element Web can also be started for in-app prototyping (see below). -5. The Figma MCP server registers automatically from the dev container configuration. +5. The Figma MCP server starts automatically — no manual action required (as long as `FIGMA_TOKEN` was set before creating the Codespace). ## 4. Use the Designer agent diff --git a/package.json b/package.json index bb75c3bdf1..c40ce83e8a 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,6 @@ "storybook:design": "node scripts/design/run-storybook.mjs", "start:element-web": "node scripts/design/run-element-web.mjs", "figma:connect": "node scripts/design/figma-connect.mjs", - "figma:file": "node scripts/design/figma-file.mjs", - "figma:node": "node scripts/design/figma-node.mjs", - "figma:components": "node scripts/design/figma-components.mjs", "figma:mcp": "node scripts/design/figma-mcp-server.mjs", "lint": "pnpm -r lint:types && pnpm lint:prettier && pnpm -r lint:js && pnpm -r lint:style && pnpm lint:workflows && pnpm lint:knip", "lint:prettier": "prettier --check .", diff --git a/packages/shared-components/src/prototypes/ai/FigmaPrototypeSandbox.stories.tsx b/packages/shared-components/src/prototypes/ai/FigmaPrototypeSandbox.stories.tsx index bc4cd18b2c..5cc80e99bc 100644 --- a/packages/shared-components/src/prototypes/ai/FigmaPrototypeSandbox.stories.tsx +++ b/packages/shared-components/src/prototypes/ai/FigmaPrototypeSandbox.stories.tsx @@ -35,9 +35,9 @@ const SETUP_STEPS: StepData[] = [ }, { number: 2, - title: "Store your token in this Codespace", + title: "Store your token before creating the Codespace", description: - "Add one Codespace secret called FIGMA_TOKEN so the Figma MCP tools work automatically every time this environment starts. Navigate to GitHub \u2192 Settings \u2192 Codespaces \u2192 Secrets, add the secret, and allow this repository.", + "Add a Codespace secret called FIGMA_TOKEN before you create (or rebuild) the Codespace. The Figma MCP server reads the token at startup — if it is missing the Figma tools will not work. Go to GitHub \u2192 Settings \u2192 Codespaces \u2192 Secrets, add the secret, and allow this repository. If you already created a Codespace without it, add the secret then rebuild: Command Palette \u2192 Codespaces: Rebuild Container.", code: "FIGMA_TOKEN \u2014 your personal access token", action: { label: "Open Codespaces secrets", diff --git a/scripts/design/figma-components.mjs b/scripts/design/figma-components.mjs deleted file mode 100644 index 8a9075d7e4..0000000000 --- a/scripts/design/figma-components.mjs +++ /dev/null @@ -1,30 +0,0 @@ -/** - * CLI wrapper for listing Figma file components. - * - * Usage: - * node scripts/design/figma-components.mjs [limit] - * - * Examples: - * node scripts/design/figma-components.mjs IjNuVxaLRhe2MotMWJ9EtG - * node scripts/design/figma-components.mjs IjNuVxaLRhe2MotMWJ9EtG 50 - */ - -import { getFigmaComponents } from "./figma-api.mjs"; - -const fileKey = process.argv[2]; -const limit = process.argv[3] ? Number.parseInt(process.argv[3], 10) : undefined; - -if (!fileKey) { - console.error("Usage: figma-components [limit]"); - console.error(" fileKey — the alphanumeric file ID from a Figma URL"); - console.error(" limit — max components to return (default: all)"); - process.exit(1); -} - -try { - const result = await getFigmaComponents(limit, fileKey); - console.log(JSON.stringify(result, null, 2)); -} catch (error) { - console.error(error instanceof Error ? error.message : error); - process.exit(1); -} diff --git a/scripts/design/figma-file.mjs b/scripts/design/figma-file.mjs deleted file mode 100644 index 568f2c7e2f..0000000000 --- a/scripts/design/figma-file.mjs +++ /dev/null @@ -1,27 +0,0 @@ -/** - * CLI wrapper for fetching a Figma file overview. - * - * Usage: - * node scripts/design/figma-file.mjs - * - * Example: - * node scripts/design/figma-file.mjs IjNuVxaLRhe2MotMWJ9EtG - */ - -import { getFigmaFile } from "./figma-api.mjs"; - -const fileKey = process.argv[2]; - -if (!fileKey) { - console.error("Usage: figma-file "); - console.error(" fileKey — the alphanumeric file ID from a Figma URL"); - process.exit(1); -} - -try { - const result = await getFigmaFile(fileKey); - console.log(JSON.stringify(result, null, 2)); -} catch (error) { - console.error(error instanceof Error ? error.message : error); - process.exit(1); -} diff --git a/scripts/design/figma-node.mjs b/scripts/design/figma-node.mjs deleted file mode 100644 index 91d72f80c9..0000000000 --- a/scripts/design/figma-node.mjs +++ /dev/null @@ -1,32 +0,0 @@ -/** - * CLI wrapper for fetching a specific Figma node. - * - * Usage: - * node scripts/design/figma-node.mjs [depth] - * - * Examples: - * node scripts/design/figma-node.mjs IjNuVxaLRhe2MotMWJ9EtG 417:19911 - * node scripts/design/figma-node.mjs IjNuVxaLRhe2MotMWJ9EtG 417:19911 6 - */ - -import { getFigmaNode } from "./figma-api.mjs"; - -const fileKey = process.argv[2]; -const nodeId = process.argv[3]; -const depth = Number.parseInt(process.argv[4] ?? "4", 10); - -if (!fileKey || !nodeId) { - console.error("Usage: figma-node [depth]"); - console.error(" fileKey — the alphanumeric file ID from a Figma URL"); - console.error(" nodeId — the node ID, e.g. 417:19911"); - console.error(" depth — child depth 1-6, default 4"); - process.exit(1); -} - -try { - const result = await getFigmaNode(nodeId, depth, fileKey); - console.log(JSON.stringify(result, null, 2)); -} catch (error) { - console.error(error instanceof Error ? error.message : error); - process.exit(1); -}