Skip to content

Package

wybthon (package)

wybthon

Wybthon: a client-side Python SPA framework powered by Pyodide.

Wybthon brings a SolidJS-inspired, signals-first reactive model to the browser using Python. Component bodies run once at mount; reactivity flows through reactive holes: zero-arg getters embedded in the VNode tree that update only the DOM nodes that depend on them.

The package detects its environment at import time:

  • In a browser (Pyodide), the full surface is available, including DOM helpers, reconciler, router, events, error boundaries, suspense, portals, and the HTML element factories.
  • Outside a browser, the pure-Python surface (reactivity, VDOM data structures, forms, context, flow control, stores) remains importable so unit tests and tooling can run anywhere CPython runs.
Example

A minimal counter component::

from wybthon import button, component, create_signal, div, p, span

@component
def Counter(initial: int = 0):
    count, set_count = create_signal(initial)
    return div(
        p("Count: ", span(count)),
        button("+1", on_click=lambda e: set_count(count() + 1)),
    )
See Also

Modules:

Name Description
component

@component decorator and forward_ref for function components.

context

Context system for passing values through the component tree.

dev

Simple threaded dev server with live-reload via Server-Sent Events.

dom

Lightweight DOM wrapper utilities for Pyodide/browser environments.

error_boundary

ErrorBoundary component for catching render errors in subtrees.

events

Event delegation utilities for VDOM event handling in the browser.

flow

SolidJS-style reactive flow control components.

forms

Form state, validation helpers, and accessibility attribute utilities.

html

Pythonic HTML element helpers that wrap h().

lazy

Helpers for lazy-loading components with simple loading/error states.

portal

Portal component for rendering children into a different DOM container.

props

DOM property application and diffing for element VNodes.

reactivity

Signal-based reactive primitives with an ownership tree.

reconciler

Reconciliation engine: mounting, patching, and unmounting VNode trees.

router

Client-side router components and navigation helpers for Pyodide apps.

router_core

Core, browser-agnostic path matching and route resolution helpers.

store

Reactive stores for nested state, inspired by SolidJS createStore.

suspense

Suspense component for rendering fallback UI during async loading.

vdom

Virtual DOM primitives, diffing, and rendering to real DOM elements.

vnode

Virtual node data structure and tree-building helpers.

Classes:

Name Description
FieldState

Signals representing a field's value, error message, and touched state.

ReactiveProps

Reactive proxy over a component's props dict.

Resource

Async resource with reactive data, error, and loading signals.

Signal

Mutable reactive container that notifies subscribed computations on change.

VNode

Virtual node representing an element, text, component, or reactive hole.

Element

Thin wrapper around a DOM node with convenience methods.

Ref

Mutable container holding a reference to an Element.

DomEvent

Thin wrapper around a JS event with convenience helpers.

Route

Declarative route definition mapping a path to a component.

Context

Opaque context identifier paired with a default value.

Functions:

Name Description
is_dev_mode

Return whether development mode is currently active.

set_dev_mode

Enable or disable development mode warnings globally.

forward_ref

Create a component that forwards a ref prop to a child element.

a11y_control_attrs

Return ARIA attributes for an input or select control bound to a field.

bind_checkbox

Bind a checkbox input to a boolean field.

bind_select

Bind a <select> element to a field, updating value on change.

bind_text

Bind a text input to a field with validation on every input event.

email

Validate a basic email address format with a lightweight regex.

error_message_attrs

Return attributes for an accessible error-message container.

form_state

Create a form state map from a dict of initial values.

max_length

Validate that the stringified value length is at most n.

min_length

Validate that the stringified value length is at least n.

on_submit

Create a submit handler that prevents default and forwards to handler.

on_submit_validated

Submit handler that validates the whole form before calling handler.

required

Validate that a value is present and non-empty.

rules_from_schema

Build a validators map from a small declarative schema.

validate

Return the first validation error, or None when all validators pass.

validate_field

Validate a single field and update its error and touched signals.

validate_form

Validate every field in a form against a rules map.

batch

Batch signal updates so subscribers flush once at the end.

children

Resolve and memoize reactive children, returning a memo getter.

create_effect

Create an auto-tracking reactive effect.

create_memo

Create an auto-tracking computed value and return its getter.

create_resource

Create an async Resource with cancellation support.

create_root

Run fn inside an independent reactive root.

create_selector

Create an O(1) selection signal.

create_signal

Create a reactive signal and return (getter, setter).

get_owner

Return the current reactive owner scope, if any.

get_props

Return the ReactiveProps proxy for the current component.

index_array

Map a reactive list with stable per-index scopes.

map_array

Map a reactive list with stable per-item scopes (keyed by identity).

merge_props

Merge multiple prop sources into a reactive proxy.

on

Create an effect with explicit dependencies.

on_cleanup

Register a cleanup callback on the active reactive owner.

on_mount

Register a callback to run once after the component mounts.

run_with_owner

Run fn under the given ownership scope.

split_props

Split a props source into groups by key name, plus a rest group.

untrack

Run fn without tracking any signal reads.

create_store

Create a reactive store from an initial value.

produce

Create a producer for batch-mutating store state.

Fragment

Group multiple children without adding an extra DOM wrapper element.

dynamic

Create a reactive-hole VNode that re-evaluates getter on dependency changes.

h

Create a VNode from a tag, props, and children.

is_getter

Return True when value is a zero-arg callable suitable for a reactive hole.

memo

Wrap a function component to skip re-mounts when its props are unchanged.

ErrorBoundary

Catch render errors in children and display a fallback.

load_component

Dynamically import a module and return a component wrapping the export.

preload_component

Eagerly import a component to warm caches before navigation.

create_portal

Render children into a different DOM container.

render

Render a VNode tree into a container element.

Link

Anchor element component that navigates via the History API.

Router

Function component that renders the matched route's component.

navigate

Programmatically change the current path and update current_path.

Suspense

Render a fallback while one or more resources are loading.

Provider

Context provider component.

create_context

Create a new Context with the given default value.

use_context

Read the current value for ctx from the ownership tree.

Dynamic

Render a dynamically-chosen component.

For

Render a list of items using a keyed mapping function.

Index

Render a list by index with a stable item getter.

Match

Declare a branch inside a Switch.

Show

Conditionally render children when when is truthy.

Switch

Render the first matching Match branch, or fallback.

Attributes:

Name Type Description
DEV_MODE bool

Process-wide flag toggling Wybthon's development warnings.

current_path Signal[str]

Signal containing the current pathname plus query string.

DEV_MODE module-attribute

DEV_MODE: bool = True

Process-wide flag toggling Wybthon's development warnings.

Defaults to True. Production builds should call set_dev_mode(False) at startup.

current_path module-attribute

current_path: Signal[str] = Signal(_current_url())

Signal containing the current pathname plus query string.

Updated by navigate and by the global popstate listener (back/forward navigation). Read it inside reactive scopes to re-render when the URL changes.

FieldState dataclass

FieldState(value: Signal[Any], error: Signal[Optional[str]], touched: Signal[bool])

Signals representing a field's value, error message, and touched state.

Attributes:

Name Type Description
value Signal[Any]

Signal holding the current input value.

error Signal[Optional[str]]

Signal holding the latest validation error message, or None when valid.

touched Signal[bool]

Signal that becomes True once the user has interacted with the field. Useful for delaying error display until the user has had a chance to respond.

ReactiveProps

ReactiveProps(props: dict, defaults: Optional[Dict[str, Any]] = None)

Reactive proxy over a component's props dict.

Every attribute or item access returns a reactive accessor: a zero-arg callable that returns the current value and tracks the read. This mirrors SolidJS's props.x semantics, adapted to Python.

Access patterns:

Expression Returns Notes
props.name callable getter Stable across reads.
props.name() current value Tracked when called inside an effect or hole.
props["name"] callable getter Same as props.name.
props.get("name", default) callable getter Returns default when missing.
props.value("name", default) current value One-shot snapshot, with auto-unwrap.

