Hello world¶
The smallest possible PythonNative app. You'll learn how to:
- Define a component with
@pn.component. - Manage state with
use_state. - Compose elements with
pn.Column. - Run it with
pn previewandpn run.
The code¶
Save this as app/main.py:
import pythonnative as pn
@pn.component
def App():
count, set_count = pn.use_state(0)
return pn.Column(
pn.Text(f"Count: {count}", style={"font_size": 24, "bold": True}),
pn.Button("Tap me", on_press=lambda: set_count(count + 1)),
style={"spacing": 12, "padding": 16, "align_items": "stretch"},
)
What's happening¶
@pn.componentregistersAppas a function component. Hooks (likeuse_state) work because the decorator establishes a hook context for each call.pn.use_state(0)returns(value, setter). The setter triggers a re-render scheduled on the Python application thread.pn.Column(*children, style=...)returns a vertical container element. Both the children and the style are read on every render; the reconciler diffs them against the previous render and updates the underlyingUIView/FrameLayoutin place.pn.Textandpn.Buttonmap to native widgets via their Swift and Kotlin component managers.- After every commit a layout pass computes
frame for each widget using Yoga and the platform's intrinsic
measurements.
spacing,padding, andalign_itemsfollow shared layout rules; fonts and control sizes can differ by platform.
Run it¶
Preview in the browser¶
For the fastest feedback loop, start the dev server and open the
browser preview before reaching for an emulator or simulator. The
preview imports your real app code, so if your project declares
packages in [requirements].packages, pip install them first (this
example needs emoji). From the project root:
A browser tab opens with app/main.py's App in a phone frame. Edit a
component, save, and the preview refreshes in place. See the
Browser preview guide for the toolbar
and more options.
Run on a device or simulator¶
Leave pn preview running and, from the project root in another
terminal:
pn run will:
- Stage your
app/and the bundledpythonnativepackage into the appropriate native template underbuild/. - Build it (
gradle installDebugon Android,xcodebuildon iOS), unless an identical native build already exists. - Install and launch it on a connected device or simulator, pointed at the running dev server.
- Stream logs back to the terminal.
The app is now a dev client: saves under app/ Fast Refresh it, and
its output shows up in the pn preview terminal. See the
Development workflow for the details.
Next steps¶
- Build a slightly richer counter: Counter.
- Add a second screen and navigation: Navigation.
- Learn the runtime model: Mental model.