Wybthon¶
Wybthon is SolidJS for Python: a client-side single-page application (SPA) framework with SolidJS 2.0's fine-grained reactive model, a Pythonic API, and a runtime that lives in the browser through Pyodide.
If you can write Python, you can build interactive web apps with Wybthon. There's no JavaScript build pipeline and no JSX.
What is Wybthon?¶
You write function components in Python, return a tree built from HTML helpers, and drop signals, memos, and small reactive expressions into that tree. Components run once. When a signal changes, only the reactive holes that read it re-run, and the reconciler batches the resulting DOM mutations into a single crossing of the Python-to-JavaScript bridge.
The framework ships with everything you need to build a real app:
- Reactive primitives:
create_signal,create_memo, andcreate_effect, with automatic batching and typed accessors. - Async-first data: an
async defpassed tocreate_memois the fetching primitive;LoadingandErroredboundaries handle the pending and failure states. actionwithcreate_optimisticandcreate_optimistic_storefor mutations.- Draft-first stores (
create_store,reconcile,create_projection). - Flow control (
Show,For,Repeat,Switch,Dynamic), callableContextobjects,Portal, andlazy. - A client-side router with
Router,Route, andLink. - Form state, validators, and accessibility helpers.
- A dev server (
wyb dev) with hot reload via Server-Sent Events.
Try it in 30 seconds¶
The smallest interactive Wybthon component looks like this:
from wybthon import button, component, create_signal, div, p, render
@component
def Counter():
count, set_count = create_signal(0)
return div(
p("Count: ", count),
button("Increment", on_click=lambda e: set_count(lambda n: n + 1)),
)
render(Counter(), "#app")
count is an accessor. Placing it in the tree creates a reactive hole, so only that text node updates when the signal changes. Walk through this example end to end in Getting started, or jump straight into the Concepts section.
Quickstart¶
-
Install Wybthon (Python 3.12 or newer):
-
Clone the demo-template and run the dev server with auto-reload:
-
Explore the demo apps and the API in the Concepts and API sections.
Why Wybthon?¶
- Run-once components and typed props. Every parameter of a
@componentfunction is aProp[T]accessor. Place it in the tree to bind it, call it inside a memo or effect to derive from it, or.peek()it for a one-time read. - Holes are the unit of update. A zero-argument callable or accessor anywhere in the tree becomes its own render effect. There are no component re-renders to reason about.
- Automatic batching. Signal writes are staged and applied once per microtask (and at the end of every event handler). There's no
batch(); callflushonly when you need the settled state synchronously. - Async is part of the graph. Reading an async memo before it resolves raises
NotReadyError, which the nearestLoadingboundary turns into fallback UI. Content stays mounted while pending, and a later refetch runs as a transition: the UI that depends on the change holds on the previous state until the new value lands, so nothing tears. - A virtual DOM where it pays off. Python has no JSX compiler to separate static from dynamic markup, and every DOM call crosses the Pyodide bridge, so Wybthon diffs small subtrees and ships the resulting ops to a JavaScript kernel in one batch. Static subtrees mount from cloned templates.
- Dev-mode diagnostics. Writing a signal inside a tracking scope raises
WriteInScopeError; reading a signal or prop at the top level of a component body warns, because that read isn't tracked. - Runs anywhere Python runs. The reactive core and the VDOM are pure Python, so unit tests run in CPython against a stub backend.
Documentation map¶
- Get started: install, write your first component, explore the dev server.
- Concepts: deep dives into the mental model, reactivity, components, lifecycle, VDOM, and DOM interop.
- Guides: task-oriented recipes for authoring patterns, testing, performance, typing, deployment, and more.
- Examples: complete, runnable modules for a counter, async fetch, forms, error handling, and routing.
- API reference: auto-generated documentation per module via
mkdocstrings. - Meta: contribution guide, documentation style guide, FAQ, and troubleshooting.
Next steps¶
- New to Wybthon? Start with Getting started.
- Coming from React or SolidJS? Read Mental model and the migration guides (from React, from Solid).
- Review runtime contracts for state visibility, ownership, and async behavior.
- Looking for an API symbol? Use the search box at the top of the page or jump to the API reference.