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.1.tar.gz (146.7 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.1-py3-none-any.whl (174.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cacao-2.0.1.tar.gz
  • Upload date:
  • Size: 146.7 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.1.tar.gz
Algorithm Hash digest
SHA256 01f2e32f46e0caa35860d5f70a2ab5323fb1ca75ceae5e0f7ba630c5fefd4194
MD5 ccad3db047d60f182bb262d5757aa163
BLAKE2b-256 01cddea41e7ab91583ea0823b7c6e378e9e064d9c68e3cdd6c135e9b081d84a7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cacao-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 174.0 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 203d953d7b2f88ec1f4b8dbff9cae3ad23b8cbd2a792797d17275910c2218679
MD5 5406af5814719b46795e05dce5a31c0e
BLAKE2b-256 7da8ec0bc67a44f3b2762a47fc77722e69e488b8fc6b80aaf5d6b7e9702fbe08

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