Fig Foundry
A WYSIWYG figure studio for matplotlib.
Drag your data onto a free canvas, compose publication figures, and export the
exact Python that draws them. The preview is the generated code, executed — so
what you see is what the .py produces.
Install · Tour · Measured · How it works · Command line
A nine-panel figure composed on the canvas from one dataset's signals. Every panel
is a real matplotlib Axes placed by explicit coordinates, so it can sit
anywhere, at any size.
You have the data; Fig Foundry is the table you lay it out on. Load a dataset, drag a signal onto the canvas and it becomes a plot. Move and resize plots with snapping, nudge and style each one in the inspector, add the second series or the σ-band, and when it is right, export the code. Because the preview is rendered by running that very code, there is no "close enough" — the figure you arrange and the script you ship are the same drawing.
|
WYSIWYG by construction One drawing path. The browser preview executes the generated .py, so the
export is byte-for-byte what you see. There is no second renderer to drift.
|
The atom is data A figure is a scene of plots over named signals. Drag a signal to make a plot; drop it on one to overlay a line, a σ-band, or error bars. Nothing is hand-drawn. |
|
Twenty-three plot types Line, step, scatter, grouped scatter, bar, box, violin, histograms, hexbin, image, contour, pcolormesh, vector fields, streamplot, decision boundary, pie, polar, and three 3-D types. |
Private, on your machine A local web app. Your datasets, figures and exports live in ~/.figfoundry;
nothing you load is sent anywhere. Pickle files load through a whitelist, not a
deserializer.
|
A quick tour
Light, dark, or your system's. The interface re-skins; the figure itself stays on a white artboard, so the artwork is publication-clean in either theme.
3-D, to your angle. Double-click a 3-D plot to open the viewfinder: drag to rotate, scroll to zoom, or use the sliders. Accept writes the camera back to the figure and, with it, into the exported code.
|
Export the code and the figure. The standalone |
Your figures. Every canvas is saved with a live thumbnail; open, duplicate or delete from here. Each one is tied to the dataset it was built from. |
Measured, not claimed
Every figure below is reproducible from the repository: the test suite, the CI runs, and the security probes.
| Plot types, each verified preview-identical to its export | 23 of 23 (tests) |
| Tests, passing on Linux and Windows, Python 3.10 and 3.12 | 152 (CI) |
| Malicious pickle payloads the whitelist refuses to load | 18, including np.fromfile, np.load, __import__, eval, exec (tests) |
| Separate renderers the export can drift from | 0 — the preview executes the export |
What it does
- Composes on a free canvas. Plots are explicit rectangles, not a fixed grid, so they go anywhere and at any size. Move, resize with snapping, nudge with the arrow keys, and multi-select (Shift+click) to move, nudge or delete a group at once.
- Twenty-three plot types. Line, step, scatter, grouped scatter (color-by-class), bar and horizontal bar, histogram, box plot, violin plot, 2-D histogram, hexbin, image, contour (filled and lines), pcolormesh, vector field, streamplot, decision boundary (a surface with the points on top), pie, polar, 3-D scatter, 3-D surface and 3-D wireframe.
- Styles every element. Per plot: the data, plot type, color, line and marker, σ-band and error bars, ticks and tick labels, limits and scale, spines, title, colormap and colorbar, and artists — vertical and horizontal lines, text, annotations, arrows, boxes, circles, ellipses, polygons and legends. Figure-level axis labels, legend, suptitle and free text.
- Suggests accessible color. One click applies the colorblind-safe Okabe–Ito palette to a plot's series; a palette menu (Okabe–Ito, Bright, Viridis, Plasma, Cividis) is available through the API.
- Speaks LaTeX. Labels, titles and text take mathtext, so
$x_0$and$\alpha$render. - Lays out for you. Arrange in a grid, align and distribute a selection, set margins and gaps, and sync axis ranges across every plot at once.
- Exports clean code. The figure as a standalone
.pythat references the dataset, plus the rendered figure as PNG, SVG or PDF. The 3-D camera, the colors, the ticks — all of it is in the code. - Remembers your setup. Themes, and the 3-D rotate/zoom direction, persist; figures,
datasets and exports live in
~/.figfoundry.
How it works
flowchart LR
data(["Your data<br/>.npz / .pkl / .csv"]) --> spec["The spec<br/>a scene: canvas,<br/>plots, artists"]
spec --> code["codegen<br/>a standalone .py"]
code --> run["execute the .py"]
run --> view(["Preview<br/>(what you see)"])
code --> out(["Export<br/>.py + PNG / SVG / PDF"])
- One path, both ends.
codegen_canvasturns the spec into a plain.py— a list offig.add_axes([...])calls over the dataset. The preview is that file, run; the export is that file, saved. They cannot disagree, because they are the same code. - The spec is the source of truth. A figure is a JSON scene (canvas, plots, artists). The browser edits it; the backend renders it by executing the generated code. Save it and it is a canvas you can reopen, duplicate and drive over the API.
- Data stays data. Signals are arrays, referenced by name. The exported code loads the dataset and indexes it — the numbers in the figure are the numbers in your file, unedited.
Data
A dataset is a named set of signals (arrays), 1-D and 2-D. Load one with Load data… (pick an existing dataset, or upload a file):
.npz— a numpy zip of named arrays. Safe by construction..pkl— a Python pickle, loaded through a whitelist unpickler that permits only numpy arrays and plain containers. A pickle that tries to run code —os,subprocess,eval,np.fromfileand the rest — is refused, not executed..csv— a table with a header row; each numeric column becomes a signal.
Command line
The same engines run from the shell, for scripting and automation:
figfoundry # start the web app (default)
figfoundry serve # ...with flags: --port, --host, --no-browser
figfoundry list # list saved figures
figfoundry new # create a blank figure, print its slug
figfoundry export SLUG [--out PATH] # write a figure's .py
figfoundry render SLUG [--format png|svg|pdf] [--out PATH]
figfoundry datasets # list available datasets
Install
uv tool install figfoundry # puts the `figfoundry` command on your PATH
figfoundry # → opens http://127.0.0.1:8037
Or:
pip install figfoundry
# or from this repository:
uv tool install figfoundry --from "git+https://github.com/ductai199x/figfoundry.git"
Python 3.10 or newer. It runs wherever Python and a browser do.
Development
uv sync --extra dev
uv run --extra dev pytest -q # 152 tests
uv run --with ruff ruff check . # lint
uv run figfoundry serve # the app
The suite covers the WYSIWYG invariant for every plot type, the pickle whitelist, dataset I/O (npz/pkl/csv), vector export, the CLI, and the API through a test client. CI runs it, plus the build and an artifact check, on Linux and Windows for Python 3.10 and 3.12 (.github/workflows/ci.yml).
License
Copyright (C) 2026 Tai Duc Nguyen.
Fig Foundry is licensed under the MIT License: use it, study it, change it and share it. The one sample dataset it ships is synthetic; your own data never leaves your machine.
Metadata
Release files for figfoundry 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| figfoundry-0.3.0.tar.gz | 198.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| figfoundry-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 278.4 kB
Release files / figfoundry-0.3.0.tar.gz
| Download URL | figfoundry-0.3.0.tar.gz |
|---|---|
| Size | 198.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3c0c577c4d26ec340f3b65027f6cb4836dfca2160103ebaeec3af7b7a5b466f8
|
|
BLAKE2b-256 checksum How to use checksums |
614be4865422f5fcd06d772630f7ba29d42764f883d82d88a778f80f4d9133fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / figfoundry-0.3.0-py3-none-any.whl
| Download URL | figfoundry-0.3.0-py3-none-any.whl |
|---|---|
| Size | 79.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
491f357ed0d3216652a50cfbb80c53d5f1866db4daabaf9b5497e213ea3a66bf
|
|
BLAKE2b-256 checksum How to use checksums |
fe5416a0488c3ca016f08c703327e6ea4c3981e95dd1f1c1718289408282716f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for figfoundry 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.