DEV Community

Daniel Ainoko
Daniel Ainoko

Posted on

From Notion Page to Figma Screens in Seconds

Notion MCP Challenge Submission ๐Ÿง 

I Turned Notion Into a UI Design Tool โ€” Claude Reads Your Page and Draws the Screens in Figma

This is a submission for the Notion MCP Challenge


What I Built

NotionCanvas MCP โ€” a Model Context Protocol server that creates a live pipeline from your Notion workspace directly into Figma.

You write your app idea, feature spec, or product requirements in Notion โ€” the way you normally would. Then you tell Claude:

"Read my Notion page and generate a mobile UI design in Figma"

And it does. Fully. Screens appear in Figma.

No Figma experience required. No prompt engineering. No copy-pasting. No manually describing your idea to an AI. Your Notion page is the brief โ€” and NotionCanvas turns it into a real, editable UI in seconds.


The Problem It Solves

Every product builder knows this moment: you have a clear idea written up in Notion โ€” user flows, feature descriptions, screen names, content โ€” and then you spend the next hour either:

  • Trying to describe that same idea to an AI image generator with mixed results
  • Opening Figma and building frames manually from scratch
  • Hiring a designer and waiting days for a first draft

The idea is already written. Why describe it again?

NotionCanvas closes that gap entirely. Your Notion page is the single source of truth โ€” and Claude bridges it to Figma automatically.


How It Works

The system has three parts working together:

Your Notion Page
      โ”‚
      โ–ผ
  notioncanvas-mcp  (Node.js MCP Server)
      โ”‚
      โ”œโ”€โ”€ Notion API  โ†’  reads your page content
      โ”œโ”€โ”€ Claude API  โ†’  interprets it, generates a Design IR (structured JSON)
      โ””โ”€โ”€ WebSocket   โ†’  sends commands to the Figma Bridge Plugin
                                  โ”‚
                           Figma Desktop
                      (NotionCanvas Bridge Plugin)
                          draws frames on canvas
Enter fullscreen mode Exit fullscreen mode

Step 1 โ€” Notion Reader: Reads your page recursively โ€” headings, paragraphs, lists, callouts, properties โ€” and builds a clean structured content object.

Step 2 โ€” Claude Interpreter: Claude receives the Notion content + your design preferences (mobile/web, theme, color, design system) and outputs a Design Intermediate Representation (DIR) โ€” a validated JSON schema describing every screen, every component, every coordinate, every color.

Step 3 โ€” DIR Validator: Zod validates every component before anything touches Figma. Malformed AI output never reaches the canvas. Claude gets up to 2 automatic retries with targeted error feedback.

Step 4 โ€” Figma Writer: The MCP server sends each screen to the Figma Bridge Plugin over a local WebSocket. The plugin executes Figma Plugin API calls โ€” createFrame(), createText(), createRectangle() โ€” and your screens appear live on the canvas.


What It Can Generate

From a single Notion page, NotionCanvas produces:

  • Full mobile screens (390ร—844) or web layouts (1440ร—900)
  • Text components with font weight, size, alignment
  • Input fields with placeholder text
  • Buttons with variants (primary, secondary, ghost, destructive)
  • Frames with Auto Layout support (vertical/horizontal, padding, spacing)
  • Rectangles with stroke, fill, corner radius
  • Every component positioned absolutely with proper coordinates
  • Background colors derived from your brand description

All components land in Figma as native, editable nodes โ€” not images, not embeds. You can grab any element and keep designing from there.


The 6 MCP Tools

Tool What it does
generate_ui_design Full pipeline: reads your Notion page โ†’ Claude โ†’ Figma screens
generate_screen Single screen from a plain-text description (no Notion needed)
notion_read_page Read and return structured content of any Notion page
notion_read_db Query a Notion database and return all entries
list_figma_frames List all existing frames in a Figma file
get_design_status Check if the Figma Bridge Plugin is connected and ready

Real Example

I wrote this in Notion:

"I want a simple ride hailing application. Main color theme is red. Use Inter font."

That's it. Two sentences.

NotionCanvas read that page, sent it to Claude, generated a full DesignIR with an onboarding screen, a home screen with a map layout, a booking screen with input fields and a confirm button โ€” and sent all of it to Figma as native frames.

The whole pipeline ran in under 90 seconds.


Video Demo

Watch on YouTube


Show us the code

GitHub: github.com/TheCodeDaniel/notion_canvas

Project structure

