Metadata-Version: 2.4
Name: stario
Version: 3.0.0
Summary: Stario - High-performance Python web framework
Author-email: Adam Bobowski <adam.bobowski@wratilabs.com>
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiofiles>=24.1.0
Requires-Dist: brotli>=1.1.0
Requires-Dist: click>=8.1.0
Requires-Dist: httptools>=0.7.1
Requires-Dist: rich>=14.1.0
Requires-Dist: xxhash>=3.5.0
Requires-Dist: watchfiles>=1.1.0
Dynamic: license-file

<p align="center">
  <picture>
    <img alt="stario-logo" src="https://raw.githubusercontent.com/bobowski/stario/main/docs/img/stario.png" style="height: 200px; width: auto;">
  </picture>
</p>

<p align="center">
  <em>Real-time Hypermedia for Python (3.14+)</em>
</p>

---

**Documentation**: [stario.dev](https://stario.dev) · **Source**: [github.com/bobowski/stario](https://github.com/bobowski/stario)

---

## What is Stario?

Stario is a small, explicit, **hypermedia-first** Python framework for building real-time apps close to the web.

It stays close to the real web:

- **HTTP request/response**
- **HTML as the app surface**
- **SSE and streaming for realtime updates**
- **Datastar as the blessed reactive model**
- **Relay for narrow command/query coordination**

Not every Stario app needs Datastar. Plain HTTP + HTML should remain a first-class path, and when realtime or client-side reactivity is needed, Stario should make Datastar feel simple, native, and obvious to adopt.

## Golden Path

Install Stario, create a project, then run the app through the CLI with a `bootstrap(app, span)` entrypoint.

```bash
uv add stario
stario init
cd your-app
uv run stario watch main:bootstrap
```

Minimal shape:

```python
import stario.responses as responses

from stario import Context, Span, Stario, Writer


async def home(c: Context, w: Writer) -> None:
    responses.text(w, "Hello from Stario")


async def bootstrap(app: Stario, span: Span) -> None:
    span.attr("app.name", "example")
    app.get("/", home, name="home")
```

The default expectation is:

- Write handlers as `async def handler(c: Context, w: Writer) -> None`
- Register routes explicitly with `app.get(...)`, `app.post(...)`, and `app.mount(...)`
- Use `bootstrap(app, span)` as the app entrypoint for `stario serve` / `stario watch`
- Reach for Datastar only when the app actually needs live reactivity

## Current Style

- **`Stario` owns application semantics** - routes, names, errors, background tasks, assets
- **`Context` and `Writer` are the core handler primitives** - request-side data on `Context`, response-side behavior on `Writer`
- **Routing is explicit** - no decorator magic, no hidden registration
- **HTML is Python** - views are normal functions returning `stario.html` trees
- **`bootstrap(app, span)` is the main integration point** - create shared dependencies, mount routers, register assets, annotate startup
- **Telemetry is part of the model** - use `span.attr(...)`, `span.attrs(...)`, and `span.event(...)` during bootstrap and request handling

## Runtime Choices

For most apps, **bless the CLI**:

```bash
uv run stario watch main:bootstrap
uv run stario serve main:bootstrap
```

That keeps the normal app shape simple: define `bootstrap(app, span)` and let the CLI own process startup, reload, and runtime wiring.

Use `Server(...)` when you explicitly want to own runtime policy in Python: custom startup, custom tracer setup, embedding Stario in another process, or running without the CLI.

```python
import asyncio
import sys
from contextlib import asynccontextmanager

import stario.responses as responses

from stario import Context, Span, Stario, Writer
from stario.http.server import Server
from stario.telemetry import JsonTracer, RichTracer


async def home(c: Context, w: Writer) -> None:
    responses.text(w, "Hello from Stario")


@asynccontextmanager
async def bootstrap(app: Stario, span: Span):
    app.get("/", home, name="home")
    yield


async def main() -> None:
    tracer_factory = RichTracer if sys.stdout.isatty() else JsonTracer
    with tracer_factory() as tracer:
        await Server(bootstrap, tracer).run()


if __name__ == "__main__":
    asyncio.run(main())
```

If you already have a plain async `bootstrap(app, span) -> None`, wrap it with `normalize_bootstrap(...)` before passing it to `Server(...)`.

## Core Ideas

- **Teach the web, not framework magic** - learning Stario should mostly teach durable web concepts
- **Be hypermedia-first** - HTTP, HTML, SSE, and progressive enhancement should define the model
- **Use Datastar natively where it fits** - Datastar is the blessed reactive path, but not a requirement for every app
- **Keep core small** - only core primitives that are obvious, frequent, and central to the model belong there
- **Prefer explicit setup** - no hidden behavior, no misleading abstractions
- **Choose sharp primitives over convenience layers** - `Context`, `Writer`, HTML, SSE, relay, bootstrap
- **Build with observability in mind** - telemetry is part of the Stario model for building and maintaining apps
- **Keep integrations around core** - codecs, broker backends, sessions, and similar adapters should stay opt-in
- **Always leave an escape hatch** - users should be able to drop to native libraries without fighting the framework

## Boundaries

- **Core**: bootstrap, routing, request parsing, response writing, HTML, SSE, Datastar, relay, compression, telemetry
- **Around core**: codecs for `pydantic`/`attrs`/`cattrs`/`msgspec`, relay backends, sessions, assets
- **Avoid**: giant batteries-included platform behavior, fake universal broker APIs, implicit plugin discovery, service-locator design

## Programming Model

- **`Stario`** owns application semantics
- **`Server`** owns runtime and delivery policy
- **`Context`** owns request-side data and app-facing services
- **`Writer`** owns response-side and wire-level behavior
- **Middleware** is for cross-cutting policy, not for core request/response primitives

## Get Started

Install with `uv add stario` or `pip install stario`, then run `stario init` to create a new project. Requires **Python 3.14+**.

See the [documentation](https://stario.dev) for tutorials, API reference, and how-to guides.

---

<p align="center"><em>Stario: Real-time hypermedia, made simple.</em></p>
