{% extends 'django_cotton_gallery/base.html' %} {% load i18n %} {% block title %}{% trans "Insights" %}{% endblock %} {% block content %}

{% trans "Catalog insights" %}

{% blocktranslate %}Health and usage signals across your component catalog. Lint, annotation coverage and deprecation come from the catalog itself; zombies and most-referenced metrics require scanning your project's templates and are opt-in.{% endblocktranslate %}

{% trans "Catalog" %}

{{ report.total_components }}

{% blocktranslate count counter=report.total_components %}component{% plural %}components{% endblocktranslate %}

{% if report.by_category %} {% endif %}

{% trans "Lint health" %} {% blocktranslate %}Higher is better. Starts at 100 (clean catalog, no annotation issues) and subtracts 5 per error and 1 per warning, floored at 0. Hints don't subtract — they're heuristic checks (e.g. context-processor variables) that may produce false positives. So 100 = perfect, 0 = lots of issues. Click "Open lint report" to see exactly which rules fired.{% endblocktranslate %}

{{ report.lint_health_score }}/100 {% if report.lint_health_label == 'clean' %}{% trans "clean ✓" %} {% elif report.lint_health_label == 'healthy' %}{% trans "healthy" %} {% elif report.lint_health_label == 'needs-attention' %}{% trans "needs attention" %} {% else %}{% trans "many issues" %}{% endif %}

{{ report.lint_total_errors }} {% blocktranslate count counter=report.lint_total_errors %}error{% plural %}errors{% endblocktranslate %} · {{ report.lint_total_warnings }} {% blocktranslate count counter=report.lint_total_warnings %}warning{% plural %}warnings{% endblocktranslate %} {% if report.lint_total_hints %} · {{ report.lint_total_hints }} {% blocktranslate count counter=report.lint_total_hints %}hint{% plural %}hints{% endblocktranslate %} {% endif %}

{% trans "Open lint report →" %}

{% trans "Annotation coverage" %} {% blocktranslate %}How many of your components carry which kind of annotation. Higher = the gallery has more metadata to render rich previews and the linter has more material to check. Documented: have at least one @description or @prop. With props: declare at least one @prop. With slots: declare at least one @slot. Accept attrs: render {{ attrs }} so callers can pass extra HTML attributes through.{% endblocktranslate %}

{% trans "% of components that carry each kind of annotation. Higher is better — more metadata to drive the gallery's controls and lint checks." %}

{% trans "Cotton configuration" %} {% blocktranslate %}A snapshot of the two Cotton settings the gallery cares about — where it scans for components and how Cotton maps your tags to files. Mismatches between your filenames and these settings break previews silently, so this card flags them up front.{% endblocktranslate %}

{% comment %} Live snapshot of the Cotton settings. One row per setting, label on the left, value on the right (mono pill). The absolute SCANNING path uses RTL-truncation so the meaningful tail stays visible even when the column is narrow. {% endcomment %}
COTTON_DIR {% blocktranslate %}Subfolder name (relative to TEMPLATES['DIRS']) where Cotton — and the gallery — look for component files. Default "cotton". Belongs to the Cotton folder convention; the gallery just reads it.{% endblocktranslate %}
"{{ cotton_health.cotton_subfolder }}"
{% trans "Scanning" %} {% trans "The absolute filesystem path the gallery is currently scanning. If this isn't where you expect your components to live, check your TEMPLATES['DIRS'] and COTTON_DIR settings." %}
{{ cotton_health.cotton_dir_abs }}
COTTON_SNAKE_CASED_NAMES {% blocktranslate %}Cotton's setting that decides how a tag like <c-foo-bar /> maps to a file. With True (Cotton's default) it strips hyphens and looks for foo_bar.html; with False it keeps the hyphen and looks for foo-bar.html. The gallery indexes both styles transparently — pick whichever you prefer and stay consistent across the catalog.{% endblocktranslate %}
{% if cotton_health.snake_cased %}True{% else %}False{% endif %}
{% comment %} Verdict block — same visual rhythm as the Lint health card: a big glyph (number for BAD, symbol for GOOD/WARN) + a verdict pill that carries an info ⓘ with the long-form explanation and the fix. The paragraph hint of the previous design moves entirely into the tooltip so the card stays compact. {% endcomment %} {% if cotton_health.has_mismatch %}

