Turn Figma SVG exports into email-safe, pixel-faithful HTML assets: SVG forensics, asset extraction, effect baking, render+diff verification, and an email-robustness linter.
Project description
figforge
Turn Figma SVG exports into email-safe, pixel-faithful HTML assets.
figforge is the engine distilled from a real Figma → HTML-email rebuild. The one-off fixes that job needed — a baked hero image, transparent white icons, a silhouette rim-glow, a cut-out aligned flush to a band — turned out to be instances of a handful of general operations. figforge is those operations, so the next email is a short recipe, not a forensic expedition.
Why it exists
Browsers render Figma's CSS faithfully; email clients do not. Outlook's Word
engine ignores background-size, CSS gradients and position; Gmail strips
base64 images and clips large HTML. The reliable move is to bake design into
flat images and keep the HTML to tables — but doing that 1:1 with the design,
by hand, is fiddly. figforge automates the fiddly parts and verifies the result.
The five parts
| Module | What it does |
|---|---|
forensics |
Parse a Figma SVG into a spec: rects, gradient stops, drop-shadow filters, image-pattern crops, embedded rasters. |
assets |
Rasterise SVG layers (with optional recolour), decode embedded <image> rasters, content-crop, clean alpha, de-matte. |
effects |
Gradient bands (hard edges), radial + silhouette-rim glows from a shadow spec, and bake() to flatten layers into one image. |
render |
Render an SVG or HTML email to PNG; side_by_side + diff. |
lint |
Flag email-robustness hazards (background-size:cover, inline-block banner shrink, base64 images, missing <img width>, flex/grid, web-font fallback). |
Install
pip install figforge # core: forensics, image ops, effects, lint
pip install "figforge[render]" # + SVG/HTML rendering
The [render] extra (cairosvg, weasyprint, pymupdf) needs system libraries
that pip can't install:
# Debian/Ubuntu
sudo apt-get install libcairo2 libpango-1.0-0 libpangocairo-1.0-0
# macOS
brew install cairo pango
lint and forensics (and the pure-Pillow helpers) work without the extra.
Quick start
figforge lint email.html # catch client gotchas
figforge rasterize icon.svg --width 48 --recolor FFFFFF -o icon.png
figforge extract master.svg --image-id image1 -o photo.png # decode an embedded raster
figforge render-svg master.svg --width 680 -o target.png # 1:1 reference
figforge render-html email.html --width 680 --height 1862 -o actual.png
figforge diff target.png actual.png -o heat.png
import figforge as ff
doc = ff.parse_svg("master.svg")
band = next(r for r in doc.rects if doc.gradient_for(r)) # a gradient stripe
grad = doc.gradient_for(band)
shadow = next(s for s in doc.shadows.values() if s.color == (255, 255, 255))
man = ff.dematte(ff.clean_alpha(ff.extract_embedded_image("master.svg", "image1")))
glow = ff.rim_glow(man, shadow, source_card_px=(300, man.width))
hero = ff.bake([(glow, (0, 0)), (man, (0, 0))], size=man.size, background="#2D2C2C")
hero.save("hero.png")
A complete, dependency-light example is in examples/quickstart.py.
Principles it encodes
- Bake, don't layer. One flat
<img>renders identically everywhere; CSS backgrounds +cover+ overlap do not. - Pin widths. Give images and banner tables explicit pixel widths; never
rely on
inline-blockto fill width. - No base64 in email. Host assets; reference them by https URL.
- Verify against the source. Render the design and diff — don't trust an in-app preview, which lies about Outlook/Gmail.
Use it as an agent skill
figforge ships an Agent Skill that teaches AI coding
agents the full Figma → email-safe HTML method (the figforge engine plus the
client-robustness principles). Install it into your agent:
npx skills add AzalDaniel/FigForge --skill figma-to-email-html
The skill (skills/figma-to-email-html/) is the method; this package is the
engine it drives.
Contributing
Issues and PRs welcome — especially new lint rules for client gotchas you've hit. See CONTRIBUTING.md and the Code of Conduct. Where this is headed — a Figma REST ingester, an intermediate representation, DTCG token extraction and an MJML emitter — is in ROADMAP.md.
License
Apache License 2.0. The Apache-2.0 grant includes an explicit patent license, which is the safer default for a rendering/diffing tool.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file figforge-0.1.0.tar.gz.
File metadata
- Download URL: figforge-0.1.0.tar.gz
- Upload date:
- Size: 24.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c29b83e887b54d14488367d4434ebb3dfcf56f9a9451114e1d97ad23f363883a
|
|
| MD5 |
85ecef127b23714553f802eaf32d493d
|
|
| BLAKE2b-256 |
5b5b3b0172368440f845481a9cc15e85e81a15b8a7556fcde810db5f17c75f16
|
Provenance
The following attestation bundles were made for figforge-0.1.0.tar.gz:
Publisher:
release.yml on AzalDaniel/FigForge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
figforge-0.1.0.tar.gz -
Subject digest:
c29b83e887b54d14488367d4434ebb3dfcf56f9a9451114e1d97ad23f363883a - Sigstore transparency entry: 1767733462
- Sigstore integration time:
-
Permalink:
AzalDaniel/FigForge@0f1f7b584bae9a90f89345db7bc4609fc7e89756 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AzalDaniel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0f1f7b584bae9a90f89345db7bc4609fc7e89756 -
Trigger Event:
push
-
Statement type:
File details
Details for the file figforge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: figforge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cb62b09c5587fbd1632289f8d1a947907a3a3741792f437777a7ab952d49f09
|
|
| MD5 |
2a26ff136b1a3106a6cab1deb4f33e35
|
|
| BLAKE2b-256 |
fdec97a03c25f0125158c61a66bd009fc679f4c29889fdaf4b67ec5f443dc387
|
Provenance
The following attestation bundles were made for figforge-0.1.0-py3-none-any.whl:
Publisher:
release.yml on AzalDaniel/FigForge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
figforge-0.1.0-py3-none-any.whl -
Subject digest:
9cb62b09c5587fbd1632289f8d1a947907a3a3741792f437777a7ab952d49f09 - Sigstore transparency entry: 1767735232
- Sigstore integration time:
-
Permalink:
AzalDaniel/FigForge@0f1f7b584bae9a90f89345db7bc4609fc7e89756 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/AzalDaniel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0f1f7b584bae9a90f89345db7bc4609fc7e89756 -
Trigger Event:
push
-
Statement type: