### Full Application Setup with Explicit Wiring
Source: https://stario.dev/tutorials/tiles-walkthrough
Demonstrates a complete application setup in `main.py`, showing explicit wiring of the tracer, application instance, static asset serving, route registration (GET, POST), and server startup with host, port, and worker configuration. This approach avoids hidden configurations and auto-discovery.
```python
import sys
from pathlib import Path
# Assuming Stario, RichTracer, JsonTracer, home, subscribe, click are defined elsewhere
# from stario import Stario
# from tracers import RichTracer, JsonTracer
# from handlers import home, subscribe, click
async def main():
if "--local" in sys.argv or sys.stdout.isatty():
tracer = RichTracer()
host, port, workers = "127.0.0.1", 8000, 1
else:
tracer = JsonTracer()
host, port, workers = "0.0.0.0", 8000, 4
with tracer:
app = Stario(tracer)
app.assets("/static", Path(__file__).parent / "static")
app.get("/", home)
app.get("/subscribe", subscribe)
app.post("/click", click)
await app.serve(host=host, port=port, workers=workers)
```
--------------------------------
### Start Stario App with app.serve()
Source: https://stario.dev/reference/server
The simplest way to run a Stario application is by calling `app.serve()`. This method handles the server setup and execution within an asyncio event loop. It requires importing `asyncio` and the `Stario` class.
```python
import asyncio
from stario import Stario, RichTracer
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Stario Main Application Setup (Python)
Source: https://stario.dev/tutorials/structuring-apps
The main entry point for a Stario application, demonstrating how to create dependencies (database, relay) and pass them to handler factories. It configures the Stario app, registers routes, and starts the server.
```python
# main.py
import asyncio
import sys
from pathlib import Path
from app.db import create_database
from app.handlers import home, send_message, subscribe
from stario import JsonTracer, Relay, RichTracer, Stario
async def main():
is_dev = "--local" in sys.argv or sys.stdout.isatty()
if is_dev:
tracer = RichTracer()
host, port, workers = "127.0.0.1", 8000, 1
else:
tracer = JsonTracer()
host, port, workers = "0.0.0.0", 8000, 4
# Create dependencies
db = create_database(is_dev=is_dev)
relay: Relay[str] = Relay()
with tracer:
app = Stario(tracer)
app.assets("/static", Path(__file__).parent / "app" / "static")
# Register routes - factories are called here with dependencies
app.get("/", home)
app.get("/subscribe", subscribe(db, relay))
app.post("/send", send_message(db, relay))
await app.serve(host=host, port=port, workers=workers)
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Starting the Server with app.serve()
Source: https://stario.dev/reference/server
The simplest way to run your Stario application is by using the `app.serve()` method. This method handles server instantiation and running.
```APIDOC
## POST /websites/stario_dev
### Description
Starts the Stario application server using the `app.serve()` method.
### Method
POST
### Endpoint
/websites/stario_dev
### Parameters
#### Query Parameters
- **host** (string) - Optional - TCP bind address. Defaults to `"127.0.0.1"`.
- **port** (integer) - Optional - TCP port number. Defaults to `8000`.
- **unix_socket** (string) - Optional - Path to a Unix domain socket. Mutually exclusive with `host`/`port`.
- **workers** (integer) - Optional - Number of worker threads. Defaults to `1`.
- **graceful_timeout** (float) - Optional - Seconds to wait for tasks to finish during shutdown. Defaults to `5.0`.
- **backlog** (integer) - Optional - Connection backlog size. Defaults to `2048`.
### Request Example
```json
{
"host": "0.0.0.0",
"port": 8000,
"workers": 4
}
```
### Response
#### Success Response (200)
- **message** (string) - Indicates the server has started successfully.
#### Response Example
```json
{
"message": "Server started successfully"
}
```
```
--------------------------------
### Start Stario Tiles Application
Source: https://stario.dev/tutorials/tiles-walkthrough
Navigates to the project directory and starts the Stario application using uv run. This command executes the main Python file for the application.
```bash
cd tiles
uv run main.py
```
--------------------------------
### Stario Static Asset Setup and Usage (Python)
Source: https://stario.dev/reference/staticassets
This snippet demonstrates how to configure Stario to serve static assets from a local directory. It includes setting up the asset directory, using the `asset()` helper to get fingerprinted filenames, and how to reference these assets in HTML.
```python
from pathlib import Path
from stario import Stario, asset
app = Stario(tracer)
app.assets("/static", Path(__file__).parent / "static")
# In your HTML:
# Link({"rel": "stylesheet", "href": f"/static/{asset('css/style.css')}"})
# Result: /static/css/style.abc123.css
```
```python
app.assets(url_prefix, directory_path)
```
```python
from stario import asset
# Returns "js/app.d41d8c.js"
url = f"/static/{asset('js/app.js')}"
```
--------------------------------
### Initialize Connection Pool and Serve Application (Python)
Source: https://stario.dev/how-tos/database-dependency
This snippet illustrates the production setup for initializing an asynchronous connection pool using `asyncpg` within an `async main()` function. It then creates a Stario application instance and mounts the API router, before starting the server.
```python
async def main():
pool = await asyncpg.create_pool("...")
app = Stario()
app.mount("/api", api_router(pool))
await app.serve()
```
--------------------------------
### Start Stario Server Directly
Source: https://stario.dev/reference/server
For more granular control over the server, you can instantiate the `Server` class directly. This allows you to specify parameters like host, port, and the number of worker threads. The `server.run()` method then starts the server.
```python
from stario.http.app import Server
server = Server(app, host="0.0.0.0", port=8000, workers=4)
await server.run()
```
--------------------------------
### Starting the Server with Server Class
Source: https://stario.dev/reference/server
For more control over server configuration, you can instantiate the `Server` class directly and then run it.
```APIDOC
## POST /websites/stario_dev/run
### Description
Instantiates and runs the Stario `Server` class directly, allowing for explicit configuration of host, port, and workers.
### Method
POST
### Endpoint
/websites/stario_dev/run
### Parameters
#### Request Body
- **host** (string) - Required - TCP bind address. Use `"0.0.0.0"` for all interfaces.
- **port** (integer) - Required - TCP port number.
- **workers** (integer) - Required - Number of worker threads.
- **unix_socket** (string) - Optional - Path to a Unix domain socket. Mutually exclusive with `host`/`port`.
- **graceful_timeout** (float) - Optional - Seconds to wait for tasks to finish during shutdown. Defaults to `5.0`.
- **backlog** (integer) - Optional - Connection backlog size. Defaults to `2048`.
### Request Example
```json
{
"host": "0.0.0.0",
"port": 8000,
"workers": 4
}
```
### Response
#### Success Response (200)
- **message** (string) - Indicates the server is running.
#### Response Example
```json
{
"message": "Server is running"
}
```
```
--------------------------------
### Stario HTML Element Creation Example
Source: https://stario.dev/tutorials/hello-world
Demonstrates how to create HTML elements using Stario's helper functions, including attribute assignment and nested elements. It shows how dictionaries are converted to attributes and how styles are applied.
```python
Div({"class": "box", "style": {"color": "red"}}, "hello ", Span("world"))
```
--------------------------------
### Stario HTML Syntax Rules and Examples
Source: https://stario.dev/reference/html
Explains the syntax rules for Stario's HTML builder, detailing how dictionaries are used for attributes and other types for children. Provides examples of creating simple elements, elements with attributes, nested elements, and merging attributes.
```python
Div("Hello") #
Hello
Div({"class": "container"}, "Hello") #
Hello
Div(H1("Title"), P("Body")) # Nested
Div({"class": "a"}, {"id": "b"}, "Hi") # Merged attributes
```
--------------------------------
### Initialize Stario Project
Source: https://stario.dev/tutorials/tiles-walkthrough
Initializes a new Stario project using the uvx command-line tool. It ensures the latest version of Stario is installed and prompts the user to select a template, such as 'tiles'.
```bash
uvx stario@latest init
```
--------------------------------
### Multi-tenant Example with Host-Based Routing
Source: https://stario.dev/reference/routing
A practical example of using host-based routing to serve different dashboards for different tenants based on their subdomain. It shows how to access the matched subdomain part via `c.req.subhost`.
```python
tenant = Router()
async def dashboard(c: Context, w: Writer) -> None:
org = c.req.subhost # "acme" for acme.myapp.com
host = c.req.host # "acme.myapp.com" (from the Host header)
w.html(Div(f"Dashboard for {org}"))
tenant.get("/dashboard", dashboard)
app.host("*.myapp.com", tenant)
```
--------------------------------
### Install Stario with Package Managers
Source: https://stario.dev/index
Provides instructions for installing the Stario Python package using common package managers like `uv` and `pip`. This step is necessary to use Stario in your Python environment.
```bash
# Using uv
uv add stario
# Using pip
pip install stario
```
--------------------------------
### Initialize Stario Project with uvx
Source: https://stario.dev/index
Initializes a new Stario project using the `uvx` command-line tool, leveraging project templates for a quick start. Ensure you are using the latest version of Stario by specifying `@latest`.
```bash
# Initialize a new Stario project based on one of the templates
uvx stario@latest init
```
--------------------------------
### Stario HTML List Rendering Example
Source: https://stario.dev/reference/html
Shows how to render lists of items using Stario's HTML builder. The example demonstrates creating an unordered list (`Ul`) where each list item (`Li`) contains a user's name, generated dynamically from a list of users.
```python
Ul(*[Li(u.name) for u in users])
```
--------------------------------
### Trigger Server Requests with Datastar Actions in Python
Source: https://stario.dev/reference/datastar
Provides examples of using Datastar's `at.*` helpers to trigger various HTTP requests (GET, POST, PUT, PATCH, DELETE) to the server. Supports specifying request paths and optional parameters like `include` and `selector` for POST requests.
```python
at.get("/path")
at.post("/path", include=["user"], selector="#output")
at.put("/path")
at.patch("/path")
at.delete("/path")
```
--------------------------------
### Datastar `at.get` Helper for Server Requests
Source: https://stario.dev/tutorials/hello-world
Demonstrates the use of the `at.get()` helper function within Datastar to generate a GET request to a specified URL. This function automatically includes all current signals with the request, simplifying server communication.
```javascript
data.on("click", at.get("/increment"))
```
--------------------------------
### Initialize Stario Tracer (Python)
Source: https://stario.dev/reference/telemetry
Demonstrates how to initialize the Stario tracer for development (RichTracer) and production (JsonTracer) environments. It shows the basic setup for integrating Stario with your application.
```python
from stario import Stario, RichTracer, JsonTracer
# Dev: Pretty console output
tracer = RichTracer()
# Prod: Structured JSON logs
tracer = JsonTracer()
app = Stario(tracer)
```
--------------------------------
### Define Basic Routes with Stario
Source: https://stario.dev/reference/routing
Demonstrates how to define basic GET, POST, and catch-all routes using the Stario framework. This is the fundamental way to map HTTP requests to specific handler functions.
```python
app = Stario(tracer)
app.get("/", home)
app.post("/users", create_user)
app.get("/users/*", get_user) # Catch-all
```
--------------------------------
### Install and Run Watchfiles for Hot Reloading
Source: https://stario.dev/how-tos/hot-reload-development
Installs watchfiles as a development dependency and runs the application with `uv run`. This command watches the current directory for changes and restarts the application automatically. Ensure the command passed to watchfiles invokes `python` directly to handle signals correctly.
```bash
uv add --dev watchfiles
uv run watchfiles "python main.py" .
```
--------------------------------
### Factory Function Example (Python)
Source: https://stario.dev/tutorials/structuring-apps
Illustrates a simple factory function in Python that captures dependencies like 'db' and 'relay' in a closure. This pattern is used for dependency injection in Stario.
```python
# The factory captures dependencies in a closure
def subscribe(db: Database, relay: Relay[str]):
async def handler(c: Context, w: Writer) -> None:
# db and relay are available here - captured from outer scope
users = db.get_users()
relay.publish("update", "join")
return handler
```
--------------------------------
### Using Unix Domain Socket
Source: https://stario.dev/reference/server
Demonstrates how to configure the Stario server to listen on a Unix domain socket instead of a TCP port, which is recommended for reverse proxy setups.
```APIDOC
## POST /websites/stario_dev/serve/unix
### Description
Configures and starts the Stario server to listen on a specified Unix domain socket.
### Method
POST
### Endpoint
/websites/stario_dev/serve/unix
### Parameters
#### Request Body
- **unix_socket** (string) - Required - Path to the Unix domain socket file.
- **workers** (integer) - Optional - Number of worker threads. Defaults to `1`.
- **graceful_timeout** (float) - Optional - Seconds to wait for tasks to finish during shutdown. Defaults to `5.0`.
- **backlog** (integer) - Optional - Connection backlog size. Defaults to `2048`.
### Request Example
```json
{
"unix_socket": "/run/myapp/server.sock",
"workers": 2
}
```
### Response
#### Success Response (200)
- **message** (string) - Indicates the server is listening on the Unix socket.
#### Response Example
```json
{
"message": "Server listening on Unix socket /run/myapp/server.sock"
}
```
```
--------------------------------
### Implement Inline Search with Stario and Datastar in Python
Source: https://stario.dev/reference/datastar
An example demonstrating a complete inline search functionality using Stario and Datastar. It includes reading search query signals, fetching data from a database, and patching the DOM with search results.
```python
async def search(c: Context, w: Writer):
# 1. Read signals
signals = await c.signals()
query = signals.get("query", "")
# 2. Patch DOM
results = await db.find(query)
w.patch(Div({"id": "results"},
*[P(r.title) for r in results]
))
```
--------------------------------
### Explicit Observability: Adding Steps (Go)
Source: https://stario.dev/explanation/logging-design
Shows how to record a step and its duration automatically using Stario's context in Go. This example demonstrates the `with c.step("db")` pattern for explicit telemetry.
```go
func handleRequest(c context.Context) {
// ... other logic ...
defer c.step("db.query").end() // Records duration automatically
// ... database query ...
// ... other logic ...
}
```
--------------------------------
### Serve Stario App on Unix Domain Socket
Source: https://stario.dev/reference/server
This example shows how to configure the Stario application to listen on a Unix domain socket. This method is preferred when running behind a reverse proxy on the same machine, as it avoids TCP overhead. The `unix_socket` argument in `app.serve()` specifies the path to the socket file.
```python
await app.serve(unix_socket="/run/myapp/server.sock")
```
--------------------------------
### Shared Socket Directory Setup for Containers
Source: https://stario.dev/how-tos/reverse-proxy-caddy
This snippet shows how to create a shared directory for Unix sockets and set appropriate permissions, specifically for containerized environments like Docker or Podman. It ensures that the container process can write to the directory where sockets will be created. The `:z` option is for SELinux relabeling.
```bash
# Create a shared socket directory
mkdir -p /sockets
chmod 775 /sockets
# Podman: use :z for SELinux relabeling
podman run -v /sockets:/sockets:z myapp
```
--------------------------------
### Live Task List Example: CQRS Implementation in Python
Source: https://stario.dev/explanation/cqrs-pattern
Demonstrates the CQRS pattern for a live task list. It includes a persistent query stream using Server-Sent Events (SSE) to display tasks, a stateless command to add new tasks via POST requests, and notification of changes using a Relay for real-time updates.
```python
relay = Relay()
tasks = []
# 1. The Query (Persistent)
async def task_stream(c: Context, w: Writer):
# Push initial state
w.patch(Ul({"id": "list"}, *[Li(t) for t in tasks]))
# Wait for notifications
async for _ in w.alive(relay.subscribe("tasks")):
w.patch(Ul({"id": "list"}, *[Li(t) for t in tasks]))
# 2. The Command (Stateless)
async def add_task(c: Context, w: Writer):
signals = await c.signals()
tasks.append(signals["new_task"])
# 3. Notify
relay.publish("tasks", None)
w.empty()
```
--------------------------------
### Python SSE Handler for Instant Page Refresh
Source: https://stario.dev/how-tos/hot-reload-development
An example of Python code demonstrating the pattern for instant page refresh using Datastar's Server-Sent Events (SSE) and full-page morphs. The `subscribe` function sends the full HTML page on connect and on every state change, ensuring the client always reflects the latest code.
```python
async def home(c: Context, w: Writer) -> None:
user_id = str(uuid.uuid4())[:8]
c["user_id"] = user_id
w.html(home_view(user_id))
async def subscribe(c: Context, w: Writer) -> None:
signals = await c.signals(HomeSignals)
users.add(signals.user_id)
# Send the full page immediately on connect
w.patch(home_view(signals.user_id))
# Then send it again on every state change
async for event, user_id in w.alive(relay.subscribe("*
```
--------------------------------
### Basic Caddy Reverse Proxy Setup
Source: https://stario.dev/how-tos/reverse-proxy-caddy
This snippet shows the most basic Caddyfile configuration to set up a reverse proxy for a Stario app running on a TCP port. Caddy automatically handles TLS certificate acquisition and renewal from Let's Encrypt.
```caddyfile
example.com {
reverse_proxy localhost:8000
}
```
--------------------------------
### Create API Router with Connection Pool Dependency (Python)
Source: https://stario.dev/how-tos/database-dependency
This example shows how to create a router factory function that accepts a connection pool and returns a `Router` object. The `api_router` function initializes a `Router` and defines an `async` handler `list_items` that acquires a connection from the pool to fetch data from the 'items' table.
```python
def api_router(pool: Pool) -> Router:
r = Router()
async def list_items(c: Context, w: Writer):
async with pool.acquire() as conn:
items = await conn.fetch("SELECT * FROM items")
w.json(items)
r.get("/items", list_items)
return r
# Mounting
app.mount("/api", api_router(my_pool))
```
--------------------------------
### Initialize and Set Up Stario Project
Source: https://stario.dev/tutorials/hello-world
Initializes a new Stario project using the 'uv' package manager and adds the 'stario' dependency. This sets up the basic file structure for the application.
```bash
uv init --app hello-world
cd hello-world
uv add stario
```
--------------------------------
### Minimal Stario App with Plain Text Response
Source: https://stario.dev/tutorials/hello-world
Creates a minimal Stario application that responds with plain text 'Hello, world!' to requests on the root path. It demonstrates basic Stario app initialization, route registration, and server serving.
```python
import asyncio
from stario import Context, Writer, Stario, RichTracer
async def home(c: Context, w: Writer) -> None:
w.text("Hello, world!")
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Stario HTML Conditional Rendering Example
Source: https://stario.dev/reference/html
Illustrates a common pattern in Stario for conditional rendering, where `None` and `False` values are ignored during HTML generation. The example shows rendering a `Span` element only if a user is an admin.
```python
Div(
H1("User"),
Span("Admin") if user.is_admin else None
)
```
--------------------------------
### Stario App Serving Server-Rendered HTML
Source: https://stario.dev/tutorials/hello-world
Extends the minimal Stario app to serve server-rendered HTML content. It utilizes Stario's HTML element helpers to construct a complete HTML page dynamically.
```python
import asyncio
from stario import Context, Writer, Stario, RichTracer
from stario.html import H1, Body, Div, Head, Html, Meta, Title
async def home(c: Context, w: Writer) -> None:
w.html(
Html(
{"lang": "en"},
Head(
Meta({"charset": "UTF-8"}),
Title("Hello World"),
),
Body(
{
"style": {
"font-family": "system-ui",
"padding": "2rem",
"max-width": "600px",
"margin": "0 auto",
}
},
H1("Hello, Stario!"),
Div("This is server-rendered HTML."),
),
)
)
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Multi-Stage Dockerfile for Stario App
Source: https://stario.dev/how-tos/containerization
This Dockerfile uses a multi-stage build to separate dependency installation from the application code. It requires Python 3.14+ and utilizes `uv` for faster dependency management. The first stage installs dependencies, and the second stage creates a lean runtime image.
```dockerfile
# Stage 1: Builder - install dependencies
FROM python:3.14-slim-bookworm AS builder
WORKDIR /app
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/
# Install build deps for C extensions (brotli)
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc build-essential && \
rm -rf /var/lib/apt/lists/*
# Install Python dependencies (cached layer)
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev
# Copy source and sync the project
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Stage 2: Runtime - no build tools
FROM python:3.14-slim-bookworm
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY --from=builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
CMD ["python", "main.py"]
```
--------------------------------
### Initialize Datastar and Create Reactive Counter in Python
Source: https://stario.dev/tutorials/hello-world
This Python code sets up a basic HTML page using Stario components and integrates Datastar for client-side reactivity. It initializes a counter signal and binds UI elements to it for incrementing and decrementing the count without server round-trips.
```python
import asyncio
from stario import Context, Writer, Stario, RichTracer, data
from stario.html import H1, Body, Button, Div, Head, Html, Meta, Script, Title
def page(*children):
"""Base page with Datastar loaded."""
return Html(
{"lang": "en"},
Head(
Meta({"charset": "UTF-8"}),
Title("Hello World"),
Script({
"type": "module",
"src": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-RC.7/bundles/datastar.js",
}),
),
Body(
{"style": {
"font-family": "system-ui",
"padding": "2rem",
"max-width": "600px",
"margin": "0 auto",
}},
*children,
),
)
async def home(c: Context, w: Writer) -> None:
w.html(
page(
Div(
data.signals({"count": 0}),
H1("Counter"),
Div(
{"style": {"display": "flex", "align-items": "center", "gap": "1rem"}},
Button(
{"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}},
data.on("click", "$count--"),
"-",
),
Div(
{"style": {"font-size": "2rem", "font-weight": "bold", "min-width": "3rem", "text-align": "center"}},
data.text("$count"),
),
Button(
{"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}},
data.on("click", "$count++"),
"+",
),
),
),
)
)
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Stario Reactive App with Server Interaction (Python)
Source: https://stario.dev/tutorials/hello-world
This Python script defines a complete Stario application. It includes functions for rendering an HTML page with a reactive counter, handling client-side button clicks, and processing server requests to increment the counter. It uses Stario's context, writer, and HTML element helpers, along with Datastar signals for client-side state management.
```python
import asyncio
from dataclasses import dataclass
from stario import Context, Writer, Stario, RichTracer, at, data
from stario.html import H1, Body, Button, Div, Head, Html, Meta, P, Script, Title
def page(*children):
return Html(
{"lang": "en"},
Head(
Meta({"charset": "UTF-8"}),
Title("Hello World"),
Script({
"type": "module",
"src": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-RC.7/bundles/datastar.js",
}),
),
Body(
{"style": {"font-family": "system-ui", "padding": "2rem", "max-width": "600px", "margin": "0 auto"}},
*children,
),
)
@dataclass
class HomeSignals:
count: int = 0
async def home(c: Context, w: Writer) -> None:
w.html(
page(
Div(
data.signals({"count": 0}),
H1("Hello, Stario!"),
Div(
{"style": {"display": "flex", "align-items": "center", "gap": "1rem"}},
Button({"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}}, data.on("click", "$count--"), "-"),
Div({"style": {"font-size": "2rem", "font-weight": "bold", "min-width": "3rem", "text-align": "center"}}, data.text("$count")),
Button({"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}}, data.on("click", "$count++"), "+"),
),
P(
{"style": {"margin-top": "2rem", "color": "#666"}},
"Or fetch from server: ",
Button({"style": {"padding": "0.25rem 0.75rem", "cursor": "pointer"}}, data.on("click", at.get("/increment")), "Server +1"),
),
),
)
)
async def increment(c: Context, w: Writer) -> None:
signals = await c.signals(HomeSignals)
c("increment", {"from": signals.count})
signals.count += 1
w.sync(signals)
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
app.get("/increment", increment)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Relay with Typed Payloads
Source: https://stario.dev/reference/relay
Demonstrates using generics with Relay to define typed payloads, improving IDE support for message structures. This example uses a dataclass for type safety.
```python
from dataclasses import dataclass
@dataclass
class Msg:
text: str
relay = Relay[Msg]()
relay.publish("chat", Msg(text="Hi"))
```
--------------------------------
### Python Stario App with Server Interaction
Source: https://stario.dev/tutorials/hello-world
A complete Python script for a Stario application that includes a basic page with a counter, buttons for incrementing the count locally, and a button to send a request to the server for incrementing. It sets up routes for the home page and the increment endpoint.
```python
import asyncio
from dataclasses import dataclass
from stario import Context, Writer, Stario, RichTracer, at, data
from stario.html import H1, Body, Button, Div, Head, Html, Meta, P, Script, Title
def page(*children):
"""Base page with Datastar loaded."""
return Html(
{"lang": "en"},
Head(
Meta({"charset": "UTF-8"}),
Title("Hello World"),
Script({
"type": "module",
"src": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-RC.7/bundles/datastar.js",
}),
),
Body(
{"style": {
"font-family": "system-ui",
"padding": "2rem",
"max-width": "600px",
"margin": "0 auto",
}},
*children,
),
)
@dataclass
class HomeSignals:
count: int = 0
async def home(c: Context, w: Writer) -> None:
w.html(
page(
Div(
data.signals({"count": 0}),
H1("Hello, Stario!"),
P({"style": "color: #666"}, "A minimal counter with server interaction."),
Div(
{"style": {"display": "flex", "align-items": "center", "gap": "1rem"}},
Button(
{"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}},
data.on("click", "$count--"),
"-",
),
Div(
{"id": "count", "style": {"font-size": "2rem", "font-weight": "bold", "min-width": "3rem", "text-align": "center"}},
data.text("$count"),
),
Button(
{"style": {"padding": "0.5rem 1rem", "font-size": "1.25rem", "cursor": "pointer"}},
data.on("click", "$count++"),
"+",
),
),
P(
{"style": {"margin-top": "2rem", "color": "#666"}},
"Or fetch from server: ",
Button(
{"style": {"padding": "0.25rem 0.75rem", "cursor": "pointer"}},
data.on("click", at.get("/increment")),
"Server +1",
),
),
),
)
)
async def increment(c: Context, w: Writer) -> None:
signals = await c.signals(HomeSignals)
c("increment", {"from": signals.count})
signals.count += 1
w.sync(signals)
async def main():
with RichTracer() as tracer:
app = Stario(tracer)
app.get("/", home)
app.get("/increment", increment)
await app.serve()
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------
### Using uvloop for Performance
Source: https://stario.dev/reference/server
Instructions on how to integrate `uvloop` with Stario for a faster asyncio event loop, recommended for production environments.
```APIDOC
## POST /websites/stario_dev/serve/uvloop
### Description
Starts the Stario application server using `uvloop` for enhanced performance.
### Method
POST
### Endpoint
/websites/stario_dev/serve/uvloop
### Parameters
#### Request Body
- **host** (string) - Optional - TCP bind address. Defaults to `"127.0.0.1"`.
- **port** (integer) - Optional - TCP port number. Defaults to `8000`.
- **workers** (integer) - Optional - Number of worker threads. Defaults to `1`.
- **graceful_timeout** (float) - Optional - Seconds to wait for tasks to finish during shutdown. Defaults to `5.0`.
- **backlog** (integer) - Optional - Connection backlog size. Defaults to `2048`.
### Request Example
```json
{
"host": "0.0.0.0",
"port": 8000,
"workers": 4
}
```
### Response
#### Success Response (200)
- **message** (string) - Indicates the server has started successfully with uvloop.
#### Response Example
```json
{
"message": "Server started successfully with uvloop"
}
```
```
--------------------------------
### Python Stario Server-Side State Synchronization
Source: https://stario.dev/tutorials/hello-world
Shows how to update server-side state and synchronize it back to the client using `w.sync()`. This method sends an SSE event that Datastar processes to update the client's signals and any bound UI elements.
```python
signals.count += 1
w.sync(signals)
```
--------------------------------
### Accessing Request Body in Stario
Source: https://stario.dev/reference/context
Provides examples for accessing the raw request body or parsed JSON and form data. It shows the asynchronous methods `c.req.json()`, `c.req.form()`, and `c.req.body()` for different content types.
```python
# Parses body as JSON
await c.req.json()
# Parses multipart or url-encoded forms
await c.req.form()
# Returns raw bytes
await c.req.body()
```
--------------------------------
### Define Custom Error Handlers in Stario
Source: https://stario.dev/reference/routing
Provides an example of how to define and register custom error handlers for specific exception types, such as `HttpException`. This allows for centralized and consistent error handling across the application.
```python
def handle_404(c: Context, w: Writer, exc: HttpException):
w.html(Div("Not Found"), status=404)
app.on_error(HttpException, handle_404)
```
--------------------------------
### Serve Static Assets with Stario
Source: https://stario.dev/reference/routing
Demonstrates the simple way to serve static assets like CSS and JavaScript files using `app.assets()`. It also shows how to generate URLs for these assets within your application code.
```python
app.assets("/static", Path(__file__).parent / "static")
# Use in code
href = f"/static/{asset('css/style.css')}"
```
--------------------------------
### Create and Mount Sub-Routers in Stario
Source: https://stario.dev/tutorials/structuring-apps
Demonstrates how to define modular route groups using Stario's Router class and mount them into the main application. This pattern helps in organizing related routes and injecting dependencies into them.
```python
from stario import Router
def chat_router(db: Database, relay: Relay[str]) -> Router:
"""Creates the chat route group with dependencies injected."""
r = Router()
r.get("/", home)
r.get("/subscribe", subscribe(db, relay))
r.post("/send", send_message(db, relay))
return r
def admin_router(db: Database) -> Router:
"""Creates admin routes - could be a separate module entirely."""
async def stats(c: Context, w: Writer) -> None:
users = db.get_users()
messages = db.get_messages()
w.json({"users": len(users), "messages": len(messages)})
r = Router()
r.get("/stats", stats)
return r
# In main.py:
app = Stario(tracer)
app.mount("/chat", chat_router(db, relay))
app.mount("/admin", admin_router(db))
```
--------------------------------
### Stario HTML Trusted Content with SafeString
Source: https://stario.dev/reference/html
Explains how to use `SafeString` in Stario for content that should not be escaped, such as SVGs or pre-sanitized HTML. It shows an example of embedding an SVG string within a `Div` element using `SafeString`.
```python
from stario.html import SafeString
Div(SafeString(""))
```
--------------------------------
### Choose Tracer Implementation (Console/JSON)
Source: https://stario.dev/tutorials/tiles-walkthrough
Select the appropriate tracer implementation based on the environment. `RichTracer` provides pretty console output suitable for development, while `JsonTracer` generates structured JSON logs for production environments.
```python
# Pretty console output for development
tracer = RichTracer()
# Structured JSON logs for production
tracer = JsonTracer()
```
--------------------------------
### Basic Stario App in a Single File
Source: https://stario.dev/tutorials/structuring-apps
Demonstrates a simple Stario application structure within a single `main.py` file. This approach is suitable for small applications but becomes unmanageable as the project grows due to implicit dependencies and difficulty in testing.
```python
# This works for 100 lines. At 500 lines, it's painful.
board = {}
users = set()
relay = Relay()
async def home(c, w): ...
async def subscribe(c, w): ...
async def click(c, w): ...
async def main():
app = Stario(tracer)
app.get("/", home)
app.get("/subscribe", subscribe)
app.post("/click", click)
await app.serve()
```
--------------------------------
### Live Input Validation with Debounce in Stario
Source: https://stario.dev/how-tos/validation-with-datastar
This example illustrates how to implement live form validation as the user types by adding an input event listener with a debounce. This prevents overwhelming the server with every keystroke while providing immediate feedback.
```python
Input(
data.bind("user"),
data.on("input", at.get("/validate"), debounce=0.3) # 300ms delay
)
```
--------------------------------
### Combine w.patch and w.sync (Python)
Source: https://stario.dev/how-tos/datastar-signals-and-patching
Demonstrates combining `w.patch` and `w.sync` within a single handler. Stario batches these operations into a single SSE stream response for efficiency.
```python
async def add_todo(c: Context, w: Writer):
signals = await c.signals()
# 1. Patch the list with the new item
w.patch(Li(signals["new_todo"]), selector="#list", mode="append")
# 2. Sync the input signal back to empty
w.sync({"new_todo": ""})
```
--------------------------------
### Serve an HTML Page in Stario
Source: https://stario.dev/tutorials/tiles-walkthrough
Implements a Stario handler to serve an HTML page. It generates a user ID, adds it to the context, and uses the Writer's html method to send the rendered view.
```python
async def home(c: Context, w: Writer) -> None:
user_id = str(uuid.uuid4())[:8]
c["user_id"] = user_id
w.html(home_view(user_id))
```
--------------------------------
### Accessing Headers in Stario
Source: https://stario.dev/reference/context
Illustrates how to access HTTP headers using the `c.req.headers` object. It covers using `get()` for single header values (with and without defaults) and `getlist()` for headers that may appear multiple times. Header names are case-insensitive.
```python
c.req.headers.get("Authorization") # First value → str | None
c.req.headers.get("Accept", "text/html") # With default → str
c.req.headers.getlist("Set-Cookie") # All values → list[str]
"Content-Type" in c.req.headers # Membership check → bool
# Example with repeated headers
# Request with: Accept-Language: en, Accept-Language: fr
c.req.headers.get("Accept-Language") # "en" (first value)
c.req.headers.getlist("Accept-Language") # ["en", "fr"]
```
--------------------------------
### Stario HTML Security: Automatic Escaping
Source: https://stario.dev/reference/html
Demonstrates Stario's default security feature, which automatically escapes strings to prevent Cross-Site Scripting (XSS) attacks. Shows an example of a script tag being escaped when rendered as HTML content.
```python
Div('')
#
<script>alert(1)</script>
```
--------------------------------
### Accessing Query Parameters in Stario
Source: https://stario.dev/reference/context
Demonstrates how to access and retrieve query parameters from the request object using `c.req.query`. It shows the usage of `get()` for single values (with and without defaults) and `getlist()` for multiple values, as well as membership checking and length retrieval.
```python
c.req.query.get("page") # First value → str | None
c.req.query.get("page", "1") # With default → str
c.req.query.getlist("tags") # All values → list[str]
"page" in c.req.query # Membership check → bool
len(c.req.query) # Number of unique keys
# Example with multi-valued parameters
# /search?tags=python&tags=async&page=2
c.req.query.get("tags") # "python" (first value)
c.req.query.getlist("tags") # ["python", "async"] (all values)
c.req.query.get("page") # "2"
c.req.query.getlist("page") # ["2"] (always a list)
c.req.query.get("missing") # None
c.req.query.getlist("missing") # []
```
--------------------------------
### Initializing Signals in Tiles Template
Source: https://stario.dev/tutorials/tiles-walkthrough
Demonstrates how to initialize signals within a Tiles template using `data.signals()`. The `ifmissing=True` argument ensures that signals are only set if they don't already exist, preserving state across re-renders.
```javascript
data.signals({"user_id": user_id}, ifmissing=True)
```
--------------------------------
### Handle Client Disconnection in SSE Streams with Python
Source: https://stario.dev/reference/exceptions
Illustrates how Stario automatically handles `ClientDisconnected` exceptions when a client closes the connection during an SSE stream. If `w.alive()` is used, the loop naturally exits upon disconnection, allowing for cleanup. This example shows a basic SSE stream subscription.
```python
async def stream(c: Context, w: Writer):
async for msg in w.alive(relay.subscribe("chat")):
w.patch(Div(msg))
# Disconnect happens -> loop ends -> cleanup runs here
```
--------------------------------
### Access Headers with Headers Object
Source: https://stario.dev/tutorials/tiles-walkthrough
Access request headers using the `Headers` object, available via `c.req.headers`. Similar to query parameters, use `.get()` to retrieve a single header value (decoded string) or `.getlist()` to get all values for a header that can appear multiple times.
```python
c.req.headers.get("Authorization") # str | None
c.req.headers.getlist("Set-Cookie") # list[str]
```
--------------------------------
### Load Database URL from Environment Variables
Source: https://stario.dev/how-tos/security
This Python code demonstrates how to securely load sensitive information, such as database connection strings, from environment variables instead of hardcoding them.
```python
import os
DB_URL = os.environ["DATABASE_URL"]
```
--------------------------------
### Real-time Event Streaming with Starlette EventSourceResponse
Source: https://stario.dev/tutorials/tiles-walkthrough
Demonstrates how to create a real-time event stream using a generator function with Starlette's EventSourceResponse. It includes manual polling for client disconnects and highlights the challenge of managing cleanup.
```python
async def subscribe(request: Request):
async def event_generator():
while True:
if await request.is_disconnected():
break # Manual polling for disconnect
data = await get_update()
yield {"data": json.dumps(data)}
return EventSourceResponse(event_generator())
```
--------------------------------
### Auto-select Tracer Based on Environment
Source: https://stario.dev/tutorials/tiles-walkthrough
Automatically select the tracer implementation based on whether the application is run locally (e.g., in a TTY) or in a production environment. This allows for development-friendly output locally and production-ready logging remotely.
```python
import sys
if "--local" in sys.argv or sys.stdout.isatty():
tracer = RichTracer()
else:
tracer = JsonTracer()
```
--------------------------------
### Basic HTML Element Creation with Stario
Source: https://stario.dev/reference/html
Demonstrates the fundamental usage of Stario's HTML builder by creating nested HTML elements using Python functions. It shows how to import necessary components and construct a simple greeting message.
```python
from stario.html import Div, H1, P, A
def greeting(name: str):
return Div(
H1(f"Hello, {name}!"),
P("Welcome to Stario."),
A({"href": "/docs"}, "Read the docs"),
)
```