{{ cotton_health.hyphen_count }} {% blocktranslate count counter=cotton_health.hyphen_count %}error component{% plural %}error components{% endblocktranslate %} {% blocktranslate %}Cotton transforms - into _ when looking up files, but these components have a hyphen in their filename — Cotton can't find them. Two ways to fix it: rename the files (form-field.htmlform_field.html) or set COTTON_SNAKE_CASED_NAMES = False in your settings.py to keep the hyphens.{% endblocktranslate %}

{% trans "Affected components:" %}

{% elif cotton_health.snake_cased %}

{% trans "suboptimal" %} {% blocktranslate %}Your filenames have no hyphens and COTTON_SNAKE_CASED_NAMES = True — cotton's default. Cotton resolves your tags fine. If you'd rather have kebab-case filenames matching your tags 1:1 (e.g. form-field.html<c-form-field />), set the setting to False; both styles work.{% endblocktranslate %}

{% blocktranslate count counter=report.total_components %}All {{ counter }} component is correctly named for this configuration — Cotton's snake_case convention is being followed.{% plural %}All {{ counter }} components are correctly named for this configuration — Cotton's snake_case convention is being followed.{% endblocktranslate %}

{% else %}

{% trans "optimal" %} {% blocktranslate %}Your filenames map 1:1 to Cotton tags (e.g. atoms/form-field.html<c-atoms.form-field />). No surprises.{% endblocktranslate %}

{% blocktranslate count counter=report.total_components %}All {{ counter }} component maps 1:1 to its Cotton tag. No surprises.{% plural %}All {{ counter }} components map 1:1 to their Cotton tags. No surprises.{% endblocktranslate %}

{% endif %}

{% trans "Deprecated" %} {{ report.deprecated|length }}

{% if report.deprecated %} {% else %}

{% trans "No component declares deprecated props." %}

{% endif %}

{% trans "Coverage gaps" %} {{ report.coverage_gaps|length }}

{% trans "Components missing a top-level @description, or with at least one prop that has no description." %}

{% if report.coverage_gaps %} {% else %}

{% trans "Every component and every prop is documented." %}

{% endif %}

{% trans "External usage — where your components are referenced" %} {% blocktranslate %}When opted in, the gallery walks every .html file under your TEMPLATES['DIRS'] entries and each app's templates/ folder, looking for <c-X.Y /> tags that reference catalog components. The catalog itself (your cotton/) is excluded — the scan only looks at consumer code. Read-only, dev-only, only template paths surface in the UI.{% endblocktranslate %} {% if scan_enabled %}{% trans "scanning" %}{% else %}{% trans "disabled" %}{% endif %}

{% trans "Tracks who uses your components from OUTSIDE the catalog (your real pages, layouts, partials). Without this, the gallery only knows about references between catalog components themselves." %}

{% if scan_enabled %}

{% trans "Most referenced" %} {{ report.most_referenced|length }}

{% if report.most_referenced %}
    {% for path, count in report.most_referenced %}
  1. {{ path }} {{ count }}
  2. {% endfor %}
{% else %}

{% trans "Nothing references your components yet." %}

{% endif %}

{% trans "Zombies" %} {{ report.zombies|length }}

{% trans "Components with zero references — neither inside the catalog nor in your project's templates." %}

{% if report.zombies %}
    {% for path in report.zombies %}
  • {{ path }}
  • {% endfor %}
{% else %}

{% trans "Every component is used somewhere — clean catalog." %}

{% endif %}
{% else %}

{% trans "Zombies and most-referenced metrics require scanning your project's templates." %}

{% blocktranslate %}The gallery never reads consumer code without consent. Set DJANGO_COTTON_GALLERY_SCAN_EXTERNAL_USERS = True in your Django settings to enable. Read-only, dev-only — only template paths are exposed in the gallery UI.{% endblocktranslate %}

{% endif %}
{% endblock %}