Embed the accessor directly in the VNode tree to create an automatic reactive hole; the surrounding DOM region updates only when the prop changes.

Example
@component
def Greeting():
    props = get_props()
    # Auto-hole: only the text node updates when ``name`` changes.
    return p("Hello, ", props.name, "!")
Note

ReactiveProps is read-only. Parents and the reconciler update it via the internal _update method.

Methods:

Name Description
value

Return the current value for key (tracked, with auto-unwrap).

get

Return a callable getter for key, falling back to default if missing.

keys

Return the prop names currently set on this instance.

values

Return current prop values as a list (tracked).

items

Return (key, current_value) pairs (tracked).

value

value(key: str, default: Any = _MISSING) -> Any

Return the current value for key (tracked, with auto-unwrap).

If the stored prop value is a getter, it is invoked and the result returned, mirroring _make_getter. If default is provided, it is returned when key is absent from both the props dict and the component's parameter defaults.

Parameters:

Name Type Description Default
key str

Prop name.

required
default Any

Value returned when the key is missing. When omitted, missing keys yield None.

_MISSING

Returns:

Type Description
Any

The current prop value (auto-unwrapped if it's a getter).

get

get(key: str, default: Any = None) -> Callable[[], Any]

Return a callable getter for key, falling back to default if missing.

When key exists on the prop bag (in raw props, prior signals, or component-parameter defaults), the returned getter reads the underlying signal: a tracking scope subscribes to it.

When key is missing, the getter returns default on each call without creating a tracked signal. This means repeated get(key, x) / get(key, y) calls each return their own default (no sticky behavior). Components that need reactivity for a possibly-missing prop should declare it as a parameter with a default value; @component ensures a signal is created up front so future updates always propagate.

Parameters:

Name Type Description Default
key str

Prop name.

required
default Any

Value returned by the fallback getter when key is missing.

None

Returns:

Type Description
Callable[[], Any]

A zero-arg callable. Subscribers to a missing-key getter are

Callable[[], Any]

not notified when the prop later appears.

keys

keys() -> Any

Return the prop names currently set on this instance.

The result reflects the latest props pushed into the proxy (it is not tracked as a reactive read).

values

values() -> Any

Return current prop values as a list (tracked).

items

items() -> Any

Return (key, current_value) pairs (tracked).

Resource

Resource(fetcher: FetchFn, source: Optional[Callable[[], Any]] = None)

Bases: Generic[R]

Async resource with reactive data, error, and loading signals.

Wraps an awaitable fetcher and exposes signal-backed state so consumers can render loading and error UIs declaratively (typically with Suspense).

Use reload() to (re)fetch and cancel() to abort the in-flight request.

When constructed with a source getter, the resource automatically refetches when the source's tracked value changes (skipping the very first read so it doesn't double-fetch on creation).

Attributes:

Name Type Description
data Signal[Optional[R]]

Reactive accessor for the most recent successful payload, or None before any fetch completes.

error Signal[Optional[Any]]

Reactive accessor for the most recent exception, or None.

loading Signal[bool]

Reactive accessor; True while a fetch is in flight.

Example
async def load_user(signal=None):
    resp = await fetch("/api/users/1")
    return await resp.json()

user = create_resource(load_user)
h("p", {}, dynamic(lambda: "Loading..." if user.loading() else user.data().get("name")))

Methods:

Name Description
reload

Cancel any in-flight request and start a new fetch.

cancel

Abort the current in-flight fetch, if any.

reload

reload() -> None

Cancel any in-flight request and start a new fetch.

Bumps the internal version, sets loading to True, clears error, and dispatches the fetcher on the asyncio loop. Older in-flight tasks are ignored when they resolve.

cancel

cancel() -> None

Abort the current in-flight fetch, if any.

Calls AbortController.abort() on the wrapped browser controller, cancels the asyncio task, and resets loading to False without touching data or error.

Signal

Signal(value: T, *, equals: Any = _DEFAULT_EQUALS)

Bases: Generic[T]

Mutable reactive container that notifies subscribed computations on change.

Most code uses create_signal which returns a (getter, setter) tuple instead of exposing Signal instances directly. This class is part of the public surface so Signal[T] can be used in type hints.

Parameters:

Name Type Description Default
value T

The initial value.

required
equals Any

Equality policy. See create_signal for the full semantics.

_DEFAULT_EQUALS

Methods:

Name Description
get

Return the current value and subscribe the active computation.

set

Write a new value and notify subscribers if it changed.

get

get() -> T

Return the current value and subscribe the active computation.

When called inside an effect, memo, or reactive hole, this signal is added to that computation's dependency set so it re-runs on future writes. Outside a tracking context the read is untracked.

Returns:

Type Description
T

The current value held by the signal.

set

set(value: T) -> None

Write a new value and notify subscribers if it changed.

Equality is determined by the equals policy passed to the constructor (default: is then ==, with equals=False to bypass the check entirely).

Parameters:

Name Type Description Default
value T

The new value to store.

required

VNode

VNode(tag: Optional[Union[str, Callable[..., Any]]], props: Optional[PropsDict] = None, children: Optional[List[ChildType]] = None, key: Optional[Union[str, int]] = None)

Virtual node representing an element, text, component, or reactive hole.

Uses __slots__ for a compact memory layout and faster attribute access, which is meaningful when authoring large lists. Internal attributes (el, subtree, render_effect, component_ctx, _frag_end) are populated by the reconciler when the VNode is mounted.

Attributes:

Name Type Description
tag

Element tag name ("div"), special tag ("_text", "_dynamic", "_fragment"), or component callable.

props

Mapping of prop names to values. Event handlers, attributes, and reactive accessors all live here.

children

List of child VNode instances (or strings, before normalization).

key

Optional stable identity used for keyed list reconciliation.

Element

Element(tag: Optional[str] = None, existing: bool = False, node: Any = None)

Thin wrapper around a DOM node with convenience methods.

Element can be constructed in three ways:

  • With a tag name to create a brand-new node (Element("div")).
  • With a CSS selector and existing=True to wrap an existing node (Element("#root", existing=True)).
  • With an opaque node value to wrap a node returned by another API (used internally by query helpers).

The wrapper proxies common form-input properties (value, checked, files) so handlers can read state from e.target.value exactly as in React or SolidJS.

Create a new element, wrap an existing one, or wrap a raw node.

Parameters:

Name Type Description Default
tag Optional[str]

Tag name ("div") or, when existing=True, a CSS selector identifying the node to wrap.

None
existing bool

If True, query the document for tag instead of creating a new element.

False
node Any

Raw underlying DOM node to wrap. When provided, tag and existing are ignored.

None

Raises:

Type Description
ValueError

If neither node nor a usable tag is provided.

Methods:

Name Description
set_text

Replace the text content of this element.

append_to

Append this element to parent.

append

Append an Element or a text string as a child node.

remove

Detach this element from its parent (no-op if already detached).

load_html

Fetch HTML from url and assign it to innerHTML.

set_html

Replace this element's content with the provided HTML string.

set_attr

Set an attribute on this element, with text-node fallbacks.

get_attr

Return the attribute value for name, or None when absent.

remove_attr

Remove an attribute from this element.

set_style

Set CSS properties using a dict and/or keyword arguments.

add_class

Add one or more CSS classes to this element.

remove_class

Remove one or more CSS classes from this element.

toggle_class

Toggle a CSS class, optionally forcing on/off.

has_class

Return True if the element currently has the given class.

on

Add an event listener and track it for later cleanup.

off

Remove matching event listeners previously attached via on.

cleanup

Remove all tracked event listeners from this element.

query

Query a single element by CSS selector.

query_all

Query all matching elements by CSS selector.

find

Return the first matching descendant Element, or None.

find_all

Return all matching descendant elements as a list.

attach_ref

Store this element on ref.current.

Attributes:

Name Type Description
value Any

Current value of an <input>, <textarea>, or <select>.

checked bool

Checked state of a checkbox or radio input.

files Any

FileList for file inputs (<input type="file">), or None.

value property writable

value: Any

