Build Your First Stario App ¶
In this tutorial, you'll build a real-time counter that demonstrates Stario's core: handlers, the Writer, and Datastar integration.
Step 1: Initialize Your Project ¶
The fastest way is using the CLI:
pip install stario
stario init myapp --template hello-world
cd myapp
This sets up a project with uv and includes the Datastar client library.
Step 2: The Handler Pattern ¶
Every Stario handler has the same signature:
async def handler(c: Context, w: Writer) -> None:
pass
- Context (
c): Read request data (query, body, signals). - Writer (
w): Send responses (HTML, JSON, SSE patches).
Step 3: Build the Counter ¶
Update main.py with this reactive counter:
from stario import Context, Writer, Stario
from stario.html import Div, Button, H1
from stario.datastar import data, at
async def home(c: Context, w: Writer) -> None:
w.html(
Div({"id": "app"},
data.signals({"count": 0}),
H1("Counter"),
Div(data.text("$count")),
Button(data.on("click", at.post("/inc")), "+1"),
)
)
async def increment(c: Context, w: Writer) -> None:
signals = await c.signals()
w.sync({"count": signals.get("count", 0) + 1})
import asyncio
app = Stario()
app.get("/", home)
app.post("/inc", increment)
if __name__ == "__main__":
asyncio.run(app.serve())
What's happening? ¶
data.signalsinitializes reactive state on the client.data.textbinds the display to the$countsignal.at.post("/inc")sends the current signals to the server.c.signals()reads those signals on the server.w.sync()updates the signals back on the client via SSE.
Next Steps ¶
- Reference: Writer - All response types.
- Reference: Datastar - Reactive attributes.
- How-to: Real-time Streaming - Add
w.alive()andRelay.
