### 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"), ) ```