Skip to content

fix: stop hijacking COTTON_DIR — cotton/cf/ template layout#4

Merged
fsecada01 merged 2 commits intomasterfrom
fix/cotton-dir-consumer-conflict
Apr 28, 2026
Merged

fix: stop hijacking COTTON_DIR — cotton/cf/ template layout#4
fsecada01 merged 2 commits intomasterfrom
fix/cotton-dir-consumer-conflict

Conversation

@fsecada01
Copy link
Copy Markdown
Owner

Summary

cf-ui 0.1.0 is broken for any Django consumer that ships its own
templates/cotton/<their-app>/... tree. The previous fix
(5814476, "set COTTON_DIR (singular) in CfUiConfig") made <c-cf.*>
components resolvable by writing settings.COTTON_DIR = "cotton/<theme>"
in CfUiConfig.ready(). But django-cotton uses COTTON_DIR as a single
global prefix for every <c-foo.bar> lookup, so the moment a
consumer added cf_ui.django.CfUiConfig to INSTALLED_APPS, every one
of its own components started raising TemplateDoesNotExist: cotton/bulma/<their-path>.

This PR adopts Option A from the issue brief: move cf-ui's cotton
templates to a path that doesn't require a global prefix.

What changed

  • src/cf_ui/templates/cotton/bulma/cf/*.htmlsrc/cf_ui/templates/cotton/cf/*.html
    (14 components, all git mv — no content edits).
  • CfUiConfig.ready() is now a no-op. Django's APP_DIRS=True walk
    already exposes the package templates; the django-cotton default
    COTTON_DIR="cotton" resolves <c-cf.foo> to cotton/cf/foo.html
    correctly.
  • The cf_ui.django module just declares the AppConfig.

Why Option A over Option B

A custom app_directories.Loader subclass that scopes the theme prefix
to the cotton/cf/ subtree (Option B) would have preserved the existing
file layout, but at the cost of:

  • one more piece of stateful import-time machinery in CfUiConfig,
  • a loader that has to inspect every template lookup to decide whether
    to rewrite it,
  • harder debugging when something doesn't resolve (the rewrite layer
    hides the path from TemplateDoesNotExist).

The README already states "Bulma — only supported theme" for v0.1, and
the cotton/{bootstrap,daisy,fomantic,foundation}/ directories are
PLANNED.md stubs. Multi-theme support, when it lands, will happen
inside the templates (context-flag class names, or
{% include "cotton/cf/_themes/<theme>/<name>.html" %} partials) —
the directory layout no longer has to encode it.

Consumer migration

Most consumers: nothing to do. The bug only surfaced once they added
cf_ui.django.CfUiConfig to INSTALLED_APPS, and the workaround
(setting COTTON_DIR="cotton" explicitly to undo what cf-ui did) is
no longer needed — they should just remove that line.

The escape hatch from cf_ui import COTTON_TEMPLATES_DIR still works;
the relevant subdir changed from COTTON_TEMPLATES_DIR / "bulma" to
COTTON_TEMPLATES_DIR / "cf". Documented in the README.

Version

Bumped to 0.1.1. This is a bugfix (the package was broken for
the documented Django consumer use case), and the on-disk template
layout is not part of the public API — consumers use <c-cf.*> /
<CfCard>, which are unchanged. CHANGELOG entry added.

Tests

  • New tests/unit/test_consumer_compatibility.py (3 tests):
    1. Asserts CfUiConfig.ready() does not set
      COTTON_DIR="cotton/bulma" — pinning the regression.
    2. Builds a Django Engine that combines a tmpdir consumer template
      at cotton/myapp/foo.html with cf-ui's app-templates, and
      asserts both cotton/myapp/foo.html and
      cotton/cf/notification.html resolve through the same engine.
      This is the direct repro of the RankedJobs failure.
    3. Walks all 14 cf-ui cotton components and asserts each resolves at
      cotton/cf/<name>.html.
  • Updated tests/unit/test_core.py::test_django_appconfig_ready_sets_cotton_dir
    test_django_appconfig_does_not_override_cotton_dir.
  • Updated tests/unit/cotton/conftest.py template prefix
    (cotton/bulma/...cotton/...).
  • Updated tests/e2e/_e2e_django_settings.py — removed the now-unnecessary
    COTTON_DIR = "cotton/bulma" override.

uv run pytest tests/ -v (excluding the e2e suite, which needs a
playwright browser binary unavailable in this sandbox): 117 passed.

E2E settings module loads cleanly and get_template("cotton/cf/notification.html")
resolves end-to-end against _e2e_django_settings.

uv run ruff check src/ tests/ and uv run ruff format src/ tests/
both clean.

Test plan

  • Wait for CI (unit + integration + E2E) to go green.
  • In a consumer project (e.g. RankedJobs) on the new pin
    cf-ui==0.1.1, confirm <c-layouts.base> and other
    consumer-defined cotton components resolve again, and
    <c-cf.notification> / <c-cf.card> still render.
  • Confirm a consumer that previously set
    COTTON_DIR="cotton" as a workaround can drop that override.

https://claude.ai/code/session_01C8NrnRLghd26y2Qs325pvQ


Generated by Claude Code

@fsecada01 fsecada01 merged commit 7799ad7 into master Apr 28, 2026
4 checks passed
@fsecada01 fsecada01 deleted the fix/cotton-dir-consumer-conflict branch April 28, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants