Skip to main content

brickwork

Beautiful by default. Frontend your Django site fast, confident it delivers an excellent experience across devices. Brickwork is the server-rendered Django interface foundation: reusable tokens, shells, components, Theme profiles and copyable pages you own. Package defaults aim at finished interfaces on the jobs in docs/VISUAL-BAR.md, evidenced by the independent rendered meet-bar pass docs/audits/2026-09-12-visual-bar-signoff-pass.md. An independent beat win scorecard further records lead or tie on 6 of 8 VISUAL-BAR surfaces on package-default CSS (docs/audits/2026-09-14-beat-win-scorecard-s5s7.md); S5 remains a Lose and S3 is not scored as Plus lead or tie. Those passes are not a house aesthetic, do not name competitors as brickwork's identity, and do not claim examples alone proved beauty. Brickwork ships 74 examples (42 archetype pages, 32 sections; a 75th file, base.html, is a copied document skeleton). 73 of the 75 files add no CSS. The date range picker uses existing --bw-* tokens in its own scoped CSS because the package has no maintained date picker component (see Example pages).

Mechanism (subordinate): pin the foundation; own the pages (ADR-056); Theme with --bw-* profiles L1 to L4 (docs/THEME.md).

Read and render the examples to assess composition. Accessibility checks establish specific implementation properties. Visual quality also depends on content, hierarchy, spacing, typography and responsive composition; consumers own those choices in their finished pages.

A brand-agnostic interface foundation for server-rendered Django, on the ecosystem stack: Tailwind 4 (CSS-first), Alpine 3, HTMX 2, Django 6.0. Brickwork covers public sites, product applications, data-heavy operations, documentation, editorial publishing and transactional journeys through shared foundations, components, layouts and copyable archetypes. Quote the family shipping matrix in docs/POSITIONING.md (section 1) and the gated counts in section 5; do not claim every INTERFACE-SYSTEM archetype is shipped. See the interface-system contract for the intended coverage and the current example catalogue for what ships today.

This is not a Django-admin skin. Consumers provide data, permissions and business behaviour; Brickwork owns the reusable interface design, on a professional, tested-accessible baseline: RTL via logical properties, a real themeable dark-mode system, and four composable theme axes (brand x theme x density x direction). Rebranding is token-first: every visual value is a --bw-* custom property, so a consumer rebrands by overriding tokens, never by touching component classes.

