reflex-threejs
Interactive three.js for Reflex — in pure Python.
reflex-threejs wraps React Three Fiber (the React
renderer for three.js) and its helper library
drei as idiomatic Reflex components. Build
3D scenes — product viewers, data visualization, generative art, simulations —
without writing a line of JavaScript.
Status: alpha (v0.2.0) — foundation, core components, demo app and full SDD artifacts are in place. See the roadmap.
Why
three.js is the standard for web 3D, but it is imperative and JavaScript-only. React Three Fiber makes it declarative — yet still React/JSX. Reflex compiles Python to React, so wrapping R3F + drei once makes the entire three.js model available to Python developers as ordinary Reflex components.
import reflex as rx
from reflex_threejs import three
def index() -> rx.Component:
return rx.box(
three.canvas(
three.ambient_light(intensity=0.6),
three.directional_light(position=[5, 5, 5], intensity=1.0),
three.mesh(
three.box_geometry(args=[1.5, 1.5, 1.5]),
three.mesh_standard_material(color="#6366f1", metalness=0.3),
),
three.orbit_controls(auto_rotate=True),
camera={"position": [3, 3, 3], "fov": 50},
),
width="100%",
height="600px",
)
app = rx.App()
app.add_page(index)
Features
- Declarative scene graph —
Canvas, meshes, groups, points, lines, sprites, instancing — all from Python. - Full primitive surface — 22 geometries, 14 materials, 6 lights, cameras and
helpers, each accepting three.js constructor
args. - Interaction — pointer events (
on_click,on_pointer_over, …) routed to Reflex event handlers. - State binding — drive any prop (color, transform, …) with a Reflex state Var.
- drei helpers — OrbitControls, Environment/Stage, ContactShadows, Sky, Stars, Text, Html overlay, Float, animated materials and declarative GLTF loading.
- Ergonomic API — flat factories or the
three.*namespace mirroringrx.*. - SSR-safe — the WebGL
Canvasis dynamically imported (ssr:false).
Installation
Not yet on PyPI (planned for v0.2). For now, install from source.
git clone https://github.com/ecrespo/reflex-threejs.git
cd reflex-threejs
pip install -e .
Requires Reflex ≥ 0.7 (React 19). On an older Reflex/React 18 stack, see the compatibility guide.
Run the demo
The demo app showcases nine scenes spanning the main three.js example categories.
cd reflex_threejs_demo
pip install -r requirements.txt # installs reflex + the local package
reflex init # first run only
reflex run
Then open http://localhost:3000.
| Route | Scene | Demonstrates |
|---|---|---|
/ |
Hello Cube | Canvas, lights, mesh, OrbitControls |
/geometries |
Geometry Gallery | built-in geometries |
/materials |
Materials | material types + environment |
/lights |
Lights | ambient/directional/point/spot + shadows |
/interactive |
Interactive | click-to-recolor, hover-to-scale (state events) |
/particles |
Particles | points + buffer geometry |
/staging |
Staging & drei | Stage, ContactShadows, distort material |
/text |
3D Text | drei Text + Float |
/space |
Space | drei Stars, emissive material |
Two ways to use the API
# 1. Namespace (rx-style)
from reflex_threejs import three
three.canvas(three.mesh(three.box_geometry(), three.mesh_normal_material()))
# 2. Flat factories
from reflex_threejs import canvas, mesh, box_geometry, mesh_normal_material
canvas(mesh(box_geometry(), mesh_normal_material()))
drei helpers live under three.drei.* (common ones promoted to three.*).
Documentation
- Usage guide — host elements,
args, events, state binding. - Compatibility guide — React 18/19, R3F v8/v9.
- Spec-Driven Design (SDD) artifacts — the design of this project:
Project layout
reflex-threejs/
├── custom_components/reflex_threejs/ # the component library (Reflex convention)
│ ├── base.py canvas.py objects.py
│ ├── geometries.py materials.py lights.py
│ ├── cameras.py drei.py namespace.py
│ ├── *.pyi py.typed # generated type stubs + PEP 561 marker
│ └── __init__.py
├── reflex_threejs_demo/ # runnable demo app
├── tests/ # contract + quality-gate tests
├── scripts/gen_pyi.py # regenerate the .pyi stubs
├── docs/
│ ├── sdd/ # SDD artifacts
│ └── guides/ # usage & compatibility
├── Makefile pyproject.toml README.md LICENSE CHANGELOG.md
This is the layout produced by reflex component init (package under
custom_components/, a sibling demo app), so it builds and publishes with the
standard Reflex custom-component tooling.
How it works (in one paragraph)
Canvas is wrapped as a Reflex NoSSRComponent, so three.js initializes only in
the browser. Everything inside it — <mesh>, <boxGeometry>,
<meshStandardMaterial>, <ambientLight> — are React Three Fiber host
elements: lowercase intrinsic JSX tags resolved by R3F's reconciler at runtime,
requiring no import. We model these as Reflex components with library = None and
_is_tag_in_global_scope = True, so Reflex emits the tag as a string intrinsic
(jsx("mesh", …)) rather than an undefined component reference. drei helpers are
real exported components, so they declare the @react-three/drei package and an
explicit tag. See the architecture doc for details.
Building & publishing (Reflex custom component)
reflex-threejs is a standard Reflex custom component:
the package lives under custom_components/, ships .pyi type stubs and a
py.typed marker, and builds with the usual tooling.
make install # pip install -e ".[dev]"
make check # ruff + pytest
make stubs # regenerate .pyi stubs after changing any component props
make build # regenerate stubs, then build wheel + sdist, then twine check
make publish # upload to PyPI (needs credentials)
make build is the recommended path: it scopes stub generation to the package.
The official reflex component build does the same two steps (stub generation +
python -m build), but it recursively scans every top-level directory, so run
it only from a clean checkout without local virtualenvs in the tree:
reflex component build # produces dist/ with stubs
python -m twine upload dist/* # or: reflex component share
Bump version in pyproject.toml before publishing. The CI package job
rebuilds the stubs, verifies the committed ones are current, and runs
twine check on every push.
Contributing
Issues and PRs welcome. The design lives in docs/sdd;
please keep specs and code in sync (it's in the Definition of Done). After
changing any component's props, run make stubs and commit the updated .pyi.
License
MIT © 2026 Ernesto Crespo.
Acknowledgements
Built on the work of three.js, pmndrs/react-three-fiber, pmndrs/drei and Reflex.
Metadata
Release files for reflex-threejs 0.2.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 | Actions |
|---|---|---|---|---|
| reflex_threejs-0.2.0.tar.gz | 40.1 kB | Without provenance | Details for reflex_threejs-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| reflex_threejs-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for reflex_threejs-0.2.0-py3-none-any.whl |
Total release size: 79.7 kB
Release files / reflex_threejs-0.2.0.tar.gz
| Download URL | reflex_threejs-0.2.0.tar.gz |
|---|---|
| Size | 40.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9dd0ff80e00ba4bedc667bb246f49ef5026dd67255198c5d3a429a745a504e52
|
|
BLAKE2b-256 checksum How to use checksums |
0e95eb07642e8fe52671fb65f81572f7cc07585c2492babd64c5b70c135b7926
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / reflex_threejs-0.2.0-py3-none-any.whl
| Download URL | reflex_threejs-0.2.0-py3-none-any.whl |
|---|---|
| Size | 39.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
31a950996a0f17ccb742a790dc4e958c2aff44400a34558a2da79cdc7c9a00ec
|
|
BLAKE2b-256 checksum How to use checksums |
166177f2437656ad1cc0f3fbbec152efddd1c8851d35e153cbb0d25c9a8e254d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Security for reflex-threejs 0.2.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.