You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(config): auto @source external apps and watch-mode auto-reload
Two related features addressing issue #187, both landed together so they
compose on the first release.
1. Auto @source injection (opt-in):
New setting TAILWIND_CLI_AUTO_SOURCE_EXTERNAL_APPS (default False).
When enabled, the auto-generated default source.css gains one
@source directive per installed Django app whose path lies both
outside BASE_DIR and outside every known site-packages directory.
That's the exact shape of the issue #187 pain point: editable
installs of a sibling source repository whose templates Tailwind
cannot see on its own. Internal apps are left to Tailwind's CWD
walk; regular pip-installed third-party apps are filtered out via
a site.getsitepackages() / sysconfig check so we don't pull in
django.contrib.admin and friends.
The directive points at the app base dir, not at a glob, so
Tailwind's own file walker handles extension detection and
.gitignore exclusion — and incidentally picks up Tailwind class
strings embedded in Python code (form widgets, admin Media
classes, etc.).
2. Watch-mode auto-reload:
tailwind watch now wraps its loop in
django.utils.autoreload.run_with_reloader — the same machinery
manage.py runserver uses. Editing settings.py (e.g. adding a new
INSTALLED_APPS entry) restarts the watch process, regenerates
source.css with the fresh external-app list, and respawns the
Tailwind CLI subprocess. Pass --noreload to disable.
Tests that exercise watch via call_command now bypass the
reloader with an autouse fixture that mocks run_with_reloader to
invoke its callable directly. This keeps the existing test suite
in-process instead of forking per invocation.
Opt-in on the setting was a deliberate choice: the feature injects
extra directives into a generated file and expands Tailwind's scan
scope. Users who don't need it see no behaviour change, and the one
user who hits the issue flips a single flag.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,8 @@
8
8
### 🎯 New Features
9
9
-**Configurable minification**: New `TAILWIND_CLI_AUTOMATIC_MINIFY` setting and `--minify` / `--no-minify` flag on `tailwind build` for projects whose asset pipelines already minify CSS. Defaults preserve existing behavior.
10
10
-**System binary support**: New `TAILWIND_CLI_USE_SYSTEM_BINARY` setting lets `django-tailwind-cli` use a Tailwind CSS CLI that is already installed on `PATH` (e.g. via Homebrew), skipping the auto-download. Pairs with optional `TAILWIND_CLI_SYSTEM_BINARY_NAME` override. Emits a warning if the installed binary's version differs from an explicitly pinned `TAILWIND_CLI_VERSION`.
11
+
-**Auto `@source` for editable external apps** (opt-in): New `TAILWIND_CLI_AUTO_SOURCE_EXTERNAL_APPS` setting (default `False`). When enabled, the auto-generated default source CSS receives one `@source` directive per installed Django app whose path lives outside both `BASE_DIR` and site-packages — typically editable-installed packages that ship their own templates. This removes the need for fragile `@source "../../../../../..."` workarounds. Addresses [#187](https://github.com/django-commons/django-tailwind-cli/issues/187).
12
+
-**Watch mode auto-reload**: `python manage.py tailwind watch` now runs under Django's own auto-reloader (the same machinery `runserver` uses). Changing `settings.py` or any Python file restarts the watch process, regenerates the source CSS (picking up new `INSTALLED_APPS`), and restarts the Tailwind CLI subprocess. Pass `--noreload` to disable.
11
13
12
14
### 🛠️ Developer Experience
13
15
-**Gitignore cleanup**: Trimmed `.gitignore` to project-relevant entries only
Copy file name to clipboardExpand all lines: docs/settings.md
+32Lines changed: 32 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,6 +42,38 @@ In case you want to use the new behaviour, it is highly recommended to also set
42
42
43
43
Enable or disable the automatic downloading of the official CLI to your machine.
44
44
45
+
### TAILWIND_CLI_AUTO_SOURCE_EXTERNAL_APPS
46
+
47
+
**Default**: `False` (opt-in)
48
+
49
+
When enabled, the auto-generated default source CSS file gains one `@source` directive per installed Django app whose path lives **outside**`BASE_DIR`**and** outside every known site-packages directory. This covers exactly one real-world case: editable-installed packages that ship with their own templates, e.g. `pip install -e ../my-ui-library`.
50
+
51
+
Why it matters: Tailwind CSS 4.x discovers source files by walking the current working directory tree. Apps installed as editable packages from a sibling repository sit outside that tree and are therefore invisible to Tailwind unless declared explicitly. Turning this setting on makes `django-tailwind-cli` emit the declarations for you, using absolute paths that Tailwind can follow.
52
+
53
+
```python
54
+
# settings.py
55
+
TAILWIND_CLI_AUTO_SOURCE_EXTERNAL_APPS=True
56
+
```
57
+
58
+
With the setting enabled and an editable package `extra` installed, the auto-generated `source.css` looks like:
59
+
60
+
```css
61
+
@import"tailwindcss";
62
+
63
+
/* Auto-generated: installed apps outside BASE_DIR and site-packages. */
64
+
@source "/absolute/path/to/editable/extra";
65
+
```
66
+
67
+
:::{note}
68
+
The directive points at the app base dir, not at a glob. Tailwind CSS 4.x walks the directory and applies its own exclusions (`.gitignore`, binaries, etc.) — this also means class names embedded in Python files (e.g. form widget `attrs={"class": "..."}` strings) are picked up automatically.
69
+
:::
70
+
71
+
:::{warning}
72
+
This setting only affects the **auto-generated** default source CSS. If you set `TAILWIND_CLI_SRC_CSS` to point at a hand-written CSS file, that file is left untouched — add the `@source` directives yourself if you need them.
73
+
:::
74
+
75
+
The list of external apps is re-evaluated whenever the source CSS is written. When combined with the `tailwind watch` auto-reloader, installing a new app or editing `INSTALLED_APPS` automatically regenerates the declarations and triggers a Tailwind rebuild.
Copy file name to clipboardExpand all lines: docs/usage.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,14 @@ Run `python manage.py tailwind build` to create an optimized production built of
22
22
23
23
Run `python manage.py tailwind watch` to just start a tailwind watcher process if you prefer to start your debug server in a seperate shell or prefer a different solution than runserver or runserver_plus.
24
24
25
+
By default the watch command runs under Django's own auto-reloader (the same one `runserver` uses). Whenever you change a Python file — including `settings.py` — the watcher restarts its Python process, regenerates the default source CSS file (picking up freshly added `INSTALLED_APPS`), and restarts the Tailwind CLI subprocess. This pairs nicely with [`TAILWIND_CLI_AUTO_SOURCE_EXTERNAL_APPS`](settings.md#tailwind_cli_auto_source_external_apps): adding an editable-installed app and updating `INSTALLED_APPS` is enough — no manual restart needed.
26
+
27
+
Pass `--noreload` if you want a single-process watch loop (e.g. in CI or when debugging the watcher itself):
28
+
29
+
```bash
30
+
python manage.py tailwind watch --noreload
31
+
```
32
+
25
33
### runserver
26
34
27
35
Run `python manage.py tailwind runserver` to start the classic Django debug server in parallel to a tailwind watcher process.
0 commit comments