Tucano v0.37.2

For AI agents

An AI that doesn't know the library writes a date picker from scratch, invents a red class for errors and sorts the table on the client. Two files fix that without you explaining it again in every conversation: the full reference in plain text and three lines in your project's AGENTS.md.

llms.txt

The whole API in one text file, made to be read by a model and not by people. Point the AI to it:

https://juniorcarlini.github.io/tucano/llms.txt

First comes a section per component, with the declarative path through data-*, which is the normal one in a Django project. Then the full reference: selector, attributes, every option with the comment that explains it, methods, events, CSS classes and tokens. That part is generated from the code on every build — if an option isn't there, it doesn't exist. The rules about what not to do come at the end. The prose in the file is written in Portuguese, while the API names — attributes, options, methods, events — are in English, so a model reads it without trouble.

Every page on this site advertises the file in its <head>, for tools that look for it:

<link rel="alternate" type="text/plain" href="https://juniorcarlini.github.io/tucano/llms.txt">

Why plain text, and not this documentation

A docs page carries menus, demos and scripts along with the information, and the AI spends context reading what it doesn't need. llms.txt is only the API, in the order you use it, and it fits whole in one conversation.

AGENTS.md in your project

Paste this into the AGENTS.md at the root of the project that uses Tucano — or into CLAUDE.md, .cursorrules, wherever your tool looks. It's what makes the AI pick the library instead of writing a component from scratch.

## Interface
This project uses Tucano. Do not write from scratch a date picker, searchable select, color picker, upload, mask, toast, tooltip, modal, drawer, accordion, tabs, dropdown menu, table, pagination or text editor.
Full reference: https://juniorcarlini.github.io/tucano/llms.txt

The list names the components that have JavaScript, which are the ones an AI rewrites most. The pieces that are only classes — button, alert, badge, loading, timeline, checkbox, radio and switch, side menu, label and form field — are in the same llms.txt, and the rule "don't design a second button" covers the rest.

Three lines are enough because the work is in the link. If you want the AI to get it right in the first answer, without opening the reference, add the examples your project uses most:

## Interface
This project uses Tucano. Do not write from scratch a date picker, searchable select, color picker, upload, mask, toast, tooltip, modal, drawer, accordion, tabs, dropdown menu, table, pagination or text editor.
Full reference: https://juniorcarlini.github.io/tucano/llms.txt

<input data-tuc-datepicker data-mode="range">
<select data-tuc-select multiple>
<input data-tuc-mask="cpf-cnpj">
<input type="file" data-tuc-upload>
<button data-tuc-tip="..." class="tuc-btn is-primary">

Tucano.toast.success('Saved');
await Tucano.confirm({ title: 'Delete?' });
Tucano.drawer({ title: 'Filters', side: 'right' });

The native element still owns the value: name, required and Django's getlist() keep working. Do not replace it with JS-only state.

And Tucano's own AGENTS.md

The repository's AGENTS.md is for people who will work on the code of the library itself: how to run it, the structure and the decisions that shouldn't be reverted without a reason, each with the bug that prompted it. To use Tucano in a project, you don't need it — you need llms.txt.

What the AI must not do

These are the rules that close llms.txt. Each one exists because it's the mistake a model makes when it guesses instead of reading.

Don'tDoWhy
Write a date picker, searchable select or color picker from scratchMark the field with data-tuc-datepicker, data-tuc-select, data-tuc-colorThat's what the library exists to avoid
Use the JavaScript API out of habitPrefer the data-* attributes; JS only for options that don't exist as attributes — disabledDates, custom presets, onChangeAn attribute works in the template, survives HTMX and needs no script
Remove the native <select> or the input's nameKeep the native element in the formThat's where the value lives: required and getlist() depend on it
Style the internal .tuc-*__* classesOverride the --tuc-* variables in :rootThe internal classes are built by the script and the look comes from the tokens
Write abrir(), tamanho, 'direita'open/close/toggle, size, tone, side, items, actions; values 'left', 'right', 'danger', 'success'The API is entirely in English, and an unknown option is silently ignored
Sort a paginated list on the clientLet the header be the <a> to ?sort= and ?dir=, with the order in order_by() before PaginatorSorting the page on screen produces a false order. data-sort-mode="client" only for small tables without pagination
Invent a red class for a field with an erroraria-invalid="true" on the field and the message in .tuc-errorIt's the attribute the screen reader announces, and Django 5 already writes it
Open a panel when the field receives focusLet it open with ↓, Space, click; Enter too in the selectIt's the rule of the native <select> and of the ARIA APG
Forget hidden on a dropdown panel written in the template<div class="tuc-dropdown" id="..." hidden>Without it the menu shows up in the middle of the page until the script runs. The modal's and drawer's <dialog> doesn't need it
Design a second button.tuc-btn with is-outline, is-ghost, is-icon, is-sm — including inside a tableA custom class only for positioning
Write the placeholder of a masked fieldLeave it emptyIt comes from the format: data-tuc-mask="cpf" already starts with 000.000.000-00, and data-tuc-mask="brl" with R$ 0,00
Load from the CDN with @latestPin the version: tucano@v0.37.2jsDelivr caches @latest for a long time and silently serves an old build
Import from tucano through npm and expect fields to set themselves upTucano.init(document), or import tucano/autoThrough npm auto-init isn't included, so the bundler keeps only what was imported; tucano/auto initializes and listens to HTMX like the CDN script
Read e.target.name in the date picker's tucano:changee.detail.iso, or the <input type="hidden"> next to itThe date picker moves the name to the hidden input with the ISO value; the visible field has no name. In the select, mask and upload the name stays on the target
Write CPF validation, currency or date formatting by handTucano.mask, Tucano.dates and Tucano.colorThey're the same modules the components use, exposed as API: validateCpfCnpj, applyCurrency, format, parseUserInput, isDark
Build a custom floating notice for the server's responseDjango's messages in <div data-tuc-toast>, or the HX-Trigger header with tucano:toastThe toast already handles stacking, pausing on focus and the regions the screen reader announces; the HTMX event is listened to automatically
Publish what came from the editor with |safe directlySanitize on the server firstThe editor's filter protects the editor, not the published page
Expect HTML inserted through fetch or innerHTML to initialize itselfCall Tucano.init(node) on the new fragmentThe automatic setup covers load and every htmx:afterSwap; the library doesn't see any other insertion path
Remove data-tuc-readyKeep the attributeIt's what stops autoInit from setting up the same field twice

When in doubt, the generated reference wins

If a prose example and the "Referência completa" (full reference) section of llms.txt disagree, the reference wins: it's extracted from the code on every build. Ask the AI to copy each section's example instead of guessing, and to check every option against that list.