Skip to content

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); the runtime calls into the platform's real widget libraries directly via Chaquopy on Android and rubicon-objc on iOS. There is no JavaScript bridge.

A taste

import pythonnative as pn


@pn.component
def Counter(initial: int = 0):
    count, set_count = pn.use_state(initial)
    return pn.Column(
        pn.Text(f"Count: {count}", style={"font_size": 24, "bold": True}),
        pn.Button("+", on_click=lambda: set_count(count + 1)),
        style={"spacing": 12, "padding": 16},
    )

That same Counter mounts as a UILabel plus a UIButton inside a UIStackView on iOS, and as a TextView plus a Button inside a vertical LinearLayout on Android. Layouts use flex shorthands; visuals use a single style dict per element.

Why PythonNative?

  • Real native widgets, not a custom renderer. Accessibility, theming, and platform behaviors come along for free.
  • A familiar component model. If you know React or React Native, you already know how PythonNative works.
  • No JS bridge, no transpiler. The reconciler runs synchronously in Python on the platform's main thread; native API calls are direct method calls.
  • Hot reload built in. pn run --hot-reload watches app/ and patches changes into the running app.
  • A small surface. A handful of element factories, a handful of hooks, and one navigation primitive.

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

Next steps