BETA SOFTWARE — APIs are stabilising. Core features are complete and test-covered. Minor breaking changes may still occur before 1.0.
Framework-agnostic server components with LiveView-style interactivity inspired by Phoenix LiveView and Laravel Livewire.
Current Version: 0.4.0-beta API Documentation: fsecada01.github.io/component-framework
The framework has a complete, tested feature set covering the full Beta roadmap. APIs are solidifying — the core lifecycle, permissions, composition, and testing utilities are stable. We welcome feedback before the 1.0 release.
| Framework | Status | Install extra | Notes |
|---|---|---|---|
| FastAPI | ✅ Supported | [fastapi] |
Includes JinjaX renderer and WebSocket adapter |
| Django | ✅ Supported | [django] |
Includes Channels, Cotton, and template renderer |
| Litestar | ✅ Supported | [litestar] |
HTTP + WebSocket adapters (0.4.0+) |
| Flask | 🗓 Planned | — | Tracking issue #5 |
Install only what you need — pydantic is the only mandatory dependency:
# Django projects
pip install "component-framework[django]"
# FastAPI projects
pip install "component-framework[fastapi]"
# Litestar projects
pip install "component-framework[litestar]"
# Multiple adapters
pip install "component-framework[fastapi,django,litestar]"
# Everything
pip install "component-framework[all]"
⚠️ Breaking change in 0.3.0:fastapi,uvicorn, andjinjaxare no longer installed by default.
If you were using the FastAPI adapter, add [fastapi] to your install command:
# Before
pip install component-framework
# After
pip install "component-framework[fastapi]"CI pipelines — any workflow step that installs component-framework without
specifying an extras group will stop receiving FastAPI automatically. Update all
install commands in your GitHub Actions, Dockerfile, tox.ini, Makefile, or other
CI configuration files.
See CHANGELOG.md for the full list of changes.
- Framework-agnostic — Works with FastAPI, Django, Litestar, and more
- Server-driven UI — State lives on the server, not the client
- Minimal JavaScript — HTMX handles frontend interactions
- Reusable components — Clean OOP boundaries with lifecycle hooks
- Pluggable renderers — Jinjax, Django templates, or your own
- Async event handlers —
async def on_*handlers properly awaited viaasync_dispatch() - SSE streaming —
StreamingComponentfor long-running operations with intermediate renders - State size guard — Configurable warning (64 KB) and hard limit (512 KB) on serialised state
- Pydantic validation — Type-safe form handling
- Field-level errors — Live error feedback
- Automatic state sync — Form state synchronised with component state
- Permission classes —
AllowAny,IsAuthenticated,IsStaff,IsSuperuser,DjangoModelPermission - FBV decorators —
login_required_component,permission_required_component,staff_required_componentreturning JSON 401/403 - Component-level control —
permission_classesattribute checked by both FBV and CBV automatically - JSON-only responses — No login redirects for API/HTMX consumers
RateLimitMixin— Per-component, per-user sliding-window rate limiting- Configurable — Custom limits and windows per component class
- 429 responses — Consistent JSON
{"error": "Rate limit exceeded"}on breach
SlotComponent— Named and default slot supportCompositeComponent— Compose components from named child components- Context propagation — Parent context flows to child components
OptimisticMixin—get_optimistic_patch()for instant client-side feedback before server confirmation- Rollback support — Revert on error
- Model binding — Direct ORM integration
- Query optimisation —
select_related,prefetch_related - Transaction support — Safe database updates
- Django templates — Native template rendering
- Cotton support —
django-cottonintegration - CBVs — Class-based views with auth/permissions, JSON error responses
- WebSocket support — Real-time component updates
- SSE streaming —
StreamingComponentwith async generator handlers for progressive rendering - Broadcasting — Multi-client synchronisation
- Django Channels — Full Channels integration
- FastAPI WebSocket — Native FastAPI support
- Litestar WebSocket — Native Litestar support
CacheMixin— Configurable per-component render caching- Cache invalidation — Manual and event-driven invalidation
- Django cache backend — Works with any Django cache backend
ComponentTestCase— Test components without HTTP, without a running server- Event simulation —
dispatch_event(),mount_component() - State assertions —
assert_state(),assert_rendered() - pytest fixtures — Ready-to-use fixtures for common patterns
git clone https://github.com/fsecada01/component-framework.git
cd component-framework
# Install with uv (recommended)
uv pip install -e ".[dev]"python examples/fastapi_example.py
# Open http://localhost:8000cd examples/django_example
python manage.py migrate
python manage.py runserver
# Open http://localhost:8000API Reference: fsecada01.github.io/component-framework
Generated from docstrings by pdoc and deployed to GitHub Pages on every push to master and on every v* release tag.
| Guide | Description |
|---|---|
| Architecture Overview | Core design and component lifecycle |
| Django Implementation | Django adapter setup and patterns |
| Class-Based Views | CBV auth/permission patterns |
| E-Commerce Example | Real-time cart + product demo |
- Project Context — loaded automatically by Claude Code
- Orchestration Workflow — multi-agent routing, model selection, RTK
from component_framework.core import Component, registry
@registry.register("counter")
class Counter(Component):
template_name = "counter.html"
def mount(self):
self.state["count"] = 0
def on_increment(self, amount: int = 1):
self.state["count"] += amountfrom pydantic import BaseModel, EmailStr
from component_framework.core import FormComponent
class ContactSchema(BaseModel):
name: str
email: EmailStr
message: str
@registry.register("contact_form")
class ContactForm(FormComponent):
schema = ContactSchema
def on_submit(self):
send_email(self.validated_data)from component_framework.core.permissions import IsAuthenticated
from component_framework.adapters.django_ratelimit import RateLimitMixin
@registry.register("order_actions")
class OrderActions(RateLimitMixin, Component):
permission_classes = [IsAuthenticated]
rate_limit = 10 # requests
rate_limit_window = 60 # seconds
def on_submit_order(self):
...from component_framework.core.composition import SlotComponent, CompositeComponent
@registry.register("card")
class Card(SlotComponent):
template_name = "card.html"
slots = ["header", "body", "footer"]
@registry.register("product_page")
class ProductPage(CompositeComponent):
components = {
"card": Card,
"cart": CartComponent,
}from component_framework.adapters.django_model import DjangoModelComponent
@registry.register("order_editor")
class OrderEditor(DjangoModelComponent):
model = Order
state_fields = ["status", "notes", "total"]
select_related = ["customer"]
def on_update_status(self, status: str):
self.instance.status = status
self.save_instance()from component_framework.testing import ComponentTestCase
class TestCounter(ComponentTestCase):
def test_increment(self):
component = self.mount_component("counter")
self.assert_state(component, count=0)
self.dispatch_event(component, "increment", amount=5)
self.assert_state(component, count=5)Browser (HTMX/WebSocket/SSE)
|
Framework Adapter (FastAPI / Django / Litestar)
|
Component Framework Core
- Component lifecycle (mount → hydrate → handle_event → render → dehydrate)
- Event routing (convention-based on_<event> handlers, sync + async)
- State management (server-owned JSON state with size guards)
- Streaming (StreamingComponent for SSE progressive rendering)
- Permissions (per-component permission_classes)
- Composition (SlotComponent, CompositeComponent)
|
Backend (Database / Services)
component-framework/
├── src/component_framework/
│ ├── core/ # Framework-agnostic core
│ │ ├── component.py # Base Component class + lifecycle
│ │ ├── form.py # Pydantic form validation
│ │ ├── websocket.py # WebSocket manager
│ │ ├── registry.py # Component registration
│ │ ├── renderer.py # Renderer interface
│ │ ├── state.py # State storage
│ │ ├── streaming.py # StreamingComponent + SSE support
│ │ ├── permissions.py # Permission classes (Beta)
│ │ └── composition.py # Slot + composite components (Beta)
│ │
│ ├── adapters/ # Framework adapters
│ │ ├── fastapi.py # FastAPI integration
│ │ ├── fastapi_websocket.py # FastAPI WebSocket
│ │ ├── django_views.py # Django views (FBV + CBV)
│ │ ├── django_model.py # Django model binding
│ │ ├── django_renderer.py # Django template rendering
│ │ ├── django_websocket.py # Django Channels
│ │ ├── django_permissions.py # FBV permission decorators (Beta)
│ │ ├── django_ratelimit.py # Rate limiting mixin (Beta)
│ │ ├── jinjax_renderer.py # Jinjax rendering
│ │ ├── litestar.py # Litestar HTTP + SSE adapter
│ │ └── litestar_websocket.py # Litestar WebSocket adapter
│ │
│ ├── testing.py # ComponentTestCase + fixtures (Beta)
│ ├── components/ # Example components
│ └── templatetags/components.py # Django template tags
│
├── examples/
│ ├── fastapi_example.py # FastAPI demo
│ ├── litestar_example.py # Litestar demo
│ └── django_example/ # Complete Django app
│
├── tests/ # 23 test modules, 404 tests
│ ├── test_component.py # Core component + async dispatch tests
│ ├── test_form.py # Form validation tests
│ ├── test_registry.py # Registry tests
│ ├── test_state.py # State storage tests
│ ├── test_streaming.py # StreamingComponent + SSE tests
│ ├── test_websocket.py # WebSocket manager tests
│ ├── test_fastapi_adapter.py # FastAPI adapter tests
│ ├── test_fastapi_sse.py # FastAPI SSE endpoint tests
│ ├── test_fastapi_websocket.py # FastAPI WebSocket tests
│ ├── test_litestar_adapter.py # Litestar adapter tests
│ ├── test_litestar_sse.py # Litestar SSE endpoint tests
│ ├── test_django_views.py # Django views tests
│ ├── test_django_model.py # Django model binding tests
│ ├── test_django_renderer.py # Django renderer tests
│ ├── test_django_websocket.py # Django Channels tests
│ ├── test_templatetags.py # Template tags tests
│ ├── test_permissions.py # Permission class tests (Beta)
│ ├── test_composition.py # Composition tests (Beta)
│ ├── test_testing_utils.py # Testing utility tests (Beta)
│ ├── test_caching.py # Cache mixin tests (Beta)
│ ├── test_ratelimit.py # Rate limit tests (Beta)
│ ├── test_optimistic.py # Optimistic UI tests (Beta)
│ └── test_optional_extras.py # Optional extras isolation tests
│
├── docs/ # Documentation
│ ├── make.py # pdoc build script
│ ├── docs_settings.py # Minimal Django settings for pdoc
│ ├── pdoc_templates/ # Custom pdoc templates (terminal brutalism)
│ ├── update_gh_pages.py # CI helper: versions.json + root index
│ └── examples/ecommerce.md # Real-time e-commerce walkthrough
│
├── .github/workflows/
│ ├── ci.yml # Tests, lint, type check (Python 3.11–3.14)
│ └── docs.yml # pdoc build + versioned GitHub Pages deploy
│
├── justfile # Task runner
├── .pre-commit-config.yaml # ruff + ty hooks
└── pyproject.toml
# Run full test suite
just test
# Verbose output
just test-verbose
# Core tests only
just test-core
# Adapter tests only
just test-adapters
# Or pytest directly
pytest tests/ -q --tb=shortCI runs against Python 3.11, 3.12, 3.13, and 3.14 on every push and pull request.
just install # Install all deps (just: https://github.com/casey/just)
# Or manually
uv pip install -e ".[dev]"
just pre-commit-install # Install ruff + ty pre-commit hooksjust format # Format code with ruff
just lint # Lint with ruff
just lint-fix # Lint and auto-fix
just check # lint + format-check + tests
just docs-build # Build API docs -> docs/site/
just docs-serve # Start pdoc dev server (localhost:8000)
just docs-check # Verify pdoc is installed and show config
just docs-clean # Remove docs/site/
just clean # Remove build artifacts
just build # Build the packagejust claude # Interactive Claude Code
just claude-unsafe # Skip permission prompts (trusted env only)
just claude-prompt # Append CLAUDE.md as system prompt
just claude-unsafe-prompt # System prompt + skip permissions
just claude-orchestrate # Full orchestration workflow
# Override prompt file
just claude-prompt PROMPT_FILE=prompts/WORKFLOW.md| Prompt file | Purpose |
|---|---|
CLAUDE.md |
Project architecture, conventions, guidelines (default) |
prompts/WORKFLOW.md |
Multi-agent orchestration, model selection, RTK token efficiency |
- ruff — Linting and formatting (line length: 100)
- ty — Type checking (Astral's Rust-based)
- pre-commit — Git hooks: trailing whitespace, YAML, merge conflicts, ruff, ty
- Open an issue first to discuss major changes
- Follow existing code style (ruff)
- Add tests for new features
- Update docstrings (used for API docs)
- Keep PRs focused and small
- Core component framework
- FastAPI adapter
- Django adapter
- Form validation
- Model binding
- WebSocket support
- Class-based views
- CI pipeline (GitHub Actions)
- Pre-commit hooks (ruff + ty)
- Comprehensive test suite
- Permission classes and FBV decorators
- Rate limiting (
RateLimitMixin) - Component caching (
CacheMixin) - Optimistic UI (
OptimisticMixin) - Component composition (slots, composite)
- Testing utilities (
ComponentTestCase) - Versioned API documentation (GitHub Pages + pdoc)
- Optional extras — FastAPI/Uvicorn/JinjaX no longer mandatory (
[fastapi],[django],[all])
- Litestar adapter — HTTP, WebSocket, SSE (
[litestar]extra) - Async event handlers —
async_dispatch()/async_handle_event() - SSE streaming —
StreamingComponentwith async generator handlers - State size guard — configurable warning (64 KB) and hard limit (512 KB)
- JS double-serialisation fix in
component-client.js
- Stable, frozen public API
- Performance benchmarks and optimisation
- Devtools / inspector
- Component marketplace / registry
- Full user guide and tutorials
Current benchmarks (local development):
- Component dispatch: < 1ms
- State serialisation: < 1ms
- Full HTTP cycle: ~10–20ms
- WebSocket latency: < 10ms
- Python 3.11+
- Pydantic 2.0+ (only mandatory runtime dependency)
Optional extras:
[fastapi]— FastAPI 0.109+, Uvicorn, JinjaX 0.41+[django]— Django 4.2+, Django Channels 4.0+, channels-redis 4.1+, django-cotton 0.9+[litestar]— Litestar 2.0+, Jinja2 3.1+[websockets]— websockets 12.0+[all]— all of the above
- State must be JSON-serialisable
- WebSocket scaling requires a Redis channel layer
- CSRF handling for WebSockets is manual
- SSE streaming requires ASGI deployment (Django) or any async framework (FastAPI/Litestar)
MIT — see LICENSE for details.
Inspired by:
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Docs: fsecada01.github.io/component-framework