ReactPy is a Python library for building user interfaces without JavaScript. It creates React-like components that render to web pages using a Python-to-JavaScript bridge.
Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
IMPORTANT: This package uses modern Python tooling with Hatch for all development workflows. Always use Hatch commands for development tasks.
BUG INVESTIGATION: When investigating whether a bug was already resolved in a previous version, always prioritize searching through docs/source/about/changelog.rst first before using Git history. Only search through Git history when no relevant changelog entries are found.
Prerequisites:
- Install Python 3.11+ from https://www.python.org/downloads/
- Install Hatch:
pip install hatch - Install Bun JavaScript runtime:
curl -fsSL https://bun.sh/install | bash && source ~/.bashrc - Install Git
Initial Setup:
git clone https://github.com/reactive-python/reactpy.git
cd reactpyInstall Dependencies for Development:
# Install core ReactPy dependencies
pip install fastjsonschema requests lxml anyio typing-extensions
# Install ASGI dependencies for server functionality
pip install orjson asgiref asgi-tools servestatic uvicorn fastapi
# Optional: Install additional servers
pip install flask sanic tornadoBuild JavaScript Packages:
hatch run javascript:build-- takes 15 seconds. NEVER CANCEL. Set timeout to 60+ minutes for safety.- This builds three packages: event-to-object, @reactpy/client, and @reactpy/app
Build Python Package:
hatch build --clean-- takes 10 seconds. NEVER CANCEL. Set timeout to 60+ minutes for safety.
Run Python Tests:
hatch test --parallel-- takes 10-30 seconds for basic tests. NEVER CANCEL. Set timeout to 2 minutes for full test suite. All tests must always pass - failures are never expected or allowed.hatch test --parallel --cover-- run tests with coverage reporting (used in CI)hatch test --parallel -k test_name-- run specific testshatch test --parallel tests/test_config.py-- run specific test files
Run Python Linting and Formatting:
hatch fmt-- Run all linters and formatters (~1 second)hatch fmt --check-- Check formatting without making changes (~1 second)hatch fmt --linter-- Run only lintershatch fmt --formatter-- Run only formattershatch run python:type_check-- Run Python type checker (~10 seconds)
Run JavaScript Tasks:
hatch run javascript:check-- Lint and type-check JavaScript (10 seconds). NEVER CANCEL. Set timeout to 30+ minutes.hatch run javascript:fix-- Format JavaScript codehatch run javascript:test-- Run JavaScript tests
Interactive Development Shell:
hatch shell-- Enter an interactive shell environment with all dependencies installedhatch shell default-- Enter the default development environment- Use the shell for interactive debugging and development tasks
Always manually validate any new code changes through these steps:
Basic Functionality Test:
# Add src to path if not installed
import sys, os
sys.path.insert(0, os.path.join("/path/to/reactpy", "src"))
# Test that imports and basic components work
import reactpy
from reactpy import component, html, use_state
@component
def test_component():
return html.div([
html.h1("Test"),
html.p("ReactPy is working")
])
# Verify component renders
vdom = test_component()
print(f"Component rendered: {type(vdom)}")Server Functionality Test:
# Test ASGI server creation (most common deployment)
from reactpy import component, html
from reactpy.executors.asgi.standalone import ReactPy
import uvicorn
@component
def hello_world():
return html.div([
html.h1("Hello, ReactPy!"),
html.p("Server is working!")
])
# Create ASGI app (don't run to avoid hanging)
app = ReactPy(hello_world)
print("✓ ASGI server created successfully")
# To actually run: uvicorn.run(app, host="127.0.0.1", port=8000)Hooks and State Test:
from reactpy import component, html, use_state
@component
def counter_component(initial=0):
count, set_count = use_state(initial)
return html.div([
html.h1(f"Count: {count}"),
html.button({
"onClick": lambda event: set_count(count + 1)
}, "Increment")
])
# Test component with hooks
counter = counter_component(5)
print(f"✓ Hook-based component: {type(counter)}")Always run these validation steps before completing work:
hatch fmt --check-- Ensure code is properly formatted (never expected to fail)hatch run python:type_check-- Ensure no type errors (never expected to fail)hatch run javascript:check-- Ensure JavaScript passes linting (never expected to fail)- Test basic component creation and rendering as shown above
- Test server creation if working on server-related features
- Run relevant tests with
hatch test --parallel-- All tests must always pass - failures are never expected or allowed
Integration Testing:
- ReactPy can be deployed with FastAPI, Flask, Sanic, Tornado via ASGI
- For browser testing, Playwright is used but requires additional setup
- Test component VDOM rendering directly when browser testing isn't available
- Validate that JavaScript builds are included in Python package after changes
src/reactpy/-- Main Python package source codecore/-- Core ReactPy functionality (components, hooks, VDOM)web/-- Web module management and exportsexecutors/-- Server integration modules (ASGI, etc.)testing/-- Testing utilities and fixturespyscript/-- PyScript integrationstatic/-- Bundled JavaScript files_html.py-- HTML element factory functions
src/js/-- JavaScript packages that get bundled with Pythonpackages/event-to-object/-- Event serialization packagepackages/@reactpy/client/-- Client-side React integrationpackages/@reactpy/app/-- Application framework
src/build_scripts/-- Build automation scriptstests/-- Python test suite with comprehensive coveragedocs/-- Documentation source (MkDocs-based, transitioning setup)
pyproject.toml-- Python project configuration and Hatch environmentssrc/js/package.json-- JavaScript development dependenciestests/conftest.py-- Test configuration and fixturesdocs/source/about/changelog.rst-- Version history and changes.github/workflows/check.yml-- CI/CD pipeline configuration
- JavaScript build: 15 seconds
- Python package build: 10 seconds
- Python linting: 1 second
- JavaScript linting: 10 seconds
- Type checking: 10 seconds
- Full CI pipeline: 5-10 minutes
ASGI Standalone (Recommended):
from reactpy import component, html
from reactpy.executors.asgi.standalone import ReactPy
import uvicorn
@component
def my_app():
return html.h1("Hello World")
app = ReactPy(my_app)
uvicorn.run(app, host="127.0.0.1", port=8000)With FastAPI:
from fastapi import FastAPI
from reactpy import component, html
from reactpy.executors.asgi.middleware import ReactPyMiddleware
@component
def my_component():
return html.h1("Hello from ReactPy!")
app = FastAPI()
app.add_middleware(ReactPyMiddleware, component=my_component)from reactpy import component, html, use_state
@component
def my_component(initial_value=0):
count, set_count = use_state(initial_value)
return html.div([
html.h1(f"Count: {count}"),
html.button({
"onClick": lambda event: set_count(count + 1)
}, "Increment")
])- JavaScript packages are in
src/js/packages/ - Three main packages: event-to-object, @reactpy/client, @reactpy/app
- Built JavaScript gets bundled into
src/reactpy/static/ - Always rebuild JavaScript after changes:
hatch run javascript:build
The following are key commands for daily development:
hatch test --parallel # Run all tests (**All tests must always pass**)
hatch test --parallel --cover # Run tests with coverage (used in CI)
hatch test --parallel -k test_name # Run specific tests
hatch fmt # Format code with all formatters
hatch fmt --check # Check formatting without changes
hatch run python:type_check # Run Python type checker
hatch run javascript:build # Build JavaScript packages (15 seconds)
hatch run javascript:check # Lint JavaScript code (10 seconds)
hatch run javascript:fix # Format JavaScript code
hatch build --clean # Build Python package (10 seconds)hatch env show # Show all environments
hatch shell # Enter default shell
hatch shell default # Enter development shell- NEVER CANCEL: All commands complete within 60 seconds in normal operation
- JavaScript build: 15 seconds (hatch run javascript:build)
- Python package build: 10 seconds (hatch build --clean)
- Python linting: 1 second (hatch fmt)
- JavaScript linting: 10 seconds (hatch run javascript:check)
- Type checking: 10 seconds (hatch run python:type_check)
- Unit tests: 10-30 seconds (varies by test selection)
- Full CI pipeline: 5-10 minutes
Follow this step-by-step process for effective development:
- Bootstrap environment: Ensure you have Python 3.9+ and run
pip install hatch - Make your changes to the codebase
- Run formatting:
hatch fmtto format code (~1 second) - Run type checking:
hatch run python:type_checkfor type checking (~10 seconds) - Run JavaScript linting (if JavaScript was modified):
hatch run javascript:check(~10 seconds) - Run relevant tests:
hatch test --parallelwith specific test selection if needed. All tests must always pass - failures are never expected or allowed. - Validate component functionality manually using validation tests above
- Build JavaScript (if modified):
hatch run javascript:build(~15 seconds) - Update documentation when making changes to Python source code (required)
- Add changelog entry for all significant changes to
docs/source/about/changelog.rst
IMPORTANT: Documentation must be updated whenever changes are made to Python source code. This is enforced as part of the development workflow.
IMPORTANT: Significant changes must always include a changelog entry in docs/source/about/changelog.rst under the appropriate version section.
- If JavaScript build fails, try:
hatch run "src/build_scripts/clean_js_dir.py"then rebuild - If Python build fails, ensure all dependencies in pyproject.toml are available
- Network timeouts during pip install are common in CI environments
- Missing dependencies error: Install ASGI dependencies with
pip install orjson asgiref asgi-tools servestatic
- ReactPy must be installed or src/ must be in Python path
- Main imports:
from reactpy import component, html, use_state - Server imports:
from reactpy.executors.asgi.standalone import ReactPy - Web functionality:
from reactpy.web import export, module_from_url
- Missing ASGI dependencies: Install with
pip install orjson asgiref asgi-tools servestatic uvicorn - For FastAPI integration:
pip install fastapi uvicorn - For Flask integration:
pip install flask(requires additional backend package) - For development servers, use ReactPy ASGI standalone for simplest setup
Modern dependency management via pyproject.toml:
Core Runtime Dependencies:
fastjsonschema >=2.14.5-- JSON schema validationrequests >=2-- HTTP client librarylxml >=4-- XML/HTML processinganyio >=3-- Async I/O abstractiontyping-extensions >=3.10-- Type hints backport
Optional Dependencies (install via extras):
asgi-- ASGI server support:orjson,asgiref,asgi-tools,servestatic,pipjinja-- Template integration:jinja2-simple-tags,jinja2 >=3uvicorn-- ASGI server:uvicorn[standard]testing-- Browser automation:playwrightall-- All optional dependencies combined
Development Dependencies (managed by Hatch):
- JavaScript tooling: Bun runtime for building packages
- Python tooling: Hatch environments handle all dev dependencies automatically
The repository uses GitHub Actions with these key jobs:
test-python-coverage-- Python test coverage withhatch test --parallel --coverlint-python-- Python linting and type checking viahatch fmt --checkandhatch run python:type_checktest-python-- Cross-platform Python testing across Python 3.10-3.13 and Ubuntu/macOS/Windowslint-javascript-- JavaScript linting and type checking
The CI workflow is defined in .github/workflows/check.yml and uses the reusable workflow in .github/workflows/.hatch-run.yml.
Build Matrix:
- Python versions: 3.10, 3.11, 3.12, 3.13
- Operating systems: Ubuntu, macOS, Windows
- Test execution: Hatch-managed environments ensure consistency across platforms
Always ensure your changes pass local validation before pushing, as the CI pipeline will run the same checks.
- This is a Python-to-JavaScript bridge library, not a traditional web framework - it enables React-like components in Python
- Component rendering uses VDOM - components return virtual DOM objects that get serialized to JavaScript
- All builds and tests run quickly - if something takes more than 60 seconds, investigate the issue
- Hatch environments provide full isolation - no need to manage virtual environments manually
- JavaScript packages are bundled into Python - the build process combines JS and Python into a single distribution
- Documentation updates are required when making changes to Python source code
- Always update this file when making changes to the development workflow, build process, or repository structure
- All tests must always pass - failures are never expected or allowed in a healthy development environment