How it works
Your Python code runs on the device in CPython. pyxpo turns your component tree into native views.
The pieces
| Layer | What it does |
|---|---|
| Your app | Python functions that return components and use hooks. |
| Reconciler | Compares the new tree with the old one and works out the smallest set of changes. |
| Bridge | Sends changes to the native side as batched JSON operations, and sends events back. |
| Native shell | Creates and updates real UIKit views on iOS and Mac, Android views on Android, XAML controls on Windows, and DOM nodes on the web. |
| Runtime | A prebuilt, embedded CPython 3.13.7 with the standard library. |
From a state change to the screen
- A user taps a button. The native view sends a
pressevent over the bridge. - Your
onPresshandler runs in Python and calls a state setter. - The reconciler renders the affected components again and diffs the result.
- The changes go to the native side in one batch, for example one
updateop for a single text node. - The native shell applies the batch on the UI thread.
[{"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.
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.