Current value of an <input>, <textarea>, or <select>.

checked property writable

checked: bool

Checked state of a checkbox or radio input.

files property

files: Any

FileList for file inputs (<input type="file">), or None.

set_text

set_text(text: str) -> None

Replace the text content of this element.

append_to

append_to(parent: Element) -> None

Append this element to parent.

append

append(child: Union[Element, str]) -> None

Append an Element or a text string as a child node.

remove

remove() -> None

Detach this element from its parent (no-op if already detached).

load_html async

load_html(url: str) -> None

Fetch HTML from url and assign it to innerHTML.

Parameters:

Name Type Description Default
url str

URL to fetch via the browser's fetch API.

required

set_html

set_html(html: str) -> None

Replace this element's content with the provided HTML string.

Caution

This bypasses the renderer's diffing and does not sanitize input. Avoid passing untrusted HTML.

set_attr

set_attr(name: str, value: Union[str, int, float, bool]) -> None

Set an attribute on this element, with text-node fallbacks.

Parameters:

Name Type Description Default
name str

Attribute name (or nodeValue/text for text nodes).

required
value Union[str, int, float, bool]

Attribute value; coerced to str.

required

get_attr

get_attr(name: str) -> Optional[str]

Return the attribute value for name, or None when absent.

remove_attr

remove_attr(name: str) -> None

Remove an attribute from this element.

set_style

set_style(styles: Optional[Dict[str, Union[str, int]]] = None, **style_kwargs: Union[str, int]) -> None

Set CSS properties using a dict and/or keyword arguments.

Parameters:

Name Type Description Default
styles Optional[Dict[str, Union[str, int]]]

Optional mapping of CSS property name to value.

None
**style_kwargs Union[str, int]

Additional CSS properties (last write wins if a key appears in both).

{}

add_class

add_class(*class_names: str) -> None

Add one or more CSS classes to this element.

remove_class

remove_class(*class_names: str) -> None

Remove one or more CSS classes from this element.

toggle_class

toggle_class(class_name: str, force: Optional[bool] = None) -> None

Toggle a CSS class, optionally forcing on/off.

Parameters:

Name Type Description Default
class_name str

Class to toggle.

required
force Optional[bool]

Pass True to ensure the class is added, False to ensure it is removed; None toggles based on the current state.

None

has_class

has_class(class_name: str) -> bool

Return True if the element currently has the given class.

on

on(event_type: str, handler: Callable[[Any], Any], *, options: Optional[Dict[str, Any]] = None) -> None

Add an event listener and track it for later cleanup.

Listeners attached through on are remembered and removed by off or cleanup. The handler is wrapped in a Pyodide proxy so it can be released on removal.

Parameters:

Name Type Description Default
event_type str

DOM event name (e.g. "click", "input").

required
handler Callable[[Any], Any]

Callback invoked with the DOM event object.

required
options Optional[Dict[str, Any]]

Optional addEventListener options (e.g. {"capture": True}).

None

off

off(event_type: Optional[str] = None, handler: Optional[Callable[[Any], Any]] = None) -> None

Remove matching event listeners previously attached via on.

Parameters:

Name Type Description Default
event_type Optional[str]

If given, only remove listeners of this type.

None
handler Optional[Callable[[Any], Any]]

If given, only remove listeners with this exact callback identity.

None

When both arguments are None, all tracked listeners are removed.

cleanup

cleanup() -> None

Remove all tracked event listeners from this element.

query classmethod

query(selector: str, within: Optional[Element] = None) -> Optional[Element]

Query a single element by CSS selector.

Parameters:

Name Type Description Default
selector str

CSS selector string.

required
within Optional[Element]

Optional parent Element to scope the query to. Defaults to document.

None

Returns:

Type Description
Optional[Element]

The first matching Element, or None if no node matches.

query_all classmethod

query_all(selector: str, within: Optional[Element] = None) -> List[Element]

Query all matching elements by CSS selector.

Parameters:

Name Type Description Default
selector str

CSS selector string.

required
within Optional[Element]

Optional parent Element to scope the query to. Defaults to document.

None

Returns:

Type Description
List[Element]

A list of wrapped Element instances (possibly empty).

find

find(selector: str) -> Optional[Element]

Return the first matching descendant Element, or None.

find_all

find_all(selector: str) -> List[Element]

Return all matching descendant elements as a list.

attach_ref

attach_ref(ref: Ref) -> None

Store this element on ref.current.

Ref

Ref()

Mutable container holding a reference to an Element.

Instantiate with Ref() and pass to elements via the ref= prop. After mount, ref.current points at the wrapped element; after unmount, it is reset to None.

Example
from wybthon import Ref, on_mount
from wybthon.html import input_

input_ref = Ref()

def focus_on_mount():
    on_mount(lambda: input_ref.current and input_ref.current.element.focus())

input_(type="text", ref=input_ref)

Initialize an empty ref pointing at None.

DomEvent

DomEvent(js_event: Any)

Thin wrapper around a JS event with convenience helpers.

Attributes:

Name Type Description
type

Event type string (e.g. "click").

target

The original event target as an Element, or None if unavailable.

current_target Optional[Element]

The currently-dispatched element while bubbling through delegated handlers; updated by the dispatcher.

Wrap a raw JS event object.

Parameters:

Name Type Description Default
js_event Any

The native browser event object.

required

Methods:

Name Description
prevent_default

Prevent the default browser action for this event, if possible.

stop_propagation

Stop propagation through both the JS and the delegated chains.

prevent_default

prevent_default() -> None

Prevent the default browser action for this event, if possible.

stop_propagation

stop_propagation() -> None

Stop propagation through both the JS and the delegated chains.

Sets an internal flag that causes Wybthon's dispatcher to stop walking the DOM ancestors, and also calls the native stopPropagation so other JS listeners do not fire.

Route dataclass

Route(path: str, component: Union[Callable[[Dict[str, Any]], VNode], type], children: Optional[List['Route']] = None)

Declarative route definition mapping a path to a component.

Attributes:

Name Type Description
path str

Route pattern (e.g. "/users/:id", "/docs/*").

component Union[Callable[[Dict[str, Any]], VNode], type]

A function component or class to render when the path matches.

children Optional[List['Route']]

Optional nested routes whose paths are joined with this route's path.

Context dataclass

Context(id: int, default: Any)

Opaque context identifier paired with a default value.

Returned by create_context. Treat the object as opaque: pass it to a Provider and to use_context but do not rely on its fields.

Attributes:

Name Type Description
id int

Process-unique integer used as the storage key on owner scopes.

default Any

Value returned by use_context when no enclosing provider is found.

is_dev_mode

is_dev_mode() -> bool

Return whether development mode is currently active.

set_dev_mode

set_dev_mode(enabled: bool) -> None

Enable or disable development mode warnings globally.

Parameters:

Name Type Description Default
enabled bool

When False, warn and warn_once become no-ops and tracebacks are suppressed in log_error.

required

forward_ref

forward_ref(render_fn: Callable[..., Any]) -> Callable[..., Any]

Create a component that forwards a ref prop to a child element.

