How to Export Motion-Enabled HTML Diagrams in a Static State
Appending ?motion=static to the diagram URL freezes the animation before rasterization, ensuring the exported SVG or PNG contains all semantic elements while hiding motion controls.
The cathrynlavery/diagram-design repository treats diagrams as self-contained HTML files that may include optional motion controllers. When you need to export motion-enabled HTML diagrams in a static state for slides, Figma, or documentation, the repository enforces a strict contract that guarantees pixel-perfect fidelity and accessibility compliance.
Understanding the Motion Controller Architecture
Motion-enabled diagrams in this system rely on declarative attributes rather than imperative JavaScript playback.
The Template Structure
Every motion diagram starts from skills/diagram-design/assets/template-motion.html. This canonical controller must be copied verbatim into any diagram requiring animation support. The template establishes the root element with data-motion-mode attributes that define temporal behavior.
Motion Modes and Data Attributes
The Animation reference at skills/diagram-design/references/animation.md defines three motion modes:
- step: Advance through states via discrete increments
- reveal: Progressive disclosure of diagram layers
- loop: Continuous cyclic animation
To freeze these animations for static export, the system asserts that the motion root carries data-frame="static" after loading the URL with ?motion=static. This attribute signals that all semantic elements are visible while decorative motion curves and control chrome are hidden.
Exporting Static SVG from Motion-Enabled HTML
The SVG export procedure follows the contract outlined in skills/diagram-design/references/export.md:
- Extract the first
<svg>element using a multiline regex, deliberately dropping surrounding editorial markup (cards, headers, navigation) - Ensure standalone XML compliance by injecting
xmlns="http://www.w3.org/2000/svg"and preserving the originalviewBox - Maintain accessibility metadata by keeping
<title>and<desc>elements - Inject a
<defs><style>block that imports Google Fonts with XML-escaped entities (&instead of&) - Prepend the XML declaration
<?xml version="1.0" encoding="UTF-8"?> - Write the output adjacent to the source (
diagram.html→diagram.svg)
This extraction targets only the diagram itself, ensuring clean reusability across design tools.
Generating Static PNG with Playwright
For raster output, the exporter renders the original HTML rather than the extracted SVG to preserve exact font loading and CSS inheritance:
from playwright.sync_api import sync_playwright
import sys, pathlib
src, out = sys.argv[1], sys.argv[2]
scale = int(sys.argv[3]) if len(sys.argv) > 3 else 2
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(device_scale_factor=scale)
page.goto(f"file://{pathlib.Path(src).resolve()}?motion=static")
page.wait_for_load_state("networkidle")
page.locator("svg").first.screenshot(path=out, omit_background=True)
browser.close()
Key implementation details:
- The
?motion=staticquery parameter triggers the static frame mode beforedocument.fonts.readyresolves omit_background=Trueensures transparent backgrounds for overlay usedevice_scale_factorsupports--scale=1|2|3for 1x, 2x, or 3x resolution outputs
Command-Line Interface
Invoke the export workflow via the slash command defined in commands/export-diagram.md:
# Export both SVG and PNG (default behavior)
/diagram-design:export-diagram path/to/diagram.html
# Export only SVG
/diagram-design:export-diagram path/to/diagram.html --svg-only
# Export high-resolution PNG only
/diagram-design:export-diagram path/to/diagram.html --png-only --scale=3
# Generate registry sidecar metadata
/diagram-design:export-diagram path/to/diagram.html --registry
The command validates prerequisites before execution. For PNG generation, it verifies Playwright installation and surfaces exact install instructions if missing (pip install playwright followed by playwright install chromium).
Verification and Quality Assurance
Before exporting motion-enabled diagrams, run the verification script to ensure static compliance:
python3 scripts/verify-motion.py path/to/diagram.html
This script checks that:
- The
data-motion-modeattribute exists on the root element - Loading
?motion=staticcorrectly setsdata-frame="static" - The reduced-motion fallback is properly declared
The verification guarantees that exported artifacts match the repository's accessible-SVG contract, preventing animated states from leaking into documentation assets.
Edge Cases and Constraints
The exporter refuses to process files that violate these constraints:
- Gallery files:
assets/index.htmlcontains multiple diagrams and is explicitly excluded - Missing SVG blocks: Files lacking an
<svg>element trigger an error - Registry-only exports without IDs: Requests for
--registryrequiredata-block-idattributes on diagram elements to generate valid metadata sidecars
Summary
- Append
?motion=staticto freeze animations and assertdata-frame="static"before capture - SVG extraction isolates the first
<svg>block, injects XML namespaces, and preserves Google Fonts with escaped entities - PNG rasterization uses Playwright with
device_scale_factorscaling andomit_background=Truefor transparency - Run
scripts/verify-motion.pyto validate static compliance before batch exports - The export workflow is defined in
skills/diagram-design/references/export.mdandcommands/export-diagram.md
Frequently Asked Questions
How does the exporter handle fonts in static SVG output?
The extractor parses the HTML's Google Fonts imports and injects them into a <defs><style> block within the SVG, ensuring text renders correctly even offline. Ampersands in font URLs are XML-escaped to & to prevent parsing errors.
Why does PNG export load the HTML instead of the extracted SVG?
Rendering the original HTML guarantees that @font-face declarations and CSS custom properties resolve exactly as the author intended. This method waits for document.fonts.ready and networkidle, ensuring pixel-perfect fidelity that direct SVG rasterization might miss due to missing font contexts.
What motion modes support static export?
The step, reveal, and loop modes defined in skills/diagram-design/references/animation.md all support static export. When ?motion=static is present, the motion controller collapses temporal states into a single comprehensive frame marked by data-frame="static".
Can I export multiple diagrams from a gallery page?
No. The exporter explicitly refuses to operate on assets/index.html or any file containing multiple diagram roots. You must target individual HTML files containing single <svg> elements to ensure clean, isolated static assets.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →