architecture

How it works

Your Python code runs on the device in CPython. pyxpo turns your component tree into native views.

The pieces

LayerWhat it does
Your appPython functions that return components and use hooks.
ReconcilerCompares the new tree with the old one and works out the smallest set of changes.
BridgeSends changes to the native side as batched JSON operations, and sends events back.
Native shellCreates and updates real UIKit views on iOS and Mac, Android views on Android, XAML controls on Windows, and DOM nodes on the web.
RuntimeA prebuilt, embedded CPython 3.13.7 with the standard library.

From a state change to the screen

  1. A user taps a button. The native view sends a press event over the bridge.
  2. Your onPress handler runs in Python and calls a state setter.
  3. The reconciler renders the affected components again and diffs the result.
  4. The changes go to the native side in one batch, for example one update op for a single text node.
  5. The native shell applies the batch on the UI thread.
one batch
[{"op": "update", "id": 7, "props": {"text": "Count: 3"}}]

Async code

Python runs on its own thread with an asyncio event loop, so slow work never blocks the UI. Event handlers can be async def, and native modules return awaitables.

python
from pyxpo import Text, use_async

def Weather():
    loading, value, error = use_async(fetch_forecast, [])
    if loading:
        return Text("Loading…")
    return Text(value if not error else "Could not load")

The runtime

pyxpo ships a prebuilt CPython runtime for iOS (device and simulator) and Android. The CLI downloads it on the first native build and keeps it in ~/.cache/pyxpo. Use pyxpo runtime path to see where it is, and pyxpo runtime clean to remove it.

Your app/ folder, pyxpo itself and the native modules you list are bundled into the app. Pure Python packages from PyPI work too.

Hot reload

During pyxpo run, a dev server watches your files. When a file changes, the app reloads the changed modules and renders again. Hook state is kept when the shape of the component stays the same. If you change native config, the dev server warns you that a rebuild is needed.