The wrapped function receives (props, ref) instead of (props,), where ref is the value of the ref prop (or None). ref is stripped from props (matching React's forwardRef semantics), so the wrapped function only sees its own concerns.

Parameters:

Name Type Description Default
render_fn Callable[..., Any]

A callable taking (props, ref) and returning a VNode subtree.

required

Returns:

Type Description
Callable[..., Any]

A component callable that forwards the ref prop to render_fn.

Example
FancyInput = forward_ref(lambda props, ref: input_(
    type="text", ref=ref, class_="fancy",
))

my_ref = Ref()
h(FancyInput, {"ref": my_ref})

a11y_control_attrs

a11y_control_attrs(field: FieldState, *, described_by_id: Optional[str] = None) -> Dict[str, Any]

Return ARIA attributes for an input or select control bound to a field.

  • aria-invalid is set to "true" when the field currently has an error, otherwise "false".
  • aria-describedby references described_by_id when an error is present, allowing screen readers to announce the message.

Parameters:

Name Type Description Default
field FieldState

Bound FieldState.

required
described_by_id Optional[str]

Optional id of the element rendered by error_message_attrs.

None

Returns:

Type Description
Dict[str, Any]

Props dict to spread onto the control.

bind_checkbox

bind_checkbox(field: FieldState) -> Dict[str, Any]

Bind a checkbox input to a boolean field.

Parameters:

Name Type Description Default
field FieldState

Target FieldState (treated as holding a bool).

required

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a checkbox

Dict[str, Any]

(checked + on_change).

bind_select

bind_select(field: FieldState) -> Dict[str, Any]

Bind a <select> element to a field, updating value on change.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a <select> element

Dict[str, Any]

(value + on_change).

bind_text

bind_text(field: FieldState, *, validators: Optional[List[Validator]] = None) -> Dict[str, Any]

Bind a text input to a field with validation on every input event.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required
validators Optional[List[Validator]]

Optional list of validators. When provided, the field's error signal is updated on every keystroke.

None

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a text input

Dict[str, Any]

(value + on_input).

email

email(message: str = 'Invalid email address') -> Validator

Validate a basic email address format with a lightweight regex.

The validator accepts None and empty strings as valid so it can be combined with required (which handles the "missing" case explicitly).

Parameters:

Name Type Description Default
message str

Error message used when the value does not match.

'Invalid email address'

Returns:

Type Description
Validator

A validator returning message on bad input, otherwise

Validator

None.

error_message_attrs

error_message_attrs(*, id: str) -> Dict[str, Any]

Return attributes for an accessible error-message container.

The container becomes a polite live region so that updates are announced to assistive technology without interrupting the user.

Parameters:

Name Type Description Default
id str

DOM id to assign to the error container. Pair with a11y_control_attrs so the input references this element via aria-describedby.

required

Returns:

Type Description
Dict[str, Any]

Props dict to spread onto the error container element.

form_state

form_state(initial: Dict[str, Any]) -> Dict[str, FieldState]

Create a form state map from a dict of initial values.

Parameters:

Name Type Description Default
initial Dict[str, Any]

Mapping of field name to initial value.

required

Returns:

Type Description
Dict[str, FieldState]

A dict mapping each field name to a freshly-created

Dict[str, FieldState]

max_length

max_length(n: int, message: Optional[str] = None) -> Validator

Validate that the stringified value length is at most n.

Parameters:

Name Type Description Default
n int

Maximum allowed length.

required
message Optional[str]

Optional override for the default error message.

None

Returns:

Type Description
Validator

A validator that returns the message when `len(str(value)) >

Validator

nor whenvalueisNone, otherwiseNone`.

min_length

min_length(n: int, message: Optional[str] = None) -> Validator

Validate that the stringified value length is at least n.

Parameters:

Name Type Description Default
n int

Minimum allowed length.

required
message Optional[str]

Optional override for the default error message.

None

Returns:

Type Description
Validator

A validator that returns the message when `len(str(value)) <

Validator

nor whenvalueisNone, otherwiseNone`.

on_submit

on_submit(handler: Callable[[Dict[str, FieldState]], Any], form: Dict[str, FieldState]) -> Callable[[Any], Any]

Create a submit handler that prevents default and forwards to handler.

Parameters:

Name Type Description Default
handler Callable[[Dict[str, FieldState]], Any]

Callback invoked with the form state when submit fires.

required
form Dict[str, FieldState]

Form state map produced by form_state.

required

Returns:

Type Description
Callable[[Any], Any]

An event handler suitable for on_submit= on a <form>.

on_submit_validated

on_submit_validated(rules: Dict[str, List[Validator]], handler: Callable[[Dict[str, FieldState]], Any], form: Dict[str, FieldState]) -> Callable[[Any], Any]

Submit handler that validates the whole form before calling handler.

Prevents the default submit action, validates via validate_form, and invokes handler only when validation passes.

Parameters:

Name Type Description Default
rules Dict[str, List[Validator]]

Mapping from field name to a list of validators.

required
handler Callable[[Dict[str, FieldState]], Any]

Callback invoked with the form state on success.

required
form Dict[str, FieldState]

Form state map produced by form_state.

required

Returns:

Type Description
Callable[[Any], Any]

An event handler suitable for on_submit= on a <form>.

required

required(message: str = 'This field is required') -> Validator

Validate that a value is present and non-empty.

Parameters:

Name Type Description Default
message str

Error message used when the value is missing or blank.

'This field is required'

Returns:

Type Description
Validator

A validator that returns message for None or empty strings

Validator

(after strip()), otherwise None.

rules_from_schema

rules_from_schema(schema: Dict[str, Dict[str, Any]]) -> Dict[str, List[Validator]]

Build a validators map from a small declarative schema.

Supported per-field keys:

  • required: bool or str (if a string, it is used as the custom message).
  • min_length: int. Optional custom message via min_length_message.
  • max_length: int. Optional custom message via max_length_message.
  • email: bool or str (if a string, it is used as the custom message).

Parameters:

Name Type Description Default
schema Dict[str, Dict[str, Any]]

Mapping from field name to its rule spec dict.

required

Returns:

Type Description
Dict[str, List[Validator]]

A validators map suitable for

Dict[str, List[Validator]]
Example
rules_from_schema({
    "name": {"required": True, "min_length": 2},
    "email": {"email": True},
})

validate

validate(value: Any, validators: List[Validator]) -> Optional[str]

Return the first validation error, or None when all validators pass.

Parameters:

Name Type Description Default
value Any

Value to validate.

required
validators List[Validator]

Ordered list of validators applied with short-circuit semantics.

required

Returns:

Type Description
Optional[str]

The error message from the first failing validator, or None

Optional[str]

if every validator returns None.

validate_field

validate_field(field: FieldState, validators: Optional[List[Validator]] = None) -> Optional[str]

Validate a single field and update its error and touched signals.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required
validators Optional[List[Validator]]

Validators to apply. When omitted or empty, the field is treated as valid.

None

Returns:

Type Description
Optional[str]

The first error message produced by the validators, or None

Optional[str]

when the field is valid.

validate_form

validate_form(form: Dict[str, FieldState], rules: Dict[str, List[Validator]]) -> Tuple[bool, Dict[str, Optional[str]]]

Validate every field in a form against a rules map.

Mutates each field's touched and error signals as a side effect.

Parameters:

Name Type Description Default
form Dict[str, FieldState]

Form state map (typically produced by form_state).

required
rules Dict[str, List[Validator]]

Mapping from field name to a list of validators. Unknown field names are ignored.

required

Returns:

Type Description
bool

A (is_valid, errors) tuple where is_valid is True only

Dict[str, Optional[str]]

when every validator passes and errors maps each field name

Tuple[bool, Dict[str, Optional[str]]]

to its current error message (or None).

batch

batch(fn: Optional[Callable[[], T]] = None) -> Union[T, _Batch]

Batch signal updates so subscribers flush once at the end.

Two call shapes are supported:

  1. Context manager (Pythonic):
    with batch():
        set_a(1)
        set_b(2)
    
  2. Callback (SolidJS style):
    batch(lambda: (set_a(1), set_b(2)))
    

When called with a function, the function's return value is returned. Effects are flushed synchronously before batch returns, matching SolidJS semantics.

Parameters:

Name Type Description Default
fn Optional[Callable[[], T]]

Optional zero-arg callable. When omitted, returns a context manager.

None

Returns:

Type Description
Union[T, _Batch]

Either a _Batch context manager (when fn is None) or the

Union[T, _Batch]

return value of fn.

children

children(fn: Callable[[], Any]) -> Callable[[], List[Any]]

Resolve and memoize reactive children, returning a memo getter.

Wraps a getter that returns children (e.g. lambda: props.children()) and returns a memo that flattens nested lists and unwraps callables. Matches SolidJS's children() helper.

Parameters:

Name Type Description Default
fn Callable[[], Any]

Zero-arg getter that returns the raw children value (typically lambda: get_props().children()).

required

Returns:

Type Description
Callable[[], List[Any]]

A zero-arg memo getter producing a flat list of resolved children.

Example
@component
def Card(title=""):
    props = get_props()
    resolved = children(lambda: props.children())
    return section(h3(props.title), *resolved())

create_effect

create_effect(fn: Callable[..., Any]) -> Computation

Create an auto-tracking reactive effect.

The effect runs immediately and re-runs whenever any signal read inside fn changes. on_cleanup may be called inside fn to register per-run cleanup that runs before re-execution and on disposal.

If fn accepts a positional parameter, the previous return value is passed on each re-execution (None on the first run), matching SolidJS's createEffect(prev => ...).

Inside a component, the effect is automatically disposed on unmount.

Parameters:

Name Type Description Default
fn Callable[..., Any]

Zero- or one-arg callable. When it accepts an argument, the previous return value is forwarded.

required

Returns:

Type Description
Computation

The underlying Computation. Call .dispose() to stop the effect

Computation

manually.

Example
count, set_count = create_signal(0)
create_effect(lambda prev: (print("was", prev), count())[1])

create_memo

create_memo(fn: Callable[[], T]) -> Callable[[], T]

Create an auto-tracking computed value and return its getter.

Re-computes only when signals read inside fn change. Inside a component, the underlying computation is disposed on unmount.

Parameters:

Name Type Description Default
fn Callable[[], T]

Zero-arg callable producing the derived value.

required

Returns:

Type Description
Callable[[], T]

A zero-arg callable. Reading it inside a tracking scope creates

Callable[[], T]

a dependency on the memoised value.

Example
doubled = create_memo(lambda: count() * 2)
print(doubled())  # reactive read

create_resource

create_resource(source_or_fetcher: Union[Callable[[], Any], Callable[..., Awaitable[R]]], fetcher: Optional[Callable[..., Awaitable[R]]] = None) -> Resource[R]

Create an async Resource with cancellation support.

Can be called two ways:

  • create_resource(fetcher): simple fetcher, no source signal.
  • create_resource(source, fetcher): refetches automatically when the source getter's tracked value changes.

The fetcher should be an async function returning the data value. If it accepts a signal keyword argument, an AbortSignal is passed for cancellation support when running in a browser.

Parameters:

Name Type Description Default
source_or_fetcher Union[Callable[[], Any], Callable[..., Awaitable[R]]]

When called with one argument, this is the fetcher. When called with two, this is the source getter (typically a signal accessor).

required
fetcher Optional[Callable[..., Awaitable[R]]]

Optional fetcher. Required when source_or_fetcher is a source getter.

None

Returns:

Type Description
Resource[R]

A Resource[R] whose data, error, and loading signals can

Resource[R]

be read inside reactive scopes.

Example
user_id, set_user_id = create_signal(1)

async def load_user(signal=None):
    resp = await fetch(f"/api/users/{user_id()}")
    return await resp.json()

user = create_resource(user_id, load_user)

create_root

create_root(fn: Callable[[Callable[[], None]], T]) -> T

Run fn inside an independent reactive root.

Useful for spawning long-lived reactive work that should not be tied to the surrounding component's lifecycle (e.g., global stores).

Parameters:

Name Type Description Default
fn Callable[[Callable[[], None]], T]

Callable receiving a dispose callback. Calling dispose() tears down the root and any effects created inside it.

required

Returns:

Type Description
T

Whatever fn returns.

Example
result = create_root(lambda dispose: setup_global_state(dispose))

create_selector

create_selector(source: Callable[[], Any]) -> Callable[[Any], bool]

Create an O(1) selection signal.

When source() changes, only computations that previously called the returned is_selected(key) with the old or new key are notified, instead of every subscriber re-running.

Parameters:

Name Type Description Default
source Callable[[], Any]

Zero-arg getter returning the currently-selected key.

required

Returns:

Type Description
Callable[[Any], bool]

A function is_selected(key) -> bool that is reactive to

Callable[[Any], bool]

selection changes.

Example
selected, set_selected = create_signal(1)
is_selected = create_selector(selected)

# Inside a For loop per item:
create_effect(lambda: print("active:", is_selected(item_id)))

create_signal

create_signal(value: T, *, equals: Any = _DEFAULT_EQUALS) -> tuple

Create a reactive signal and return (getter, setter).

Works inside or outside components. Inside a stateful component the signal is captured by the render function's closure and persists naturally; there is no cursor system or "rules of hooks".

Parameters:

Name Type Description Default
value T

Initial value stored in the signal.

required
equals Any

Equality policy controlling when subscribers are notified. Accepts:

  • The default sentinel (or True): value equality (new == old) with an identity fast-path. Skips notification when the new value is is-identical or ==-equal to the old. This matches Python's natural intuition; re-setting an unchanged value is a no-op, and a fresh container with equal contents also skips notification.
  • False: always notify on every set() call, even when the new value is identical or equal to the old. Useful for "fire a change event" signals.
  • A callable (old, new) -> bool: skip notification when it returns True. Pass equals=lambda a, b: a is b for SolidJS-style identity-only semantics.
_DEFAULT_EQUALS

Returns:

Type Description
tuple

A (getter, setter) tuple. The getter is a zero-arg callable

tuple

suitable for embedding as a reactive hole.

Example
count, set_count = create_signal(0)
print(count())          # 0
set_count(5)
print(count())          # 5

get_owner

get_owner() -> Optional[Owner]

Return the current reactive owner scope, if any.

Capture the owner before crossing async boundaries (e.g. await) and restore it with run_with_owner to maintain proper lifecycle management.

Returns:

Type Description
Optional[Owner]

The active Owner, or None when called outside any reactive

Optional[Owner]

scope.

get_props

get_props() -> 'ReactiveProps'

Return the ReactiveProps proxy for the current component.

The returned object provides reactive access to individual props. Each attribute / index lookup yields a callable getter; call the getter to read the current value (tracked when called inside an effect or hole).

Most components should rely on the destructured parameters provided by @component. Use get_props() for advanced cases such as generic wrappers, key iteration, or proxy-mode interop.

Returns:

Type Description
'ReactiveProps'

The cached ReactiveProps proxy for this component instance.

Raises:

Type Description
RuntimeError

If called outside a component setup phase.

Example
@component
def Greet(name="world"):
    # ``name`` is already a reactive accessor.
    return p("Hello, ", name, "!")

@component
def Advanced():
    props = get_props()
    create_effect(lambda: print("name:", props.name()))

index_array

index_array(source: Callable[[], Optional[List[Any]]], map_fn: Callable[[Callable[[], Any], int], T]) -> Callable[[], List[T]]

Map a reactive list with stable per-index scopes.

Unlike map_array, scopes are keyed by index position. Each slot has a reactive item_getter signal that updates when the value at that index changes.

Parameters:

Name Type Description Default
source Callable[[], Optional[List[Any]]]

Zero-arg getter that returns the current list.

required
map_fn Callable[[Callable[[], Any], int], T]

Called as map_fn(item_getter, index). item_getter() returns the item; index is a plain int (not a getter).

required

Returns:

Type Description
Callable[[], List[T]]

A zero-arg getter producing the mapped list.

Example
items, set_items = create_signal(["A", "B", "C"])
labels = index_array(items, lambda item, idx: f"[{idx}] {item()}")
# labels() == ["[0] A", "[1] B", "[2] C"]

map_array

map_array(source: Callable[[], Optional[List[Any]]], map_fn: Callable[[Callable[[], Any], Callable[[], int]], T]) -> Callable[[], List[T]]

Map a reactive list with stable per-item scopes (keyed by identity).

Items are matched by reference identity. The mapping callback runs once per unique item; when an item leaves the source list, its reactive scope is disposed automatically.

Parameters:

Name Type Description Default
source Callable[[], Optional[List[Any]]]

Zero-arg getter that returns the current list (typically a signal accessor).

required
map_fn Callable[[Callable[[], Any], Callable[[], int]], T]

Called as map_fn(item_getter, index_getter) for each unique item. item_getter() returns the item; index_getter() returns its current position.

required

Returns:

Type Description
Callable[[], List[T]]

A zero-arg getter producing the mapped list. Reading it inside a

Callable[[], List[T]]

reactive scope subscribes to source changes.

Example
items, set_items = create_signal(["A", "B", "C"])
labels = map_array(items, lambda item, idx: f"{idx()}: {item()}")
# labels() == ["0: A", "1: B", "2: C"]

merge_props

merge_props(*sources: Any) -> '_MergedProps'

Merge multiple prop sources into a reactive proxy.

Each source may be a plain dict, a zero-arg getter that returns a dict, or another _MergedProps / _SplitProps. Later sources override earlier ones on key conflicts.

The returned object supports dict-like access ([], .get, in, iteration). When a source is a callable, it is called on each property access, so signal reads inside the getter are tracked by the current reactive computation.

Parameters:

Name Type Description Default
*sources Any

One or more prop sources, in priority order (rightmost wins).

()

Returns:

Type Description
'_MergedProps'

A reactive merged-props proxy.

Example
defaults = {"size": "md", "variant": "solid"}
final = merge_props(defaults, props)
# final["size"] lazily reads from props, then falls back to defaults

on

on(deps: Union[Callable[[], Any], List[Callable[[], Any]]], fn: Callable[..., Any], defer: bool = False) -> Computation

Create an effect with explicit dependencies.

deps may be a single getter or a list of getters. fn receives the current value(s) as positional arguments. Only the listed deps are tracked; the body of fn runs inside untrack.

Parameters:

Name Type Description Default
deps Union[Callable[[], Any], List[Callable[[], Any]]]

One getter or a list of getters to subscribe to.

required
fn Callable[..., Any]

Callback receiving the current dep value(s) on each change.

required
defer bool

When True, skip the first invocation (so fn runs only on subsequent changes, not the initial read).

False

Returns:

Type Description
Computation

The underlying Computation.

Example
on(count, lambda v: print("count is now", v))
on([a, b], lambda va, vb: print(f"a={va}, b={vb}"), defer=True)

on_cleanup

on_cleanup(fn: Callable[[], Any]) -> None

Register a cleanup callback on the active reactive owner.

Lifecycle differs by call site:

  • Inside create_effect: runs before each re-execution and on final disposal.
  • Inside a component's setup phase: runs when the component unmounts.
  • Inside a reactive hole: runs before each hole re-evaluation and when the hole is disposed.

Parameters:

Name Type Description Default
fn Callable[[], Any]

Zero-arg cleanup callback.

required

Raises:

Type Description
RuntimeError

If called outside any reactive scope.

on_mount

on_mount(fn: Callable[[], Any]) -> None

Register a callback to run once after the component mounts.

Must be called during a component's setup phase (the body of a @component function, before the return).

Parameters:

Name Type Description Default
fn Callable[[], Any]

Zero-arg callback invoked once after the first render commits.

required

Raises:

Type Description
RuntimeError

If called outside a component setup phase.

run_with_owner

run_with_owner(owner: Optional[Owner], fn: Callable[[], T]) -> T

Run fn under the given ownership scope.

Useful for restoring context after an await boundary where the reactive owner would otherwise be lost.

Parameters:

Name Type Description Default
owner Optional[Owner]

The owner to install for the duration of fn. Pass None to disable ownership tracking entirely.

required
fn Callable[[], T]

Zero-arg callable to execute.

required

Returns:

Type Description
T

Whatever fn returns.

Example
async def load():
    owner = get_owner()
    data = await fetch_something()
    run_with_owner(owner, lambda: create_effect(lambda: use(data)))

split_props

split_props(props: Any, *key_groups: List[str]) -> Tuple[Any, ...]

Split a props source into groups by key name, plus a rest group.

Parameters:

Name Type Description Default
props Any

A dict, callable getter, or _MergedProps / _SplitProps to split.

required
*key_groups List[str]

One or more lists of keys defining each group.

()

Returns:

Type Description
Any

A tuple (group1, group2, ..., rest) where each group is a

...

reactive proxy that lazily reads from the original props. The

Tuple[Any, ...]

final rest group contains every key not claimed by an earlier

Tuple[Any, ...]

group.

Example
local, rest = split_props(props, ["class", "style"])
# local["class"] lazily reads from props
# rest contains every other key

untrack

untrack(fn: Callable[[], T]) -> T

Run fn without tracking any signal reads.

Useful inside effects when you need to read a signal without creating a dependency, or during component setup to seed local state from a prop without subscribing.

Inside untrack the dev-mode destructured-prop warning is also silenced, so count, set_count = create_signal(untrack(initial)) cleanly opts out of the noise.

Parameters:

Name Type Description Default
fn Callable[[], T]

Zero-arg callable to invoke with tracking suppressed.

required

Returns:

Type Description
T

Whatever fn returns.

Example
create_effect(lambda: print("a changed:", a(), "b is:", untrack(b)))

create_store

create_store(initial: Any) -> Tuple[Any, _StoreSetter]

Create a reactive store from an initial value.

Parameters:

Name Type Description Default
initial Any

Initial state. Dicts and lists are wrapped in reactive proxies; other values are returned unchanged.

required

Returns:

Type Description
Any

A tuple (store, set_store) where store is a reactive

_StoreSetter

proxy that tracks reads per-path, and set_store is a setter

Tuple[Any, _StoreSetter]

supporting path-based updates and

Tuple[Any, _StoreSetter]

produce batches.

Example
store, set_store = create_store({"count": 0, "user": {"name": "Ada"}})

store.count         # 0
store.user.name     # "Ada"

set_store("count", 5)
set_store("user", "name", "Jane")
set_store("count", lambda c: c + 1)

See the module docstring for the full set of supported calling conventions.

produce

produce(fn: Callable[..., None]) -> _ProduceResult

Create a producer for batch-mutating store state.

fn receives a mutable draft of the store. Mutations are recorded and applied reactively when the producer is passed to a store setter created by create_store.

The draft supports attribute access, item access, and append / pop for lists.

Parameters:

Name Type Description Default
fn Callable[..., None]

A function that mutates the supplied draft. The draft is consumed immediately when applied; do not keep a reference past the call.

required

Returns:

Type Description
_ProduceResult

A marker object recognized by the store setter.

Example
set_store(produce(lambda s: setattr(s, "count", s.count + 1)))

set_store(produce(lambda s: s.todos.append(
    {"text": "New", "done": False}
)))

Fragment

Fragment(*args: Any) -> VNode

Group multiple children without adding an extra DOM wrapper element.

Fragments use empty comment nodes as start/end markers and mount their children directly into the parent container. This avoids extra elements that would pollute selectors like :first-child or affect layout.

Parameters:

Name Type Description Default
*args Any

Either a sequence of children (Fragment(a, b, c)) or a single dict containing a children key (the form used when Fragment is called as h(Fragment, {}, a, b, c)).

()

Returns:

Type Description
VNode

A _fragment VNode that the reconciler will mount inline.

Example
Fragment(h1("Title"), p("Body text"))
h(Fragment, {}, h1("Title"), p("Body text"))  # same thing

dynamic

dynamic(getter: Callable[[], Any], *, key: Optional[Union[str, int]] = None) -> VNode

Create a reactive-hole VNode that re-evaluates getter on dependency changes.

This is the explicit form of the same machinery that wraps callable children automatically. Use it when you want to be explicit about which child is dynamic, or to attach a stable key for keyed reuse inside a fragment.

The getter may return a VNode, a str, a list of either, or None.

Parameters:

Name Type Description Default
getter Callable[[], Any]

Zero-arg callable evaluated inside its own effect. Any signal reads inside the getter become dependencies that trigger re-evaluation.

required
key Optional[Union[str, int]]

Optional stable identity used by keyed reconciliation.

None

Returns:

Type Description
VNode

A _dynamic VNode that the reconciler will mount as a reactive hole.

Example
div(dynamic(lambda: f"Hello, {name()}!"))

h

h(tag: Optional[Union[str, Callable[..., Any]]], props: Optional[PropsDict] = None, *children: Any) -> VNode

Create a VNode from a tag, props, and children.

This is the low-level VNode constructor used everywhere. For common HTML tags, prefer the helpers in wybthon.html (div, span, button, …).

Callable children (zero-argument getters) are passed through unchanged; normalize_children wraps them as _dynamic VNodes when the parent element mounts. Components receive their children verbatim via the children prop so they can decide how to render them.

Parameters:

Name Type Description Default
tag Optional[Union[str, Callable[..., Any]]]

An HTML tag name ("div"), a special tag ("_text", "_dynamic", "_fragment"), or a component callable.

required
props Optional[PropsDict]

Mapping of prop names to values. May be None.

None
*children Any

Children to attach. Lists/tuples are flattened.

()

Returns:

Type Description
VNode

A new VNode.

Example
from wybthon import h

view = h("button", {"on_click": handle_click}, "Click me")

is_getter

is_getter(value: Any) -> bool

Return True when value is a zero-arg callable suitable for a reactive hole.

The check excludes:

  • VNode instances
  • Classes (isinstance(value, type))
  • Components and providers (marked with _wyb_component / _wyb_provider)
  • Ref objects (have a current attribute)
  • Callables that require positional arguments (e.g. event handlers taking an event object)

Parameters:

Name Type Description Default
value Any

Any value, typically a child or prop value being normalized.

required

Returns:

Type Description
bool

True if the value should be treated as a reactive getter.

memo

memo(component: Callable[..., Any], are_props_equal: Optional[Callable[[PropsDict, PropsDict], bool]] = None) -> Callable[..., Any]

Wrap a function component to skip re-mounts when its props are unchanged.

Because Wybthon component bodies run once, memo is only useful when you want to skip re-mounting on a prop change (for example, components with an expensive setup phase). Most ordinary components do not need it; fine-grained holes already minimise DOM work.

Parameters:

Name Type Description Default
component Callable[..., Any]

The component callable to memoize.

required
are_props_equal Optional[Callable[[PropsDict, PropsDict], bool]]

Optional (old_props, new_props) -> bool comparator. Defaults to a shallow identity check (is) across every key.

None

Returns:

Type Description
Callable[..., Any]

A wrapped component callable. Identity is preserved across

Callable[..., Any]

renders so the reconciler can detect "same component, same

Callable[..., Any]

props".

Example
MemoList = memo(ExpensiveList,
                are_props_equal=lambda a, b: a["items"] == b["items"])

ErrorBoundary

ErrorBoundary(props: Any) -> Any

Catch render errors in children and display a fallback.

Parameters:

Name Type Description Default
props Any

The component's props with the following keys:

  • fallback: A VNode, a string, or a callable (error, reset) -> VNode. The callable form may also accept just (error,).
  • on_error: Optional callback invoked with the caught exception (errors raised inside the callback are swallowed).
  • reset_key / reset_keys: When this value (or callable result) changes, the boundary auto-clears the current error.
  • children: Children rendered when no error is active.
required

Returns:

Type Description
Any

A reactive VNode subtree that swaps to the

Any

fallback whenever a child raises.

load_component

load_component(module_path: str, attr: Optional[str] = None) -> Callable[[Any], VNode]

Dynamically import a module and return a component wrapping the export.

The returned function component renders a small loader until the module finishes importing. On success it renders the loaded component with the forwarded props; on error it renders a minimal error message.

Parameters:

Name Type Description Default
module_path str

Importable Python module path.

required
attr Optional[str]

Optional attribute name on the loaded module. When omitted, the loader picks an export by convention (Page, Component, Default, or first PascalCase symbol).

None

Returns:

Type Description
Callable[[Any], VNode]

A function component that proxies its props to the loaded

Callable[[Any], VNode]

component once it becomes available.

preload_component

preload_component(module_path: str, attr: Optional[str] = None) -> None

Eagerly import a component to warm caches before navigation.

Errors are swallowed so this helper can be safely called as a "best effort" warmup (for example from a hover handler on a <Link>).

Parameters:

Name Type Description Default
module_path str

Importable Python module path.

required
attr Optional[str]

Optional attribute name on the loaded module.

None

create_portal

create_portal(children: Union[VNode, List[VNode]], container: Any) -> VNode

Render children into a different DOM container.

Parameters:

Name Type Description Default
children Union[VNode, List[VNode]]

A single VNode or a list of them.

required
container Any

An Element instance or a CSS selector string identifying the target DOM container.

required

Returns:

Type Description
VNode

A VNode that, when mounted, mounts children into

VNode

container while remaining linked to the surrounding

VNode

component's reactive scope (signals, context, and lifecycle

VNode

hooks still apply).

