Metadata-Version: 2.4
Name: spaday
Version: 0.1.0
Summary: Build reactive web-component UIs configured in Python, executed in the browser
Project-URL: Repository, https://github.com/1kbgz/spaday
Project-URL: Homepage, https://github.com/1kbgz/spaday
Author-email: 1kbgz <dev@1kbgz.com>
License: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Rust
Requires-Python: >=3.10
Provides-Extra: aiohttp
Requires-Dist: aiohttp; extra == 'aiohttp'
Provides-Extra: cluster
Requires-Dist: pydantic>=2; extra == 'cluster'
Requires-Dist: pyzmq; extra == 'cluster'
Requires-Dist: starlette; extra == 'cluster'
Requires-Dist: transports; extra == 'cluster'
Requires-Dist: uvicorn; extra == 'cluster'
Requires-Dist: websockets; extra == 'cluster'
Provides-Extra: develop
Requires-Dist: aiohttp; extra == 'develop'
Requires-Dist: anywidget; extra == 'develop'
Requires-Dist: build; extra == 'develop'
Requires-Dist: bump-my-version; extra == 'develop'
Requires-Dist: check-dist; extra == 'develop'
Requires-Dist: cibuildwheel; extra == 'develop'
Requires-Dist: codespell; extra == 'develop'
Requires-Dist: flask; extra == 'develop'
Requires-Dist: hatch-js; extra == 'develop'
Requires-Dist: hatch-rs; extra == 'develop'
Requires-Dist: hatchling; extra == 'develop'
Requires-Dist: httpx; extra == 'develop'
Requires-Dist: mdformat; extra == 'develop'
Requires-Dist: mdformat-tables>=1; extra == 'develop'
Requires-Dist: pydantic>=2; extra == 'develop'
Requires-Dist: pytest; extra == 'develop'
Requires-Dist: pytest-cov; extra == 'develop'
Requires-Dist: ruff; extra == 'develop'
Requires-Dist: starlette; extra == 'develop'
Requires-Dist: tornado; extra == 'develop'
Requires-Dist: twine; extra == 'develop'
Requires-Dist: ty; extra == 'develop'
Requires-Dist: uv; extra == 'develop'
Requires-Dist: wheel; extra == 'develop'
Provides-Extra: examples
Requires-Dist: pydantic>=2; extra == 'examples'
Requires-Dist: starlette; extra == 'examples'
Requires-Dist: transports; extra == 'examples'
Requires-Dist: uvicorn; extra == 'examples'
Requires-Dist: websockets; extra == 'examples'
Provides-Extra: flask
Requires-Dist: flask; extra == 'flask'
Provides-Extra: form
Requires-Dist: pydantic>=2; extra == 'form'
Provides-Extra: perspective
Requires-Dist: perspective-python<4.6,>=4.5; extra == 'perspective'
Requires-Dist: pydantic>=2; extra == 'perspective'
Requires-Dist: starlette; extra == 'perspective'
Requires-Dist: transports; extra == 'perspective'
Requires-Dist: uvicorn; extra == 'perspective'
Requires-Dist: websockets; extra == 'perspective'
Provides-Extra: tornado
Requires-Dist: tornado; extra == 'tornado'
Provides-Extra: widget
Requires-Dist: anywidget; extra == 'widget'
Description-Content-Type: text/markdown

# spaday

[![Build Status](https://github.com/1kbgz/spaday/actions/workflows/build.yaml/badge.svg?branch=main&event=push)](https://github.com/1kbgz/spaday/actions/workflows/build.yaml)
[![codecov](https://codecov.io/gh/1kbgz/spaday/branch/main/graph/badge.svg)](https://codecov.io/gh/1kbgz/spaday)
[![License](https://img.shields.io/github/license/1kbgz/spaday)](https://github.com/1kbgz/spaday)
[![PyPI](https://img.shields.io/pypi/v/spaday.svg)](https://pypi.python.org/pypi/spaday)

Build reactive web-component UIs **configured in Python, executed in the browser**.

## Overview

You author a UI as a tree of typed Python components — [WebAwesome](https://webawesome.com) by default,
or any library that ships a [Custom Elements Manifest](https://github.com/webcomponents/custom-elements-manifest).
You attach behavior as **declarative data**: an action DSL (toggle a prop, send a model edit, call an
endpoint) and reactive **bindings** (a control two-way-bound to a state field, or a prop computed from
others). spaday's JavaScript runtime renders the tree to real web components and interprets that
behavior **client-side** — so a toggle or a derived value updates with no round-trip to Python.

That UI state is a [transports](https://github.com/1kbgz/transports) model, so it syncs over any
connection (WebSocket, SSE, Jupyter comm) and any codec; the same tree drops into a web app or a Jupyter
notebook unchanged.

Like transports, spaday is a **Rust core with thin bindings**: the component tree, the diff engine, the
CEM parser, the action interpreter, and the reactive engine live in Rust and compile to **PyO3** (Python
authors the tree) and **wasm** (the browser runs it). One core, two bindings.

```python
from spaday import Widget
from spaday.components.webawesome import WaCard, WaSwitch

# a switch two-way-bound to a state field, rendered in a Jupyter cell
ui = WaCard().child(WaSwitch().text("Lamp").bind("checked", "on", mode="two-way"))
w = Widget(ui, state={"on": True})
w  # flip the switch → w.state["on"] flips in Python; set w.state → the switch follows
```

## Install

```bash
pip install spaday            # core: author + serialize component trees
pip install "spaday[widget]"  # + the Jupyter / anywidget host
```

## Documentation

- **[Tutorial](docs/src/tutorial.md)** — build your first interactive UI, step by step (in a notebook).
- **How-to guides** — [author a component tree](docs/src/components.md),
  [add behavior and reactivity](docs/src/behavior.md),
  [serve and embed an app](docs/src/serving.md),
  [use it in a notebook](docs/src/notebook.md),
  [sync to a server over transports](docs/src/transports.md),
  [wrap an imperative JS library](docs/src/wrappers.md),
  [generate typed classes from a manifest](docs/src/cem.md).
- **[API reference](docs/src/api.md)** — the Python surface.
- **[How spaday works](docs/src/concepts.md)** — the architecture and the reasoning behind it.
