Compose UI from single template files. No build step, fully interoperable with the Django templates you already write.
<div class="card">
<h3>{{ title }}</h3>
<p>{{ slot }}</p>
</div>
<c-card title="Pricing">
Simple, per-seat billing.
</c-card>
<c-card title="Support">
Help when you need it.
</c-card>
{% cotton card title="Pricing" %}
Simple, per-seat billing.
{% endcotton %}
{% cotton card title="Support" %}
Help when you need it.
{% endcotton %}
Simple, per-seat billing.
Help when you need it.
<c-vars label type="text" :required="False" />
<div class="field">
<label>{{ label }}{% if required %} *{% endif %}</label>
<input type="{{ type }}" {{ attrs }} />
</div>
{% cotton:vars label type="text" :required="False" %}
<div class="field">
<label>{{ label }}{% if required %} *{% endif %}</label>
<input type="{{ type }}" {{ attrs }} />
</div>
<c-field label="Email" type="email" required />
<c-field label="Age" type="number"
placeholder="18+" />
{% cotton field label="Email" type="email" required /%}
{% cotton field
label="Age"
type="number"
placeholder="18+"
/%}
<c-vars variant="primary" />
<button class="btn btn-{{ variant }}">
{{ slot }}
</button>
{% cotton:vars variant="primary" %}
<button class="btn btn-{{ variant }}">
{{ slot }}
</button>
<c-button>Save</c-button>
<c-button variant="default">Cancel</c-button>
<c-button variant="danger">Delete</c-button>
{% cotton button %}Save{% endcotton %}
{% cotton button variant="default" %}Cancel{% endcotton %}
{% cotton button variant="danger" %}Delete{% endcotton %}
New to components? Start with Thinking in Components.
You still can, and Cotton stays fully interoperable with them. But the native tools for reuse get verbose fast. Here is the same idea, the native way and with Cotton.
{# ❌ include: HTML is escaped #}
{% include "card.html" with content="<b>Bold</b>..." %}
{# ❌ extends: only one per template #}
{% extends "card.html" %}
{% block content %}Card 1{% endblock %}
{% extends "card.html" %}
{% block content %}Card 2{% endblock %}
{# ❌ templatetags: needs a .py file #}
{% load card %}
{% card %}
{# ✅ pass rich HTML content #}
<c-card title="First Card">
<b>Bold</b>, <a href="#">links</a>, anything
</c-card>
{# ✅ reuse unlimited times #}
<c-card title="Card 1">...</c-card>
<c-card title="Card 1">...</c-card>
{# ✅ just an alert.html file, no Python #}
<c-alert type="warning">No Python needed</c-alert>
{# ✅ pass rich HTML content #}
{% cotton card title="First Card" %}
<b>Bold</b>, <a href="#">links</a>, anything
{% endcotton %}
{# ✅ reuse unlimited times #}
{% cotton card title="Card 1" %}...{% endcotton %}
{% cotton card title="Card 1" %}...{% endcotton %}
{# ✅ just an alert.html file, no Python #}
{% cotton alert type="warning" %}No Python needed{% endcotton %}