render

render(vnode: VNode, container: Union[Element, str]) -> Element

Render a VNode tree into a container element.

Subsequent calls with the same container patch the existing tree in place; only the differences are applied. Pass None (via the internal API) to unmount.

Parameters:

Name Type Description Default
vnode VNode

The root VNode to render.

required
container Union[Element, str]

An Element wrapper or a CSS selector string identifying an existing DOM node.

required

Returns:

Type Description
Element

The wrapped container Element. Useful for chaining or for

Element

retaining a reference to the mount point.

Example
from wybthon import h, render

render(h("h1", {}, "Hello, world!"), "#app")
Link(props: Any) -> Any

Anchor element component that navigates via the History API.

Wrapped in a reactive hole so the active class flips automatically when the route changes; no parent re-render is required. Modifier-key clicks (Cmd/Ctrl/Shift) and middle-clicks are passed through to the browser so users can open links in a new tab.

Parameters:

Name Type Description Default
props Any

The component's props with the following keys:

  • to (str): Target path. Joined with the active base path unless it starts with http://, https://, or #.
  • replace (bool): When True, replace the current history entry instead of pushing a new one.
  • class_active (str): Class added when to matches the current path. Defaults to "active".
  • base_path (str): Override for the base path. Defaults to the value provided by the surrounding Router.
  • class / class_ / className: Recognized class spellings, merged with the active class when applicable.
  • All other props are forwarded to the underlying <a> element.
