Skip to content

Frontend Assets

The admin UI uses pre-compiled Tailwind CSS that ships with the package. End users do not need any Node toolchain — composer require is enough.

For contributors

This page is for contributors who change templates or add new utility classes. If you are just using the plugin, you can skip it.

What ships in the package

FilePurposeCommitted?
webroot/css/tailwind.cssGenerated, minified Tailwind utilities used by the admin UIyes
webroot/css/tailwind.input.cssThe three @tailwind directives that feed the buildyes
tailwind.config.jsContent scan paths, dark-mode strategy, custom primary coloryes
webroot/css/tinyauth.cssHand-written non-Tailwind styles (matrix cells, dropdowns, tree, etc.)yes
webroot/js/tinyauth.jsAll admin JS — search, dropdowns, dark-mode, role drag-and-dropyes

webroot/css/tailwind.css is regenerated by tree-shaking against tailwind.config.js's content paths, so it only contains classes the templates actually use.

When to regenerate

You only need to rebuild tailwind.css when:

  • you add a new Tailwind utility class to a .php template under templates/ or to webroot/js/tinyauth.js
  • you change tailwind.config.js (e.g. add a new theme color)

Editing existing classes that are already in use does not require a rebuild.

How to regenerate

The plugin has a composer assets script that wraps the Tailwind v3 CLI via npx:

sh
composer assets

Internally this runs:

sh
npx --yes tailwindcss@^3 -i webroot/css/tailwind.input.css -o webroot/css/tailwind.css --minify

Requirements:

  • Node 18+ available on the contributor's machine (used by npx); not required for end users.
  • /node_modules/ is gitignored — the npx cache lives there. Do not commit it.

Commit together

Commit the regenerated webroot/css/tailwind.css along with the template change in the same PR.

Why precompiled and not the Tailwind Play CDN

The admin UI is designed to be servable under a strict Content-Security-Policy header (no script-src 'unsafe-eval', no style-src 'unsafe-inline'). The Play CDN at https://cdn.tailwindcss.com cannot be used under strict CSP because it JIT-compiles utility classes in the browser via Function() — that is, by definition, unsafe-eval. Pre-compiling in the package keeps the plugin strict-CSP compatible out of the box.

Inline <script> blocks that remain in the layout (HTMX CSRF wiring, dark-mode FOUC bootstrap, the window.TinyAuth URL map) carry the request's cspNonce so they pass under nonced strict CSP without needing unsafe-inline. See Strict CSP for the host-app side.

CSP guard test

tests/TestCase/CspComplianceTest.php scans templates/ for Alpine.js directives and inline event handlers (onclick=, x-data=, @click=, etc.) and fails if any reappear. Run it via composer test or directly:

sh
vendor/bin/phpunit tests/TestCase/CspComplianceTest.php

If you add a new template, this test catches accidental CSP regressions before review.

Released under the MIT License.