Accessibility is tested, not asserted by design. CI blocks every push on an axe-core WCAG 2.2 AA scan across 262 documents (156 hand-maintained fixtures plus 106 catalogue-document pages, being 53 catalogue documents, 52 archetypes and 1 skeleton, each x light and dark themes), plus a no-JS floor suite, keyboard suites, mobile-overflow checks at 320/360/375/414px, and pixel-level composited contrast measurement. That last check exists because the axe gate itself once ran green over a real 4.25:1 contrast defect (axe's contrast check does not rasterise the page, so text over a background image reports "incomplete" rather than a violation); the gate catching its own blind spot and adding a check for it is stronger evidence than a gate that has never missed.

Status: stable. This checkout is version 4.0.0 (pip install django-brickwork for the published package); CHANGELOG.md records the current release. The five semver-governed public-API contracts (token, template, navigation, interaction, JavaScript) are live. The surface covers the application shell and nav, the token system (elevation, state overlays, type roles, motion, borders, with fine colours derived live from a small load-bearing brand set via color-mix()), the interaction set (modal, toast, dropdown, combobox, tabs, disclosure, tooltip, slide-over), forms with the whole-form renderer and the HTMX 422 loop, the data table with sortable and selectable modes, the feedback and input-chrome primitives, the wizard/stepper, and a machine-readable token contract with a per-tenant brand-CSS emitter.

See it running: brickwork.icvoss.com is the live interactive demo and template gallery, and icvoss.com/packages/django-brickwork hosts the package documentation page.

Marketing kit (1.2.0+). brickwork also ships an opt-in brickwork.marketing sub-app (a marketing shell and nine marketing components: hero, feature grid, pricing tier, pricing table, CTA, testimonial, logo cloud, stat band, FAQ) on the same --bw-* token and accessibility contract, so a consumer can build its public marketing pages on brickwork alongside its console. Worked landing/pricing/about pages are shipped as copy-paste examples, not importable templates: see Example pages below.

Documentation

  • docs/DESIGN.md: the canonical token reference; every --bw-* name, default value, and derivation rule.
  • docs/INTERFACE-SYSTEM.md: the intended coverage, ownership boundary and required archetypes for the complete interface system.
  • docs/VISUAL-BAR.md: the meet-or-beat visual bar against leading Tailwind UI kits (internal; clean-room look/idea only).
  • docs/ROADMAP.md: the active plan from the current package to complete interface-system coverage.
  • docs/THEME.md: Brickwork Theme (L1 to L4 profiles on --bw-*; L3/L4 may claim kit chrome follows authored axes after Phase E token-compliance; beauty of defaults stays VISUAL-BAR / beat)
  • docs/examples/vite-tailwind/: Vite + Tailwind consumer recipe and projection sync (INTEGRATION.md §1.3)
  • docs/BRANDING.md: how a consuming app brands brickwork (the load-bearing token minimum, dark mode, the four axes, the fg-on-accent contrast trap, and dynamic per-tenant / per-user theming recipes).
  • docs/brand-pack.md: the consumer brand-pack contract (measured DESIGN.md plus override fragment plus preview; numeric claims must cite --bw-* or defer to base-theme).
  • docs/QUICKSTART.md: start here. Orients you, then routes you to the right guide below.
  • docs/INTEGRATION.md: the greenfield integration cookbook, including the Vite + Tailwind recipe (§1.3) and projection sync; the seams a consuming app wires end to end (settings and static, nav config, context processor, a worked HTMX 422 form, the chrome/body boundary).
  • docs/ADOPTION.md: the strangle guide for migrating an existing app onto brickwork cluster by cluster (multi-host, asset coexistence, the htmx floor).
  • src/brickwork/examples/README.md: the copy-paste example pages, what each one is, and how to use one (see Example pages below).
  • brickwork.specimens (import from the installed package): first-family demonstration contexts for listing UI (data_table, filter_bar, empty_state); see the umbrella CONTRACTS entry django-brickwork.specimens.v1.
  • frontend/README.md: the in-repo build that compiles the shipped static assets.

Install

From public PyPI:

uv add django-brickwork             # or: pip install django-brickwork
INSTALLED_APPS = [
    "brickwork",
    # ...
]

The compiled CSS and JS ship inside the package and are referenced with plain {% static %}; no build-tool dependency (django-vite / django-tailwind) is imposed on consumers. Consumers provide their own Alpine 3 + @alpinejs/focus (and optionally htmx 2) via their own frontend build; brickwork registers behaviour onto the host Alpine instance and never calls Alpine.start().

Starting a project from nothing? Skip ahead to manage.py startsite in the Quickstart section below: it emits a running starter project rather than walking you through wiring one by hand.

Supported versions

Dependency Supported
Python 3.12+
Django 6.0 (the CI-tested matrix; later majors are not yet asserted, and the dependency pin is deliberately floor-only)
htmx >= 2.0 for the interaction contracts (see below); not required otherwise
Alpine.js 3.x plus @alpinejs/focus, provided by the host app
Browsers evergreen; the interaction suite is CI-tested on Chromium (Playwright)

htmx floor: htmx >= 2.0

brickwork's interaction contracts (the HTMX 422 form-swap loop, toast delivery via hx-swap-oob, modal dismissal via the HX-Trigger: bw:modal:close response header, combobox server filtering) are built and CI-gated on htmx >= 2.0 only. htmx 1.9 is out of contract (BR-BW-HTMX-010): htmx 2 changed default response handling in ways the 422 loop relies on, and the interaction suites only ever exercise htmx 2. A brownfield app on htmx 1.9 should upgrade htmx to 2.x as a prerequisite before adopting brickwork's interaction primitives; see docs/ADOPTION.md.

Quickstart: the fastest path is a command, not this section

python manage.py startsite myproject

emits a minimal, running project: settings wired for brickwork (and the optional marketing kit), a contrast-verified brand file, a validated nav config, and three real pages, each with the view that feeds it. cd myproject && python manage.py runserver opens the populated starting pages. Adapt their content and brand, then review the composition in its real states and viewports. The emitted project is yours outright from the moment it is written, with no update path back into it (ADR-095); see docs/QUICKSTART.md.

The rest of this section wires the same seams by hand, for a project that already has its own settings and routing brickwork needs to fit into.

Five minutes from install to a themed, accessible console page. Wire the app and the shell context processor:

# settings.py
INSTALLED_APPS = [
    "brickwork",
    # ...
]
TEMPLATES = [{
    "BACKEND": "django.template.backends.django.DjangoTemplates",
    "APP_DIRS": True,
    "OPTIONS": {"context_processors": [
        # ... Django's defaults ...
        "brickwork.context_processors.theme",   # wires theme/density/dir onto <html>
        "yourapp.context_processors.nav",
    ]},
}]

Declare the nav once, validated at import:

# yourapp/nav.py
from brickwork.models import NavItem
from brickwork.services.navigation import validate_nav_config

NAV = [
    NavItem(label="Dashboard", url_name="dashboard"),
]
validate_nav_config(NAV)
# yourapp/context_processors.py
from brickwork.services.navigation import resolve_active_item, visible_items
from yourapp.nav import NAV

def nav(request):
    return {
        "nav_items": visible_items(NAV, request),
        "nav_active": resolve_active_item(NAV, request),
    }

Extend the shell and fill its blocks:

{# yourapp/templates/yourapp/dashboard.html #}
{% extends "brickwork/shell/app.html" %}
{% load brickwork_nav %}

{% block sidebar %}{% bw_nav nav_items nav_active %}{% endblock %}

{% block page_header %}
  {% include "brickwork/components/_page_header.html" with title="Dashboard" %}
{% endblock %}

{% block content %}
  {% include "brickwork/components/_empty_state.html" with heading="Nothing here yet" body="Create your first project to get going." %}
{% endblock %}
# yourapp/views.py
from django.shortcuts import render

def dashboard(request):
    return render(request, "yourapp/dashboard.html", {"bw_page_title": "Dashboard"})

Run collectstatic and open the page: shell, sidebar nav with active-route highlighting, skip link, dark mode and density axes, all on the default theme. Branding it is a handful of --bw-* token overrides (docs/BRANDING.md); the full seam-by-seam walkthrough is docs/INTEGRATION.md.

Example pages

A whole page is the most project-specific thing you own, so brickwork does not ship one as a template you extend. Instead it ships 75 HTML files under src/brickwork/examples/: 42 archetype pages, 32 sections, and base.html (a copied document skeleton). That matches the lead inventory above; it is not a closed sixteen-page list.

Useful starting pages (not exhaustive): app/list, detail, dashboard, form, wizard; auth/signin; marketing/landing, pricing; docs/article; ops/dense-list; ops/data-empty-error. The full catalogue, section variants, and per-file view contracts live in src/brickwork/examples/README.md.

Looking for a date picker: Brickwork does not ship a maintained bw_date_picker Alpine calendar engine (BR-BW-INPUT-004), but it does ship field and panel chrome (_date_picker_chrome.html) and a complete copyable date-range picker. app/date-range-picker.html provides a calendar popover with weekday and month grids, locale-aware via Django's own django.utils.dates, including single-date mode, over a native <input type="date"> no-JavaScript floor that stays the submitted control. Copy it and adapt it. Brickwork owns the date-entry chrome and the interface pattern; the copied page's engine remains yours outright.

They cannot be extended, by construction: the directory is package data, not an app templates/ folder, so Django's APP_DIRS loader cannot see it and {% extends "brickwork/examples/..." %} raises TemplateDoesNotExist. That is deliberate (ADR-056): a page you import is a page a dependency can reshape on your next pin bump; a page you copy is yours outright.

To use one: open it (in the repo, or via brickwork.examples.read_example()), copy it into your own templates/ tree, and edit it. Each example is annotated with what your view must supply and stays real, specific content throughout, never Lorem ipsum.

Extending a shell directly (brickwork/shell/app.html, brickwork_marketing/shell/marketing.html, and friends) remains fully supported and is the option that keeps receiving improvements automatically; copying an example is the alternative for a project that wants to own its page outright from day one.

Contracts

brickwork's public API is five versioned contracts: token, template, navigation, interaction (HTMX), and JavaScript (Alpine). Template block names, HTMX target IDs, Alpine component names, event names and token names are semver-governed. Machine-readable coverage ships as three generated siblings under static/brickwork/dist/: token-manifest.json, template-manifest.json, and interaction-manifest.json (Alpine names, events, HTMX targets; icvoss/django-brickwork#229). docs/DESIGN.md enumerates the token contract, docs/INTEGRATION.md walks the template, navigation and interaction seams, and CHANGELOG.md records every contract change release by release.

Usage

Tags vs includes

Some components are consumed as template tags, others via {% include %}. This is deliberate: a component that carries logic (variant validation, a11y enforcement, icon resolution) ships as a tag so that logic is not duplicated at every call site; a purely structural component is an include the consumer fills with context.

  • Tags (load the library first): {% bw_icon %}, {% bw_button %}, {% bw_badge %}, {% bw_alert %}, {% bw_nav %}, {% bw_nav_header %}, {% bw_nav_rail %}, {% bw_field_widget %}, {% bw_dropdown %}, {% bw_tabs %}, {% bw_toast %}, {% bw_combobox %}. The three nav tags are sibling renderers over the same NavItem tree: the sidebar/tree render, the horizontal marketing-header row, and the compact two-tier rail (see INTEGRATION.md section 2).

    {% load brickwork_components brickwork_icons brickwork_nav %}
    {% bw_button label="Save" variant="primary" %}
    {% bw_badge label="New" variant="info" %}
    

    The _button.html / _badge.html / _alert.html template files exist but are the tags' own render targets, not a consumer-facing {% include %} API. Call the tag, not the partial.

    {% bw_dropdown %} items may carry an optional attrs mapping for consumer-owned hooks on the rendered item, for example {"data-item-id": widget.pk}. Only data-* names are accepted; Brickwork's own data-bw-* hooks remain reserved (ADR-083: this is the same rule as the data seam below, not a wider one, since the seam protects what a component deliberately withholds, not just what it emits).

  • Includes (structure you fill with context): _page_header.html, _data_table.html, _pagination.html, _empty_state.html, _filter_bar.html, _spinner.html, and the form partials forms/_field.html / forms/_form_errors.html.

    {% include "brickwork/components/_data_table.html" with table_id="gadgets" columns=columns rows=rows %}
    

    Record rows may include a data mapping for consumer-owned hooks on the rendered row, for example {"data-item-id": gadget.pk}. Only data-* names are accepted; Brickwork's own data-bw-* hooks remain reserved. _stat.html accepts the same optional data mapping on its tile root.

Icons: decorative or labelled, always

{% bw_icon %} requires exactly one of decorative=True or label="...", and raises TemplateSyntaxError if given neither or both. This is intentional (ICO-007, WCAG 4.1.2): an icon is either purely presentational (aria-hidden) or carries meaning (an accessible name), never ambiguous.

{% bw_icon "search" decorative=True %}          {# beside a visible label #}
{% bw_icon "trash" label="Delete item" %}       {# standalone, meaningful #}

You rarely call bw_icon directly for the icon inside a bw_button or bw_nav item: those tags take an icon="..." argument and handle the a11y pairing for you. Reach for bw_icon directly only for a standalone icon in your own markup, where this rule applies.

Development

Python package:

pip install -e ".[dev]"
pytest

Frontend build (compiles tokens + component assets into the package's static dir; see frontend/README.md):

npm install
npm run build

Licence

MIT. See LICENSE.

Release files for django-brickwork 4.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-brickwork 4.0.0
File Size Uploaded
django_brickwork-4.0.0.tar.gz 1.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-brickwork 4.0.0
File Interpreter ABI Platform
django_brickwork-4.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.8 MB

Release files / django_brickwork-4.0.0.tar.gz

Download URL django_brickwork-4.0.0.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
e622e83fee5ef315be8b5e36c268a829810b5320d13f7f1947e75be2bb3ce8e3
BLAKE2b-256 checksum
How to use checksums
94985f18ececc54ca0ef967d502508722fad0d83cf14b71c9088986b4683f8be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / django_brickwork-4.0.0-py3-none-any.whl

Download URL django_brickwork-4.0.0-py3-none-any.whl
Size 827.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
54db700fec3267843e8751aaf104ccc2f966f4db426ee16a88e7b62d77b62c1a
BLAKE2b-256 checksum
How to use checksums
7e3d67d6a96d963b67e48c10a5efddfde35f0ba0143d74d047f74809a1c777c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 release files

3.38.0

2 release files

3.37.0

2 release files

3.36.0

2 release files

3.35.0

2 release files

3.34.0

2 release files

3.33.0

2 release files

3.32.0

2 release files

3.31.0

2 release files

3.30.0

2 release files

3.29.0

2 release files

3.28.0

2 release files

3.27.0

2 release files

3.26.1

2 release files

3.26.0

2 release files

3.25.0

2 release files

3.24.0

2 release files

3.23.0

2 release files

3.22.0

2 release files

3.21.0

2 release files

3.20.0

2 release files

3.19.1

2 release files

3.19.0

2 release files

3.18.0

2 release files

3.15.0

2 release files

3.14.0

2 release files

3.13.0

2 release files

3.12.0

2 release files

3.11.0

2 release files

3.10.0

2 release files

3.9.0

2 release files

3.8.0

2 release files

3.7.0

2 release files

3.6.0

2 release files

3.5.1

2 release files

3.5.0

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.1

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page