required

Returns:

Type Description
Any

A reactive VNode for the anchor element.

Router

Router(props: Any) -> Any

Function component that renders the matched route's component.

The render function is wrapped in a reactive hole so that updates to current_path automatically re-evaluate the matched route; no parent re-render is required.

Parameters:

Name Type Description Default
props Any

The component's props with the following keys:

  • routes (List[Route]): Declared routes.
  • base_path (str): Base path stripped before matching.
  • not_found: Optional component rendered when no route matches. Falls back to a literal "Not Found" <div>.
required

Returns:

Type Description
Any

A reactive VNode containing the matched

Any

component, wrapped in a Provider that

Any

publishes the active base_path via

Any

navigate

navigate(path: str, *, replace: bool = False) -> None

Programmatically change the current path and update current_path.

Parameters:

Name Type Description Default
path str

Target URL path, including any query string.

required
replace bool

When True, use history.replaceState so the current history entry is overwritten instead of appended.

False

Suspense

Suspense(props: Any) -> Any

Render a fallback while one or more resources are loading.

Parameters:

Name Type Description Default
props Any

The component's props with the following keys:

  • resources / resource: A single Resource or a list of resources. When omitted, the component just renders its children.
  • fallback: VNode, string, or callable returning one of those. Shown while any resource is loading.
  • keep_previous (bool, default False): When True, show previously-resolved children during refetches instead of replacing them with the fallback.
  • children: Children rendered when no resource is loading.
