Skip to main content

React Three Fiber and drei (three.js) wrapped as Reflex components.

Project description

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.1.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 graphCanvas, 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reflex_threejs-0.1.0.tar.gz (38.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reflex_threejs-0.1.0-py3-none-any.whl (38.7 kB view details)

Uploaded Python 3

File details

Details for the file reflex_threejs-0.1.0.tar.gz.

File metadata

  • Download URL: reflex_threejs-0.1.0.tar.gz
  • Upload date:
  • Size: 38.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for reflex_threejs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4d8ece5086661bba8eee6e64904e331b3e12efe53a8f6e4b730903e991c64b42
MD5 d56974585bf2e5d8c60c76f0c35d9b16
BLAKE2b-256 7a26c9e567ba0008793bbddb04791a337111d2478119af9885f25bd4e93702e2

See more details on using hashes here.

File details

Details for the file reflex_threejs-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: reflex_threejs-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for reflex_threejs-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 319f39a59952e78d186487058f22c962875fb1cf3e2fdaa5b11228bf5686b1c6
MD5 35e2c0278e63bf7d67d165369c5a1e99
BLAKE2b-256 3de092ca283a3be8adf9a8d9a14b3842c3d0a729875eaa63c8be9b31fbbacf0a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page