Skip to main content

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 mirroring rx.*.
  • SSR-safe — the WebGL Canvas is 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

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)

Source distribution for reflex-threejs 0.2.0
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)

Table of built distributions (wheels) for reflex-threejs 0.2.0
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page