notioncanvas-mcp/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ index.ts                    โ† MCP server entry point (stdio transport)
โ”‚   โ”œโ”€โ”€ clients/
โ”‚   โ”‚   โ”œโ”€โ”€ notion.ts               โ† Notion API + p-queue rate limiter (2.8 req/s)
โ”‚   โ”‚   โ”œโ”€โ”€ claude.ts               โ† Claude API + JSON retry logic (3 attempts)
โ”‚   โ”‚   โ”œโ”€โ”€ figma-ws.ts             โ† WebSocket bridge server (localhost:9223)
โ”‚   โ”‚   โ””โ”€โ”€ figma-rest.ts           โ† Figma REST API (read-only frame listing)
โ”‚   โ”œโ”€โ”€ interpreter/
โ”‚   โ”‚   โ”œโ”€โ”€ schema.ts               โ† Zod DesignIR schema (5 component types)
โ”‚   โ”‚   โ””โ”€โ”€ prompt.ts               โ† Claude system/user prompt builders
โ”‚   โ”œโ”€โ”€ tools/                      โ† 6 MCP tools
โ”‚   โ”œโ”€โ”€ types/                      โ† TypeScript interfaces
โ”‚   โ””โ”€โ”€ utils/                      โ† logger, retry, PAT expiry checker
โ””โ”€โ”€ plugin/
    โ”œโ”€โ”€ manifest.json               โ† Figma plugin manifest
    โ”œโ”€โ”€ plugin.js                   โ† Figma Plugin API (main thread)
    โ””โ”€โ”€ ui.html                     โ† WebSocket iframe (relay bridge)
Enter fullscreen mode Exit fullscreen mode

Setup is one command after filling your .env

npm install
npm run build
npm run setup   # auto-detects Claude Desktop config path, merges entry, resolves absolute paths
Enter fullscreen mode Exit fullscreen mode

The setup command handles everything:

  • Reads credentials from your .env
  • Detects claude_desktop_config.json path for macOS or Windows
  • Creates the file if it doesn't exist
  • Merges the notioncanvas entry without touching your other MCP servers
  • Auto-resolves the absolute path to dist/index.js โ€” nothing to edit manually

Stack

  • TypeScript / Node.js โ€” ESM, strict mode
  • @modelcontextprotocol/sdk โ€” MCP server with stdio transport
  • @notionhq/client โ€” Notion API with p-queue rate limiting
  • @anthropic-ai/sdk โ€” Claude API (claude-sonnet-4-6)
  • ws โ€” WebSocket server for the Figma bridge
  • zod โ€” DesignIR schema validation before any Figma writes
  • Figma Plugin API โ€” native canvas writes via the bridge plugin

How I Used Notion MCP

Notion MCP is the foundation that makes this whole idea possible โ€” and not in a trivial way.

Why Notion as the input source is actually powerful

Most AI design tools start with a blank text box. You describe your idea to the AI. The AI designs something. But that description lives nowhere โ€” it's not connected to your roadmap, your feature specs, your user stories. It's a one-off prompt.

Notion changes that. Your product thinking already lives there. Feature specs, screen flows, content requirements, user personas โ€” structured, searchable, shareable with your team. With Notion MCP as the reader, that existing knowledge becomes the direct input to the design pipeline.

You're not describing your idea to an AI. You're pointing an AI at your idea. That's a fundamentally different workflow.

The specific integration

I used the Notion internal integration token (via @notionhq/client) to:

  1. Read pages recursively โ€” the client traverses the full block tree, handling pagination (100 blocks per request), nested toggles, callouts, lists, and all block types. Pages with hundreds of blocks are handled cleanly.

  2. Query databases โ€” the notion_read_db tool lets you pull structured data from Notion databases and feed it into screen generation. Imagine a database of app screens with properties like "screen type", "primary action", "user role" โ€” and generating each one automatically.

  3. Handle the page-sharing security model correctly โ€” Notion's integration tokens only work on pages explicitly shared with the integration. The server returns a helpful, specific error message when a 404 is returned, rather than a generic failure.

What Notion MCP unlocks that nothing else does

The pipeline means your Notion page becomes a living design brief. Update the page โ€” run the tool again โ€” get updated screens. It's not a one-time export. It's a repeatable process driven by the content you're already maintaining.

For solo founders, indie developers, and small product teams who live in Notion: this means going from written idea to visual screen without leaving your workflow or learning Figma from scratch.

That's the unlock. Notion stops being a notes app and starts being a design input system.


Built with Claude Code, @modelcontextprotocol/sdk, @notionhq/client, and the Figma Plugin API.
Stack: TypeScript ยท Node.js ยท WebSockets ยท Zod ยท claude-sonnet-4-6

Top comments (0)