Skip to main content

High-performance reactive web framework for Python. Build dashboards, internal tools, and data apps with a Streamlit-like API but 10x faster.

Project description

image

Cacao

PyPI Version Downloads Python Versions License Build GitHub Stars


High-performance reactive web framework for Python. Build dashboards, internal tools, and data apps with a simple API — 10x faster than Streamlit with true WebSocket reactivity.

v2.0 - Complete rewrite with signal-based reactivity, session-scoped state, and a Streamlit-like API that doesn't re-run your entire script.

Quick Start

pip install cacao

Hello World (4 lines)

import cacao as c

c.title("Hello, Cacao!")
c.text("Welcome to the simplest Python web framework")

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"])

Run with:

cacao run dashboard.py

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

Core Concepts

Signals (Reactive State)

count = c.signal(0, name="count")

# Get value for a session
current = count.get(session)

# Set value (auto-syncs to client)
count.set(session, current + 1)

Event Handlers

@c.on("submit")
async def handle_submit(session, event):
    print(event.get("value"))

Layout Components

with c.row():           # Horizontal layout
    with c.col(span=8): # 8/12 width column
        c.text("Main content")
    with c.col(span=4): # 4/12 width column
        c.text("Sidebar")

with c.card("Title"):   # Card container
    c.metric("Value", 100)

with c.tabs():          # Tabbed content
    with c.tab("tab1", "First"):
        c.text("Tab 1 content")
    with c.tab("tab2", "Second"):
        c.text("Tab 2 content")

Form Components

c.button("Click me", on_click="submit")
c.input("Name", signal=name_signal)
c.select("Category", ["A", "B", "C"])
c.checkbox("Agree", signal=agree_signal)
c.slider("Volume", min=0, max=100)

Charts

c.line(data, x="date", y="value")
c.bar(data, x="category", y="count")
c.pie(data, values="amount", names="label")
c.area(data, x="date", y="value")
c.scatter(data, x="x", y="y")
c.gauge(value=75, max_value=100)

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                         PYTHON SERVER                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌───────────────┐   │
│  │ Signals  │  │ Sessions │  │  Events  │  │ WebSocket/HTTP│   │
│  │ (state)  │──│ (per-    │──│ (typed   │──│    Server     │   │
│  │          │  │  client) │  │  async)  │  │               │   │
│  └──────────┘  └──────────┘  └──────────┘  └───────┬───────┘   │
└────────────────────────────────────────────────────┼───────────┘
                                                     │ JSON
                                                     │ WebSocket
┌────────────────────────────────────────────────────┼───────────┐
│                      REACT CLIENT                   │           │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────┴──────┐    │
│  │  Hooks   │  │Components│  │  Event   │  │   State     │    │
│  │useCacao()│──│ (your UI)│──│Dispatcher│──│   Store     │    │
│  └──────────┘  └──────────┘  └──────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Project Structure

cacao/
├── __init__.py          # Simple API exports
├── simple.py            # Streamlit-like API
├── server/              # Core server
│   ├── app.py           # App class
│   ├── signal.py        # Signal, Computed
│   ├── session.py       # Session management
│   ├── events.py        # Event handling
│   ├── server.py        # WebSocket server
│   ├── ui.py            # UI components
│   ├── chart.py         # Chart components
│   └── data.py          # Data utilities
├── cli/                 # CLI commands
└── examples/            # Example apps

CLI

# Run an app with hot reload
cacao run app.py

# Run on custom port
cacao run app.py --port 3000

# Create a new project
cacao create my-dashboard

Examples

See the examples/ directory:

  • examples/simple/hello.py - Minimal app
  • examples/simple/counter.py - Interactive counter
  • examples/simple/metrics.py - KPI dashboard
  • examples/simple/dashboard.py - Full dashboard with charts

Contributing

Contributions are welcome! Please read our contributing guidelines for details.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cacao-2.0.5.tar.gz (44.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cacao-2.0.5-py3-none-any.whl (219.5 kB view details)

Uploaded Python 3

File details

Details for the file cacao-2.0.5.tar.gz.

File metadata

  • Download URL: cacao-2.0.5.tar.gz
  • Upload date:
  • Size: 44.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for cacao-2.0.5.tar.gz
Algorithm Hash digest
SHA256 e3b0fa5101a978ab8e37865e58c3af67b761d36e7a1cadf21224eff391b0a943
MD5 5173c9d12a33f9f746b423fd260e61d9
BLAKE2b-256 63c171426ced48ee134bd0da76f589a27f20b36d3d9a55cebc92e03e810e89e0

See more details on using hashes here.

File details

Details for the file cacao-2.0.5-py3-none-any.whl.

File metadata

  • Download URL: cacao-2.0.5-py3-none-any.whl
  • Upload date:
  • Size: 219.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for cacao-2.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 d03d21c56a1948c9c21b42cd325be4a0994019b08402bb6ef31eca9de64285c9
MD5 f5e4c16eb74649c156b5b1992cde11e0
BLAKE2b-256 70179824d21eaf9b50d9102ddfef72af79fd966b547c5ad90454013ad9058f5c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page