required

Returns:

Type Description
Any

A reactive VNode subtree that toggles

Any

between fallback and children.

Provider

Provider(props: Any) -> Any

Context provider component.

Renders its children transparently. The reconciler stores value as a Signal on this component's ownership scope so that descendants can find it via use_context and react to updates with fine-grained precision.

Children are wrapped in a reactive hole so updates from the parent (for example a router swapping the matched route component) flow into the subtree even though the provider body itself runs only once.

Parameters:

Name Type Description Default
props Any

The component's props with the following keys:

  • context (Context): The context being provided.
  • value: The current value to expose to descendants.
  • children: A VNode or list of VNodes rendered transparently.
required

Returns:

Type Description
Any

A reactive VNode subtree containing the

Any

provider's children.

create_context

create_context(default: Any) -> Context

Create a new Context with the given default value.

Parameters:

Name Type Description Default
default Any

Value returned by use_context when no provider is found above the consumer.

required

Returns:

Type Description
Context

A fresh Context token. Each call returns a context with a

Context

unique id, even when default is the same.

use_context

use_context(ctx: Context) -> Any

Read the current value for ctx from the ownership tree.

Walks up the owner chain looking for the nearest provider that stored a value for this context. The returned value is unwrapped from the provider's signal so callers always observe the current value. When invoked inside a tracking scope (a reactive hole or effect), the dependency on the provider signal is recorded so the scope re-runs whenever the provider updates.

