PythonNative¶
PythonNative is a cross-platform toolkit for building native Android and iOS apps in plain Python. The component model is React-style (function components plus hooks plus a reconciler); rendering and device APIs are native Swift and Kotlin, driven over a small bridge with one transaction per commit. Application components run in Python.
A taste¶
import pythonnative as pn
@pn.component
def Counter(initial: int = 0) -> pn.Node:
count, set_count = pn.use_state(initial)
return pn.Column(
pn.Text(f"Count: {count}", style=pn.style(font_size=24, bold=True)),
pn.Button("+", on_press=lambda: set_count(count + 1)),
style=pn.style(gap=12, padding=16),
)
That same Counter mounts as a UILabel plus a UIButton inside a
UIView on iOS, and as a TextView plus a Button inside a
FrameLayout on Android. The shared Yoga layout engine interprets
flex, padding, and position beside the native widgets.
Platform controls and fonts supply their own intrinsic sizes.
Why PythonNative?¶
- Real native widgets. UIKit and Android controls provide platform behavior. Configure accessibility labels and roles, and test navigation and interaction on each platform.
- A familiar component model. If you know React or React Native, you already know how PythonNative works.
- Python application code. Components run on a dedicated asyncio application thread. Validated commits connect Python state to native widgets.
- Ordinary asyncio. One standard application loop runs Python work
independently of the native UI thread. Components can be
async defand await data right in the body, withSuspenseproviding the loading state declaratively. See the Async + data guide. - Typed from end to end. A component's signature is its prop
list and it returns a
pn.Node, so a strict type checker verifies element trees, props, and conditional children.pn.Styleis aTypedDictwithLiteralenums for every fixed-value field, so mypy and your editor catch typos inalign_itemsorfont_weightbefore the app ever runs. - Screens are components. A screen's parameters are its route
params, so
nav.push(ItemScreen(id=42))is a checked call. Navigators are module-level values, and deep links come from each screen'spath. See Navigation. - Native-backed navigation. Every stack drives the platform's real
navigation controller (fragments on Android,
UINavigationControlleron iOS), so transitions, back gestures, and state preservation are exactly what users expect from a first-class native app. - One theme, typed style sheets, and stores. A
Themedataclass styles the app and its navigators and follows dark mode;StyleSheetnamespaces give styles typed names; and aStoreholds app state with targeted re-renders. See Styling and Managing state. - A Metro-style dev loop.
pn startruns one dev server for the browser preview and every connected debug build. Save a file and each client Fast Refreshes in place, preserving component state; their logs stream back into the same terminal. See the Development workflow. - Dev-mode diagnostics. Uncaught errors show a full-screen RedBox
with the traceback instead of crashing; typos in style keys and
duplicate list keys print "did you mean" warnings; props that don't
match a component's annotations warn; conditional hooks raise at the
source. Every check is skipped in production, and
pn lintcatches hook mistakes before you run the app. - Browser preview.
pn previewrenders your app in a browser tab inside a phone frame, through the same bridge protocol the Swift and Kotlin runtimes speak, so you can iterate on UI, state, and navigation in milliseconds (no simulator boot required). See the Browser preview guide. - An extension SDK.
pythonnative.sdklets you wrap any platform widget as a first-class element with type-checked props throughdefine_component, generates the Swift and Kotlin contract from the same declaration, and PyPI plugins auto-register through thepythonnative.handlersentry-point group. - A small surface. A handful of element factories, a handful of hooks, and three navigators.
Quick links¶
- New here? Start with Getting started.
- Want to see it run right now? Try the Browser preview.
- Want the bigger picture? Read Mental model.
- Looking up an API? Package overview.
- Wrapping a custom widget? Read Custom native components.
- Stuck on an error? Try Troubleshooting.
Project status¶
PythonNative is under active development. The public API documented on this site is the supported surface; expect breaking changes only at minor version bumps until 1.0. See the Changelog for what shipped in each release.
Get involved¶
- Source code: github.com/pythonnative/pythonnative.
- File a bug or feature request: GitHub issues.
- Contribute: Contributing.
Next steps¶
- Install and scaffold your first project: Getting started.
- Learn how the runtime fits together: Architecture.