Skip to main content

citry-bootstrap

Bootstrap 5 components for citry, with React-Bootstrap API parity.

Converted from django-components-bootstrap with djc-to-citry, which is itself AI-written. The components carry over that library's tests, 466 of them, but the conversion was mechanical.

Component documentation, with a rendered preview of every example.

Install

pip install citry-bootstrap
import citry_bootstrap
from citry import Citry

app = Citry(extensions=[citry_bootstrap.PlainInputs])
citry_bootstrap.install(app)

Use

<c-bs-button variant="primary">Click me</c-bs-button>
<c-bs-alert variant="success" c-dismissible="True">Well done!</c-bs-alert>

<c-bs-card c-body="True">
  <c-bs-card-title>Title</c-bs-card-title>
  <c-bs-card-text>Some text.</c-bs-card-text>
</c-bs-card>

Bootstrap 5 lives in citry_bootstrap.components.bootstrap5, leaving room for a later major version beside it.

Naming

Components are published as <c-bs-button>. To publish them under something else:

citry_bootstrap.install(app, prefix="ui-")   # <c-ui-button>
citry_bootstrap.install(app, prefix="")      # <c-button>

That replaces the names rather than adding to them - nothing answers to bs- afterwards. A component's template names its siblings, so the prefix is rewritten in both places at once.

Replacing a component

Subclass it and hand it to install():

from citry_bootstrap.components.bootstrap5.card import CardBody


class MyCardBody(CardBody):
    def template_data(self, kwargs, slots):
        data = super().template_data(kwargs, slots)
        data["div_attrs"] = {**data["div_attrs"], "data-testid": "body"}
        return data


citry_bootstrap.install(app, override={CardBody: MyCardBody})

Yours is published under the same name, so every sibling renders it too - including Card, which builds its own body. The name follows prefix, so the two can be combined. Handing in something this library does not publish is an error rather than a silent no-op.

Constant inputs

Citry marks a value it knows at parse time with a transparent proxy, so it can precompute the template expressions that read it. The proxy prints and compares like the value it wraps, but x is True and x is None are silently False and re, str.join and os.fspath reject it. These components were translated from django-components, which has no such marker, so they read their inputs as ordinary Python.

PlainInputs takes the proxy off before citry builds the typed Kwargs, and marks the pass-through values again before citry looks for its constants, so the engine optimizes exactly what it would have without it. Registration refuses an engine that does not have it, because the failure it prevents is silent: c-fluid="True" would render container-True.

Citry issue #107 tracks handing component code plain values from the engine. This goes away when it does.

Develop

uv sync
pytest
ruff check . && ruff format --check .

The component pages are generated from the test suite, so an example cannot drift from the component it documents:

uv sync --group docs
uv run python docs/generate_docs.py
cd docs && uv run mkdocs serve

Metadata

Release files for citry-bootstrap 0.1.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 citry-bootstrap 0.1.0
File Size Uploaded
citry_bootstrap-0.1.0.tar.gz 139.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for citry-bootstrap 0.1.0
File Interpreter ABI Platform
citry_bootstrap-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 189.4 kB

Release files / citry_bootstrap-0.1.0.tar.gz

Download URL citry_bootstrap-0.1.0.tar.gz
Size 139.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a4fb2af9804373b44545a9ec9372badf1b98f392cefb906d85ec2c3073dc1335
BLAKE2b-256 checksum
How to use checksums
3f2069333fe42f71650f53684763abaf06ae36bec9ef308aebd93d7641e630e1
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 11, 2026.

Transparency log

Release files / citry_bootstrap-0.1.0-py3-none-any.whl

Download URL citry_bootstrap-0.1.0-py3-none-any.whl
Size 50.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1d3a6b072418076d941899a0eb2ccd9e1d944b33b6b5d6208dd105f43b369503
BLAKE2b-256 checksum
How to use checksums
72092ce0661fad9cdcbe6667fb6d5afdbeb10c266d2056c6f856ff08d7d40732
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

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