https://github.com/apiad/auditorium
An HTML+CSS+JS generator from pure Python code
https://github.com/apiad/auditorium
html-css-javascript python visualization
Last synced: 23 days ago
JSON representation
An HTML+CSS+JS generator from pure Python code
- Host: GitHub
- URL: https://github.com/apiad/auditorium
- Owner: apiad
- Created: 2019-11-27T21:00:22.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2026-04-17T19:19:18.000Z (26 days ago)
- Last Synced: 2026-04-17T21:34:32.445Z (26 days ago)
- Topics: html-css-javascript, python, visualization
- Language: Python
- Homepage: https://apiad.net/auditorium
- Size: 2.97 MB
- Stars: 83
- Watchers: 6
- Forks: 14
- Open Issues: 9
-
Metadata Files:
- Readme: Readme.md
- Audit: auditorium/__init__.py
Awesome Lists containing this project
README
# Auditorium
[
](https://github.com/apiad/auditorium/blob/master/LICENSE)
[
](https://pypi.org/project/auditorium/)
[
](https://pypi.org/project/auditorium/)
Auditorium is a Python framework for live technical presentations. You write slides as `async def` functions in a plain `.py` file, and Auditorium runs them as a live presentation in your browser — complete with keypress-gated reveals, timed animations, LaTeX math, syntax-highlighted code, and flexible layouts.
```python
from auditorium import Deck
deck = Deck(title="My Talk")
@deck.slide
async def hello(ctx):
"""# Hello, World!
This is rendered from the **docstring**.
"""
await ctx.step()
await ctx.md("This appeared after pressing right arrow.")
```
```bash
auditorium run talk.py
```
## How it works
Each slide is an `async def` decorated with `@deck.slide`. The docstring renders as Markdown when the slide loads. The function body is imperative Python that drives the presentation through awaitable primitives:
- **Content:** `show(html)`, `hide(selector)`, `replace(selector, html)`, `set_class(selector, cls)`, `remove_class(selector, cls)`
- **Markdown:** `md(text)`, `show_md(path)`
- **Timing:** `step()` (wait for keypress), `sleep(seconds)`
- **Layout:** `columns(sizing)`, `rows(sizing)`, `place(html, x, y)`
A FastAPI server runs your slide functions and pushes DOM mutations over WebSocket to a minimal browser client. Each browser tab gets its own independent session — you can have multiple tabs on different slides simultaneously.
## Installation
Requires Python 3.12+.
```bash
pip install auditorium
```
Or with uv:
```bash
uv add auditorium
```
## Usage
Create a file (e.g. `talk.py`) with a `Deck` instance and `@deck.slide` functions, then run:
```bash
auditorium run talk.py
```
Options:
| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | Host to bind to |
| `--port` | `8000` | Port to bind to |
| `--no-open` | (opens browser) | Don't auto-open the browser |
| `--no-watch` | (watches files) | Disable hot reload |
Hot reload is on by default — edit your `.py` file and the browser stays on the current slide while picking up changes. A small status dot in the bottom-left corner shows connection state (green = connected, red = disconnected, blinking orange = reconnecting).
## Navigation
| Key | Action |
|-----|--------|
| Right arrow / Space | Advance step, or next slide if no pending step |
| Page Down | Skip to next slide (cancel remaining steps) |
| Left arrow | Previous slide (re-runs from start) |
| `r` | Restart current slide |
| Digits + Enter | Jump to slide N |
## Layouts
Layout primitives return `Region` objects that scope insertion targets via `async with`:
```python
@deck.slide
async def side_by_side(ctx):
"""## Two Columns"""
left, right = await ctx.columns([2, 1])
async with left:
await ctx.md("Main content (2/3 width)")
async with right:
await ctx.md("Sidebar (1/3 width)")
```
Sizing accepts integers (proportional), or `"auto"` for natural content size:
```python
@deck.slide
async def structured(ctx):
"""## Header / Body / Footer"""
header, body, footer = await ctx.rows(["auto", 1, "auto"])
async with header:
await ctx.md("### Fixed Header")
async with footer:
await ctx.md("*Fixed footer*")
async with body:
await ctx.md("Body stretches to fill remaining space.")
```
Available: `columns(sizing)`, `rows(sizing)`, `place(html, x, y)`. They nest freely.
## Features
- **Markdown docstrings** — slide content as prose, right next to the code
- **Progressive reveals** — `await ctx.step()` pauses for a keypress
- **Timed animations** — `await ctx.sleep(seconds)` for automatic pacing
- **LaTeX math** — KaTeX via CDN, use `$...$` or `$$...$$` in Markdown
- **Code highlighting** — fenced code blocks highlighted by highlight.js
- **Flexible layouts** — `columns`, `rows`, `place` with `"auto"` sizing
- **Hot reload** — edit and see changes instantly, staying on the same slide
- **Independent sessions** — each browser tab runs its own slide independently
- **Reconnection** — survives server restarts without losing your place
- **No build step** — Tailwind, KaTeX, and highlight.js loaded via CDN
## Example
See [`examples/demo_deck.py`](examples/demo_deck.py) for a complete deck exercising every feature.
```bash
auditorium run examples/demo_deck.py
```
## License
MIT