# Oxid > Oxid is a fine-grained reactive UI framework for Python in the browser, running on its own > Python runtime compiled to WebAssembly, with an HTTP server (`oxid-server`, Rust around the > same runtime) in the same package. Apache 2.0, by Optersoft. Current version: 0.20.0. - Install: `pip install oxid` (Python 3.14; the wheel for macOS and Linux carries the compiler and the server binary). `uvx oxid …` runs the command line without installing. - An app is a directory of static files: `oxid build APP --out DIR` writes the page, the runtime and the app's import closure as precompiled bytecode. No JavaScript toolchain. - Signals, memos and effects update the exact text node or attribute that read them; a component body runs once. Templates are Python 3.14 template strings, `html(t"…")`, or the `h` builder (`h.div(…)`). - Commands: `oxid build`, `serve` (dev server that swaps changed modules into the page), `prerender`, `site`, `check`, `new server`, `islands`, `tailwind`; `oxid-server app.py`. ## Rules a model should know before writing Oxid code - The browser runs Oxid's own runtime, a subset of Python: no `typing` at runtime, no dataclasses, string annotations only, and only the standard modules the runtime has. PyPI packages with C extensions do not run in the page. - `html(f"…")` is plain text, not a template: use a t-string, `html(t"…")`. `oxid check` flags it. - Anything callable inside a template is a hole that updates in place. Name the function you put in a hole; a `lambda` inside `{…}` is flagged by `oxid check`. - APIs where order matters take pairs, not dicts: `record(("title", text()), ("n", integer()))`, `tabs([("Trend", view), …])`. - A page's module must not import `oxid_server`: put the shared `record` in its own module, or `oxid build` ships the server into the browser and the page fails at boot. - On the server, module-level state is per worker (one interpreter per worker thread); keep shared state in the database. `@app.on_startup(once=True)` runs a hook on one worker. - Build the page from a folder that holds only the page when `App(static=…)` serves the output. - `oxid-server --runtime cpython app.py` runs the same file with the handlers on CPython, for code that needs pandas or other CPython packages. ## Docs ### Building and shipping - [Basic](https://academy.optersoft.com/python/oxid/basic): A first Oxid app in the browser, the signal that makes it react, and the one rule that decides whether a piece of the page updates itself. - [Ship](https://academy.optersoft.com/python/oxid/ship): From a folder of Python to a public URL — three mistakes a browser catches and CPython misses, what a build writes, a pipeline that blocks a broken page. - [Template](https://academy.optersoft.com/python/oxid/template): Everything an Oxid template can say — holes, attributes, properties, class and style prefixes, delegated events, two-way bindings — and the builder API. - [Style](https://academy.optersoft.com/python/oxid/style): Tailwind CSS in an Oxid app, with no build step while learning and a one-command build for production. - [Flow](https://academy.optersoft.com/python/oxid/flow): Conditions and lists that keep their elements instead of rebuilding them — Show, Switch, a keyed For — and a store that updates one hole per field change. ### Data and navigation - [Async](https://academy.optersoft.com/python/oxid/async): A request as a reactive value — a Resource's five states, boundaries that show loading and failure so holes never check, actions, async memos, transitions. - [Router](https://academy.optersoft.com/python/oxid/router): The URL as state — nested routes that rebuild only what changed, preloading links, a query cache, stacked titles, split routes, what a screen reader hears. - [State](https://academy.optersoft.com/python/oxid/state): A class whose attributes are signals, widgets that bind to them, a timer that is an accessor, and merging fresh data into a list without rebuilding rows. - [Form](https://academy.optersoft.com/python/oxid/form): One schema, two boundaries — a form checked as it is typed, and the answer from a server checked before anything reads it. ### Making sure it works - [Testing](https://academy.optersoft.com/python/oxid/testing): Run an Oxid app with no browser, click its widgets, and assert on what it drew — in milliseconds, from pytest. ### Faster first paint - [Prerender](https://academy.optersoft.com/python/oxid/prerender): Writing an app's pages as finished HTML at build time, so they show before Python loads, and hydrating them in the browser. - [Islands](https://academy.optersoft.com/python/oxid/islands): A page with nothing to run downloads nothing to run it — and the parts of it that are interactive come alive one at a time, when the reader reaches them. - [Content](https://academy.optersoft.com/python/oxid/content): A directory of Markdown files whose front matter is checked by a schema, rendered on your machine at build time, with an island where the prose needs one. - [Sites](https://academy.optersoft.com/python/oxid/sites): A whole site as a directory of files — the tree is the site map, layouts are components, endpoints are modules, and a second language is a directory. ### A server of your own - [Server](https://academy.optersoft.com/python/oxid/api): A server for the page you already wrote — FastAPI's shape on Rust, and one record validating the form, the body it posts and the route it posts to. - [Routes and pages](https://academy.optersoft.com/python/oxid/routes): Routes in files of their own, files and uploads that never pass through Python, error pages for people, and pages rendered per request. - [Who is asking](https://academy.optersoft.com/python/oxid/auth): Sessions, passwords, keys and tokens, checked in Rust before your handler runs — what the handler still decides, and a route's limits. - [Live](https://academy.optersoft.com/python/oxid/live): A socket in both directions — `@app.websocket` on the server, a `Hub` that reaches every worker, and `oxid.live`, a signal in the page. - [Running it](https://academy.optersoft.com/python/oxid/operate): The server as a process someone else runs — settings checked before it binds, a drain that loses nothing, logs you can follow, and one image to ship. ### Showing data - [Chart](https://academy.optersoft.com/python/oxid/chart): Your first charts — take a table of 406 cars and say what to draw, one column at a time, until the picture answers a question the table could not. - [Components](https://academy.optersoft.com/python/oxid/components): A table, a layout, a map and a signal-processing library that cost nothing until imported — the entry-point protocol, what a build does, and writing one. - [Polars](https://academy.optersoft.com/python/oxid/polars): Keep a big dataset on a server with polars, ask it named questions from the page, and let the answers — never the data — drive metrics, charts and grid. - [Database](https://academy.optersoft.com/python/oxid/database): A page that talks to Postgres with no server of its own — queries as resources, writes the database refuses, and why authorisation belongs with the data. ### Going further - [Chat](https://academy.optersoft.com/python/oxid/chat): A conversation that streams — the log, the box, and an answer that grows one text node while twenty bubbles above it are never touched. - [Wasm libraries](https://academy.optersoft.com/python/oxid/wasm): Call a C or Rust library from an Oxid app by importing it — what a crossing costs, measured, and the one rule that follows from it. ## Site - [Oxid](https://oxid.optersoft.com/): the landing page - [Gallery](https://oxid.optersoft.com/gallery/): apps built with the real command, each measured cold - [Playground](https://oxid.optersoft.com/playground/): write an app and run it in the browser - [PyPI](https://pypi.org/project/oxid/): the package and its release history ## Optional - [Academy index](https://academy.optersoft.com/python/oxid): the course's landing page, with the order of the chapters