Parameters:

Name Type Description Default
ctx Context

The context token created by create_context.

required

Returns:

Type Description
Any

The nearest provider's current value, or

Any

ctx.default when no provider exists above the caller.

Dynamic

Dynamic(component: Any = None, props: Optional[Dict[str, Any]] = None, **kwargs: Any) -> Any

Render a dynamically-chosen component.

component may be a string tag name, a component function, or None (renders nothing). It can also be a getter for reactive switching.

Parameters:

Name Type Description Default
component Any

Tag name, component callable, getter, or None.

None
props Optional[Dict[str, Any]]

Optional dict of props forwarded to the resolved component.

None
**kwargs Any

Additional props (merged on top of props).

{}

Returns:

Type Description
Any

A reactive VNode that re-mounts whenever

Any

the resolved component identity changes.

Example
Dynamic(component=lambda: heading_level(),
        children=[f"Section {idx}"])

For

For(props_or_each: Any = None, children_pos: Any = None, /, **kwargs: Any) -> Any

Render a list of items using a keyed mapping function.

Component style (reactive):

For(each=items,
    children=lambda item, index: li(item, key=index()))

Inside the callback, item is a signal-backed getter returning the current item value, and index is a signal-backed getter returning the current integer index, matching SolidJS <For>.

For maintains stable per-item reactive scopes keyed by reference identity. The mapping callback runs only once per unique item. When an item leaves the list, its scope (including any effects or cleanups created inside the callback) is disposed.

Parameters:

Name Type Description Default
props_or_each Any

A props dict (component style) or the each getter / list (direct call form).

None
children_pos Any

Positional children callback (direct call form).

None
**kwargs Any

each, children (a (item, index_getter) -> VNode callable), and optional fallback.

{}

Returns:

Type Description
Any

A reactive VNode tree that diffs the list by

Any

item identity.

Index

Index(props_or_each: Any = None, children_pos: Any = None, /, **kwargs: Any) -> Any

Render a list by index with a stable item getter.

Unlike For, the children callback receives (item_getter, index) so that the DOM node for each index is reused even when the underlying data changes.

Index maintains stable per-index reactive scopes. Each slot has a signal-backed item_getter that updates when the value at that position changes. Growing the list creates new scopes; shrinking disposes excess scopes.

Parameters:

Name Type Description Default
props_or_each Any

A props dict (component style) or the each getter / list (direct call form).

None
children_pos Any

Positional children callback (direct call form).

None
**kwargs Any

each, children (a (item_getter, index: int) -> VNode callable), and optional fallback.

{}

Returns:

Type Description
Any

A reactive VNode tree that diffs the list by

Any

index.

Match

Match(when: Any = None, children: Any = None, **kwargs: Any) -> _MatchResult

Declare a branch inside a Switch.

when may be a getter or a plain value. Supports both positional and keyword calling styles:

Match(True, h("p", {}, "yes"))                                # positional
Match(when=lambda: x() > 0, children=lambda: p("positive"))   # keyword

Must be used inside Switch().

Parameters:

Name Type Description Default
when Any

Predicate value or zero-arg getter.

None
children Any

A VNode, a callable returning a VNode, or a plain value to coerce to text.

None
**kwargs Any

Same keys as the explicit parameters; takes priority over positional values when provided.

{}

Returns:

Type Description
_MatchResult

An opaque branch descriptor consumed by Switch.

Show

Show(props_or_when: Any = None, children_pos: Any = None, /, **kwargs: Any) -> Any

Conditionally render children when when is truthy.

Can be called in two styles:

Component style (reactive; recommended for dynamic conditions):

Show(when=count, children=lambda: p("Count: ", count),
     fallback=lambda: p("Empty"))

Direct call (evaluated once; fine inside an explicit hole):

Show(when=lambda: count() > 0,
     children=lambda: p("Positive"),
     fallback=lambda: p("Not positive"))

Behavior:

  • when may be a zero-arg getter or a plain value.
  • children / fallback may be a VNode, a callable, or a plain value. When children is callable and when is truthy, the truthy value is passed as the first argument (matching SolidJS <Show>).

The component creates a keyed conditional scope: when the truthiness of when changes, the previous branch's scope is disposed and a new scope is created. This ensures that effects and cleanups registered inside a branch are properly torn down on transitions.

Parameters:

Name Type Description Default
props_or_when Any

A props dict (component style) or the when value (direct call form).

None
children_pos Any

Positional children slot (direct call form).

None
**kwargs Any

when, children, and optional fallback.

{}

Returns:

Type Description
Any

A reactive VNode tree that re-renders when

Any

the condition's truthiness changes.

Switch

Switch(*branches: Any, fallback: Any = None, **kwargs: Any) -> Any

Render the first matching Match branch, or fallback.

Component style (reactive):

Switch(
    Match(when=lambda: status() == "loading",
          children=lambda: p("Loading...")),
    Match(when=lambda: status() == "ready",
          children=lambda: p("Ready")),
    fallback=lambda: p("Unknown"),
)

Each Match when is evaluated lazily inside the Switch component's reactive scope.

Parameters:

Name Type Description Default
*branches Any

One or more Match results, in priority order.

()
fallback Any

Slot to render when no branch matches. May be a VNode, a callable, or a plain value.

None
**kwargs Any

Optional fallback override.

{}

Returns:

Type Description
Any

A reactive VNode for the first matching

Any

branch, or the fallback slot.

Public API (top-level imports)

  • Core rendering
  • Element, Ref
  • VNode, h, render, Fragment, dynamic, is_getter, memo
  • Components
  • component, forward_ref, ErrorBoundary, Suspense
  • Reactivity
  • create_signal (optional equals=), create_effect, create_memo, batch, untrack, on, create_root, create_selector
  • on_mount, on_cleanup
  • ReactiveProps, get_props, children (memoized children helper), get_owner, run_with_owner
  • Resource, create_resource
  • merge_props, split_props, map_array, index_array
  • Types: Signal, Computed (for type hints; create instances via create_signal / create_memo)
  • Context
  • Context, create_context, use_context, Provider
  • Stores
  • create_store, produce
  • Flow control
  • Show, For, Index, Switch, Match, Dynamic
  • Router
  • Route, Router, Link, navigate, current_path
  • Forms
  • State and validation: FieldState, form_state, validate, validate_field, validate_form
  • Validators: required, min_length, max_length, email
  • Bindings and submit helpers: bind_text, bind_checkbox, bind_select, on_submit, on_submit_validated
  • A11y helpers: a11y_control_attrs, error_message_attrs
  • Events
  • DomEvent
  • Lazy loading
  • lazy, load_component, preload_component
  • Development mode
  • DEV_MODE, set_dev_mode, is_dev_mode

Browser vs non-browser

DOM/VDOM rendering (Element, render, router, etc.) requires a Pyodide/browser environment. In non-browser contexts the reactivity primitives, forms, lazy utilities, and pure-Python VDOM constructs (VNode, h, Fragment, dynamic, memo, is_getter) are still available.