facett
facett's Rust UI components, compiled to WebAssembly and drawn on WebGPU — graphs to 100 000 nodes, maps (2-D and 3-D OSM), tables, charts, timelines, a docs viewer, a 3-D model viewer and a simulation view — shipped as a Python package with a host-agnostic loader page. Every pixel is drawn by the Rust components; there is no JavaScript renderer and no Python renderer.
- Live demo (the native facett demo, in the browser): https://nordisk.codeberg.page/facett/
- Source: https://git.gunnar.rs/nordisk/facett
Install
pip install facett # the components + loader, no dependencies
pip install 'facett[streamlit]' # + Streamlit support (facett.streamlit)
import facett never imports Streamlit; only facett.streamlit does, and it says which extra to install when Streamlit is missing.
Streamlit
import streamlit as st
from facett.streamlit import facett_component, is_data_driven
st.title("facett in Streamlit")
facett_component("table", data={
"columns": ["repo", "lang", "crates"],
"rows": [["facett", "rust", "71"], ["korp", "rust", "12"]],
})
# graph components generate their data INSIDE the wasm — 100 000 nodes never cross
# from Python:
facett_component("graphpan", data={"generate": {"source": "sbm", "size": 100_000, "seed": 1}})
facett_component(name, *, data=None, height=520, key=None, dev=False, nav="labels") mounts one component in an iframe served from the installed package. A full app built on it is the facett-demo package (pip install facett-demo, then run facett-demo).
Any other host
import facett
facett.assets_dir() # directory holding index.html + every bundle's wasm, JS glue, manifest
facett.manifest() # [{name, description, group, title, data_driven, bundle, generate}, ...]
facett.bundles() # the routing table: which bundle (core/docs/model3d/sim) holds which component
facett.build_info() # identity of the INSTALLED artifact: version, wasm size, component count
Serve assets_dir() and load index.html:
index.html?component=table&data=<url-encoded JSON>, or post{type: "facet:render", args: {component, data, height}}to the frame;index.html?component=<name>&events=<SSE url>— a live feed: every event'sdatais one payload;{"done": true}ends it and keeps the last frame up,{"error": "<why>"}shows the host's own words.
When no host has named a component the loader WAITS and draws nothing — it never shows a fixture where a caller's data was expected.
Requirements
- A browser with WebGPU, in a secure context (
localhostor https — and every ancestor frame must be one too). Chrome/Edge on Linux need--enable-unsafe-webgpu --enable-features=Vulkan. - The wasm runs each component's CPU preparation on one thread (wasm32 has no threads here); rendering is on the GPU.
Versions
0.2.0 is the first release under this name. It was facet-wrapped-web (0.1.x); the old import name facet_wrapped_web still works in 0.2.x as an alias that warns, and is removed in 0.3.0.
License
MIT (the text is in LICENSE, shipped in this package). Versions published up to and including 0.2.0 (crates.io 0.1.x/0.2.0 and PyPI facett/facett-demo 0.2.0) were released under MIT OR Apache-2.0 and stay so. From 0.2.1 facett is MIT only.