Skip to main content
Glama

fig2web

CI npm

Read Figma files without Figma. fig2web rebuilds every screen of a .fig file as static HTML/CSS and inspects its contents — fully offline, no Figma account, no Dev Mode, no paid MCP service.

Trade-off, up front: the output is a faithful static reconstruction (layout, text, colors, gradients, vectors, images) — not pixel-perfect, and not interactive.

Why

Figma's Dev Mode MCP server requires a paid seat. The .fig format, however, is a ZIP container carrying a self-describing Kiwi binary payload — readable offline once you speak its language. fig2web speaks it.

The container/wire format notes below were reverse-engineered from real files (420-screen baseline, 100% text extraction, adversarially verified).

Related MCP server: figma-mcp-server

Install

1. Install — requires Node.js >= 18, nothing else:

npm i -g fig2web

2. Convert a file:

fig2web "My Design.fig"

3. Open the result — open My\ Design-html/index.html (macOS), xdg-open (Linux), start (Windows):

You get a gallery of every screen plus screens/*.html and extracted assets/. No Figma account required.

No global install? npx -y fig2web "My Design.fig" works too.

CLI

fig2web design.fig                   # -> design-html/ (gallery + screens + assets)
fig2web design.fig -o out/           # custom dir
fig2web design.fig --inspect         # analysis reports (tree/texts/palette/…)
fig2web design.fig --json            # machine-readable summary on stdout

The HTML bundle:

design-html/
  index.html        # gallery with scaled live thumbnails
  screens/*.html    # one page per screen, absolutely-positioned HTML/CSS
  assets/           # image fills extracted by sha1
  styles.css

MCP

Ships a stdio MCP server. After npm i -g fig2web:

claude mcp add fig2web -- fig2web-mcp

Claude Desktop claude_desktop_config.json:

{ "mcpServers": { "fig2web": { "command": "fig2web-mcp" } } }

Tools: convert_fig_to_html { fig_path, out_dir? }, inspect_fig { fig_path }.

API

import { convertToHtml, inspectFig } from 'fig2web';

const res = convertToHtml('design.fig', { outDir: 'out' });
// { outDir, screens: 420, stats: {...}, screenList: [...] }

const { summary } = inspectFig('design.fig');
// pages, screens, texts, colors, fonts, variables (tokens!), components, assets

How .fig files work (format notes)

A .fig file is a ZIP container:

file.fig = ZIP {
  canvas.fig     # the payload
  meta.json      # { schemaVersion, exportedAt: ISO-8601, ... }
  thumbnail.png
  images/<sha1>  # image binaries; name = content sha1, no extension
}

canvas.fig binary layout:

"fig-kiwi" (8B magic; siblings: fig-jam. FigJam, fig-deck Slides, fig-makee Make)
u32 LE version               # 106 observed
chunks: [u32 len][payload]*  # payload sniffed: zstd magic 28 B5 2F FD, else raw-deflate
  chunk 0 = Kiwi binary schema, raw-deflate
  chunk 1 = message { nodeChanges[], blobs[] }

The message conforms to a self-describing Kiwi schema embedded as chunk 0 — every file carries its own schema; decoded with kiwi-schema (Evan Wallace).

nodeChanges essentials

  • Flat array — the tree is rebuilt from guid (sessionID:localID) + parentIndex, ordered by ascending position (numeric string, stable sort).

  • phase: CREATED/UPDATED last-wins; DELETED removes.

  • Field names as observed on the wire: guid, parentIndex, phase, type, name, visible, size {x,y}, transform (2x3 matrix), cornerRadius, rectangleTopLeftCornerRadius (…Right/Bottom pairs), opacity, mask, clipContent, blendMode, effects[] (DROP_SHADOW → box-shadow), fillPaints[]/strokePaints[], textData.characters, fontSize, fontName {family,style}, lineHeight, letterSpacing, textAlignHorizontal, fillGeometry[]/strokeGeometry[] (commandsBlob indexes blobs[]), textData vs variableDataValues (VARIABLE nodes → design tokens via variableResolvedType), variableResolvedType, variableDataValues.entries[].variableData.value.colorValue.

paint → output mapping

  • SOLID → css color; GRADIENT_* → css gradients (inverse-matrix angle)

  • IMAGE paint: p.image.hash is 20 raw bytes → hex string = filename in images/

  • Vectors: blobs = [u8 cmd][LE f32*], cmds 0=Z 1=M 2=L 3=Q 4=C → inline SVG

  • DROP_SHADOW → box-shadow; mask nodes donate corner radius to next sibling

Limitations

  • Static only: no prototyping, interactions, or auto-layout reflow.

  • Masks/booleans are visual approximations.

  • Google-Fonts linkage when identified; proprietary fonts fall back to system.

  • Faithful, not pixel-perfect.

  • kiwi-schema — kiwi format tools

  • fig2sketch — .fig → Sketch converter

  • Figma's own .fig thumbnailer… (official docs are sparse; this README + source are the reference.)

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables interaction with Figma designs through the Figma API, allowing users to export images in multiple formats, extract style data and CSS, analyze design elements, and retrieve SVG code from Figma files. Supports batch operations and comprehensive design element analysis including images, vectors, and components.
    7
    23 npm
    11
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables developers to extract and organize Figma design files, including complete node data (tree structure and images) for AI understanding and code generation.
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Enables offline reading and rendering of Figma .fig files, allowing AI agents to extract design specs, export assets, and generate code without needing the Figma API or network access.
    26
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables agents to extract, inspect, search, and bundle design context from local Figma .fig files entirely offline, exposing frame summaries, node context, style tokens, assets, vector SVGs, and visual-match review via MCP.
    MIT