Cacao
π« Cacao is a reactive Python web framework for building real-time apps with a decorator-based API, component state management, JSON UIs, and WebSocket-powered updates. Ideal for dashboards, internal tools, and hybrid apps (web & desktop).
Install / Use
/learn @cacao-research/CacaoREADME
Cacao
High-performance reactive web framework for Python.
Build dashboards, internal tools, and data apps with a simple API β real WebSocket reactivity, not full-page reruns.
<br>Features Β· Quick Start Β· Examples Β· Components Β· Architecture Β· Static Builds Β· Contributing
</div>v2.0 β Complete rewrite with signal-based reactivity, session-scoped state, plugin hooks, and a Streamlit-like API that doesn't re-run your entire script.
Quick Start
pip install cacao
import cacao as c
c.title("Hello, Cacao!")
c.text("Welcome to the simplest Python web framework")
cacao run app.py
That's it β 3 lines of Python and you have a live web app with hot reload.
Why Cacao?
| Feature | Cacao | Streamlit |
|---------|-------|-----------|
| Reactivity | Signal-based (only changed values update) | Full script re-run on every interaction |
| State | Session-scoped by design | st.session_state bolt-on |
| Updates | WebSocket streaming (instant) | HTTP polling (laggy) |
| Multi-user | Isolated sessions built-in | Shared state issues |
| API | Context managers + decorators | Magic globals |
| Static export | cacao build β no server needed | Not supported |
Features
Reactive Signals
count = c.signal(0, name="count")
@c.on("increment")
async def increment(session, event):
count.set(session, count.get(session) + 1)
Signals are the core of Cacao. When a value changes, only the affected components update β no full-page reruns, no diffing your entire tree.
60+ Built-in Components
Layouts, forms, charts, display elements, navigation β everything you need out of the box.
Multi-Page Apps
with c.page("/"):
c.title("Home")
with c.page("/settings"):
c.title("Settings")
Hash-based routing works both in server mode and static builds.
Static Builds
cacao build app.py
Export your app to a static site (HTML + JS + CSS) that runs entirely in the browser. Deploy to GitHub Pages, Netlify, or any static host β no Python server required.
Plugin Hooks & Auth
Extensible architecture with plugin registration, authentication hooks, and notification toasts.
Dark & Light Themes
c.config(theme="dark") # or "light"
Examples
Interactive Counter
import cacao as c
c.config(title="Counter")
count = c.signal(0, name="count")
@c.on("increment")
async def increment(session, event):
count.set(session, count.get(session) + 1)
@c.on("decrement")
async def decrement(session, event):
count.set(session, count.get(session) - 1)
c.title("Counter")
with c.card():
c.metric("Count", count)
with c.row():
c.button("-", on_click="decrement", variant="secondary")
c.button("+", on_click="increment")
Dashboard with Charts
import cacao as c
c.config(title="Sales Dashboard", theme="dark")
sales = c.sample_sales_data()
c.title("Sales Dashboard")
with c.row():
c.metric("Revenue", "$45,231", trend="+20.1%", trend_direction="up")
c.metric("Orders", "1,247", trend="+12.5%", trend_direction="up")
c.metric("Customers", "842", trend="+5.3%", trend_direction="up")
with c.row():
with c.col(span=8):
with c.card("Revenue Trend"):
c.line(sales, x="date", y="revenue", area=True)
with c.col(span=4):
with c.card("By Category"):
c.pie(sales[:5], values="revenue", names="category", donut=True)
with c.card("Recent Transactions"):
c.table(sales[:10], columns=["date", "category", "revenue", "orders"])
More examples in the examples/ directory:
| Example | Description |
|---------|-------------|
| simple/hello.py | Minimal hello world |
| simple/counter.py | Interactive counter with signals |
| simple/metrics.py | KPI dashboard |
| simple/dashboard.py | Full dashboard with charts |
| chat/app.py | Chat application |
| todo/server.py | Todo list app |
| analytics_dashboard/ | Analytics dashboard |
Components
Layout
| Component | Description |
|-----------|-------------|
| row() | Horizontal flex layout |
| col(span=N) | Column with 12-grid span |
| grid() | CSS grid layout |
| container() | Centered container |
| stack() | Vertical stack |
| split() | Side-by-side split |
| hero() | Hero section |
| card() | Card container |
| tabs() / tab() | Tabbed content |
| accordion() | Collapsible sections |
| modal() | Modal dialog |
| panel() | Sliding panel |
| app_shell() | Full app layout with sidebar |
Display
| Component | Description |
|-----------|-------------|
| title() / text() | Typography |
| markdown() | Markdown with optional TOC |
| code() | Syntax-highlighted code |
| metric() | KPI metric with trend |
| table() | Data table |
| json_view() | Interactive JSON viewer |
| badge() / alert() | Status indicators |
| progress() | Progress bar |
| image() / video() | Media |
| timeline() | Timeline display |
| diff() | Side-by-side diff viewer |
| breadcrumb() | Navigation breadcrumb |
Form
| Component | Description |
|-----------|-------------|
| button() | Button with variants |
| input_field() | Text input |
| textarea() | Multi-line input |
| select() | Dropdown select |
| checkbox() / switch() | Toggle inputs |
| slider() | Range slider |
| date_picker() | Date picker |
| search_input() | Search with suggestions |
| file_upload() | File upload |
| chat() | Chat input interface |
Charts
| Component | Description |
|-----------|-------------|
| line() / area() | Line and area charts |
| bar() | Bar chart |
| pie() / donut() | Pie and donut charts |
| scatter() | Scatter plot |
| gauge() | Gauge meter |
| heatmap() | Heatmap |
| radar() | Radar chart |
| funnel() | Funnel chart |
| treemap() | Treemap |
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PYTHON SERVER β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββββββ β
β β Signals β β Sessions β β Events β β WebSocket/HTTPβ β
β β (state) ββββ (per- ββββ (typed ββββ Server β β
β β β β client) β β async) β β (Starlette) β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββ¬ββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββ
β JSON
β WebSocket
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββ
β REACT CLIENT β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββ΄βββββββ β
β β Hooks β βComponentsβ β Event β β State β β
β βuseCacao()ββββ (60+ UI) ββββDispatcherββββ Store β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data flow:
Python API β JSON definition β WebSocket β React renders
β β
Signal.set() βββ Event handler βββ User action
CLI
cacao run app.py # Run with hot reload
cacao run app.py --port 3000 # Custom port
cacao run app.py --no-reload # Disable hot reload
cacao create my-dashboard # Scaffold a new project
cacao build app.py # Build static site
cacao build app.py --base-path /repo # For GitHub Pages subdirectory
Static Builds
Cacao generates static sites that run entirely in the browser β no Python server required.
cacao build app.py
Output:
dist/
βββ index.html # Your app
βββ cacao.js # Runtime + built-in handlers
βββ cacao.css # Styles
Built-in client-side handlers for common operations:
- Encoders β Base64, URL, HTML entities, JWT decode
- Generators β UUID, passwords, Lorem Ipsum
- Converters β JSON/YAML, case conversion, number bases
- Text β Statistics, regex t
Related Skills
node-connect
350.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
109.9kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
109.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
350.1kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
