CSS framework UI kit for
component-framework— Bulma, Bootstrap, Foundation, Fomantic UI, DaisyUI.
📖 Full documentation: https://fsecada01.github.io/component-framework-ui/
Fourteen ready-to-use components in two first-class template sets:
| Template set | Engine | Web frameworks |
|---|---|---|
jinja/ |
Jinja2 / JinjaX | FastAPI, Litestar |
cotton/ |
django-cotton | Django |
Component names are theme-agnostic — <Cf:Card> and <c-cf.card> render
whichever theme is active. Switching CSS frameworks means changing one config
line, not hundreds of templates.
pip install "cf-ui[django,bulma]" # Django + Bulma
pip install "cf-ui[fastapi,daisy]" # FastAPI + Tailwind/DaisyUI
pip install "cf-ui[litestar,bootstrap]" # Litestar + Bootstrap 5All template sets ship in every install. Theme selection is runtime config, not install-time.
{# Django #}
{% load cf_ui %}
<c-cf.card header="Welcome">Card body content.</c-cf.card>
<c-cf.form-field name="email" label="Email" type="email" /># FastAPI
from jinjax import Catalog
from cf_ui.fastapi import install_cf_ui
catalog = Catalog()
install_cf_ui(catalog, theme="bulma")
html = catalog.render("Cf:Card", header="Welcome", _content="Card body.")→ Quickstart for all three frameworks
| Theme | Status |
|---|---|
| Bulma | ✅ |
| Tailwind + DaisyUI | ✅ — guide |
| Bootstrap 5 | ✅ — CSS only, no bootstrap.bundle.js; decision record |
| Foundation 6 | ✅ — CSS only, no jQuery |
| Fomantic UI | ✅ — CSS only, no jQuery |
Switching is one line — CF_UI_THEME = "daisy" on Django, theme="daisy" on
FastAPI/Litestar — and needs no template edits in the consuming app. An
unimplemented theme name is rejected at startup rather than at first render.
| Page | What's in it |
|---|---|
| Installation | Extras, requirements, asset options |
| Quickstart | Django, FastAPI, and Litestar setups |
| Getting started | Themes, assets, composition axes, Alpine, escaping |
| Use cases | HTMX tables, modals, forms with errors |
| Components | All fourteen, with every prop |
| Escaping | Why cf-ui escapes its own output |
| Theming | Composition axes and custom value sets |
| Tailwind plugin | Build-time axis validation |
| Accessibility | Focus management, ARIA, keyboard behavior |
git clone https://github.com/fsecada01/component-framework-ui
cd component-framework-ui
uv pip install -e ".[dev]"
playwright install chromium
just test # unit tests
just test-integration # integration tests
just test-e2e # E2E Playwright tests (requires chromium)
just test-all # everything
just lint # ruff check
just format # ruff format
just docs # serve the docs site locally- Python 3.11+
component-framework >= 0.4- Pydantic 2.0+ (only mandatory runtime dependency)
Optional extras:
[django]— Django 4.2+, django-cotton 2.0+[fastapi]— FastAPI 0.109+, JinjaX 0.41+, uvicorn, python-multipart[litestar]— Litestar 2.0+, Jinja2 3.1+, JinjaX 0.41+
Jinja2 and JinjaX are layers, not alternatives, which is why the Litestar
extra names both. Litestar's JinjaTemplateEngine owns the Jinja2
environment, and cf-ui installs a JinjaX catalog onto it — so <Cf:Card>
renders from the same template on both paths. The FastAPI extra omits Jinja2
only because JinjaX pulls it in transitively there, where the catalog owns
the environment outright.
MIT