255 Jinja2 macros for building enterprise web applications with Tailwind CSS v4 + Alpine.js. Every component is reactive, dark-mode compliant, and config-driven.
cd your-project
git submodule add https://github.com/mrwuss/ui-kit templates/ui-kit{# In any Jinja2 template #}
{% from "ui-kit/components/ui.html" import button, badge, stat_card, data_table %}pip install git+https://github.com/mrwuss/ui-kit.git# main.py
from ui_kit import configure_templates
templates = configure_templates(app_dirs=["templates"]){# In any Jinja2 template #}
{% from "components/ui.html" import button, badge, stat_card, data_table %}Copy src/ui_kit/templates/ into your project's template directory.
| Directory | Contents |
|---|---|
src/ui_kit/templates/components/ui.html |
252 Jinja2 macros — the core component library |
src/ui_kit/templates/components/code.html |
2 macros — code_block, view_code_button (v2.0 source-display modal) |
src/ui_kit/templates/base/base.html |
Base page template — sidebar, dark mode, componentState persistence |
src/ui_kit/templates/examples/ |
6 interactive Jinja2 page templates (see Examples below) |
preview/index.html |
Interactive component preview — open in browser |
docs/REFERENCE.md |
Full parameter schema for every macro |
docs/USAGE.md |
Detailed usage examples |
docs/design-tokens.md |
Color system, spacing, typography reference |
src/ui_kit/static/js/ |
JS utility modules — CoreAPI, CoreSSE, CoreFormat |
Forms (19): input_field, select_field, textarea_field, number_field, date_field, time_input, date_range, currency_input, checkbox_field, toggle_switch, radio_group, chip_input, file_upload, editable_field, async_select, form_group, field_error, search_with_results, rating_input
Accessibility (3): skip_to_content, font_scale_toggle, reduced_motion_toggle
Data Display (15): data_table, table_* (8 macros), comparison_table, comparison_row, description_list, sortable_table_head, spark_cell
Charts (8): sparkline, spark_cell, stat_card_spark (no dependency) | plotly_chart, bar_chart, line_chart, pie_chart, gauge_chart, live_chart, chart_card (require Plotly.js)
Navigation (8): nav_bar (collapsible sidebar), nav_bar_top, nav_bar_top_panel, nav_panel, nav_item, nav_submenu, sidebar_user, tree_view
Feedback (8): alert, toast_container, blocking_modal, loading_overlay, spinner, error_ref, inline_confirm, field_error
Cards & Layout (16): card, bordered_card, stat_card, stat_card_spark, service_health_card, page_heading, page_footer, divider, accordion, tab_bar, breadcrumb, tooltip, truncate_text, kbd, skeleton, empty_state
Modals & Panels (6): modal, confirm_modal, slide_over, command_palette, popover, document_viewer
Badges & Status (11): badge, dot_badge, notification_counter, health_indicator, status_dot, match_method_badge, validation_score, env_badge, sse_status, copy_button, avatar
Cards (3): contact_card, item_card, document_card
Dashboard Utilities (5): filter_toolbar, active_filters, metric_delta, bulk_action_bar, queue_stats
Data Visualization (2): tracker, data_bar
Communication (2): notification_panel, chat_bubble
Data Streaming (3): log_console (standalone/dock/raw), live_chart, sse_status
Authentication (3): auth_modal (login/re-auth), auth_redirect_modal (access denied), api_key_modal (API key entry)
Alpine primitives (7) — macros that hide recurring Alpine.js patterns, per Epic #350:
- v2.14:
alpine_dropdown_portal(teleport + escape + click-outside),alpine_debounced_input(debounce + on_input),alpine_x_init_boundary(_lastValue-guarded reactive watches),reactive_list(keyedx-for+ drag-reorder) - v2.19:
alpine_json_island(the MANDATORY server→client JSON handoff pattern),alpine_shortcut_binding(window-scoped keyboard shortcuts with optionalwhen=guard),alpine_polling_timer(setInterval+ visibility pause + reactiveactive_var)
JS Utilities (3): CoreAPI (fetch + CSRF-aware wrapper), CoreSSE (SSE manager), CoreFormat (formatting)
- Jinja2 (any version with macro support)
- Tailwind CSS v4 via CDN — pin the patch version:
cdn.jsdelivr.net/npm/@tailwindcss/browser@4.1.14. Unpinned@4or rolling@latestURLs auto-upgrade on every minor; v4 has shipped breaking changes between patches, so unpinned setups silently break. Kit is regression-tested against4.1.14— bump consumers in lockstep with each kit release. - Alpine.js 3.x via CDN
- Plotly.js (optional — only for chart macros, graceful fallback if missing)
- JS Utilities (optional — CoreAPI, CoreSSE, CoreFormat for API/SSE/formatting patterns)
Macros bridge server-side Jinja2 rendering with client-side Alpine.js reactivity. Every macro supports both static and dynamic usage:
{# Static (server-rendered) #}
{{ badge("Active", variant="green") }}
{# Dynamic (Alpine-bound) #}
{{ badge("", text_var="item.status", variant_var="item.statusColor") }}
{# Form with event handlers #}
{{ input_field("Name", model="form.name", on_change="save()", x_bind_disabled="!editing") }}For data_table / accordion_table inside a parent x-data, pass standalone=false:
<div x-data="myApp()">
{{ data_table("t", columns=cols, data_var="myData", standalone=false) }}
</div>See CLAUDE.md for the full integration guide, parameter ordering convention, and nesting patterns.
UI preferences (dark mode, sidebar collapsed, active tab) persist across page reloads via componentState — a utility in base.html that writes a ui_state JSON cookie with localStorage fallback. Server can read the cookie for SSR.
componentState.get('darkMode', false)
componentState.set('sidebarCollapsed', true)Live Preview — all 255 components with interactive demos and dark mode toggle.
Example Templates — full-page interactive demos:
| Example | Live | Demonstrates |
|---|---|---|
| Scorecard | view | stat_card(value_var), expandable KPI targets, customer drill-down |
| Dashboard | view | data_table(standalone=false), health_indicator(status_var), SSE |
| Settings | view | form_group, sizing (sm/md/lg), on_change auto-save, x_bind_disabled |
| Kitchen Sink | view | ~50 macros nested: tab → card → data_table → accordion_table |
| Email Report | view | HTML email with inline CSS, KPI stats, exception table |
Or serve locally: python -m ui_kit.serve (requires pip install uvicorn starlette)
- USAGE.md — Usage examples for every macro
- REFERENCE.md — Full parameter schemas
- design-tokens.md — Colors, spacing, typography
- CLAUDE.md — AI agent context (component inventory, design system rules, decision guide)
If your app uses CodeRabbit, drop a .coderabbit.yaml in your repo
root that encodes the conventions the kit enforces (dark mode,
accessibility, reuse of existing primitives, Alpine.js over vanilla
JS, etc.). This keeps reviewers from re-flagging the same class of
issue on every PR and reduces noise in the review body.
A working template lives in the Sales-PP-KPI repo:
.coderabbit.yaml.
The pattern strips the review body down (no high-level summary, collapsed walkthrough, no poem / related PRs) so nearly every actionable finding lands as an inline diff comment.
Even with the config, CodeRabbit always splits its output across two surfaces per review round — this is architectural, not a toggle:
| Surface | What lives there | How to read it |
|---|---|---|
| Inline diff comments | "Potential issue" / major / minor findings | gh api repos/:owner/:repo/pulls/{n}/comments |
| Review body | Nitpicks, actionable-count summary, autofix checkboxes | gh pr view {n} --json reviews --jq '[.reviews[] | select(.author.login | startswith("coderabbitai"))][-1].body' |
Plus two informational surfaces worth checking on any review round:
| Surface | What lives there | How to read it |
|---|---|---|
| Issue-style PR comments | Rate-limit warnings, pre-merge walkthroughs | gh api repos/:owner/:repo/issues/{n}/comments |
| Status check rollup | Pre-merge check pass/fail | gh pr view {n} --json statusCheckRollup |
A PR can be "inline-clean" and still have unresolved nitpicks.
Automation and humans sweeping a PR for findings must hit all four
every round. The kit's .coderabbit.yaml documents this rule in a
comment block so it propagates to every consumer that copies the
template.
The kit's own config is in .coderabbit.yaml at
the root of this repo — use it as a second reference.
MIT