statamic/preset-tailwindcss
A Statamic preset that quickly adds Tailwind CSS to a new Statamic site, providing configuration, a CSS entry point, and build setup for utility-first styling. It streamlines front-end setup by wiring Tailwind into the asset pipeline so developers can start using utility classes right away.
Read this first: the package is archived. statamic/preset-tailwindcss last shipped on 2019-05-09, targets Statamic 2, and predates Tailwind 1.0-era tooling. There is no service provider, no application-facing API, and no runtime PHP — it is a set of build files (tailwind.config.js, package.json, webpack.mix.js) plus an Antlers layout/partial set that a php please preset command copies into your theme. Treat it as a reference scaffold you copy from and delete, not a dependency you keep. On Statamic 3+ there is no preset installer at all; Tailwind is wired through Vite.
Where to look first, in order:
tailwind.config.js — content/purge configuration, theme extensions, and any safelist. This is 90% of the day-to-day value of the package.package.json + webpack.mix.js — the build pipeline (Tailwind version, PostCSS, Mix scripts).@tailwind directives, CSS entry, and markup to hang together.If you maintain a legacy Statamic 2 site:
composer require --dev statamic/preset-tailwindcss
Then, from the package README, run the preset install command inside the php please namespace. It copies the build files and template set into your theme directory. Run it on a clean working tree — it writes files non-interactively and will not prompt before overwriting your existing tailwind.config.js or layout.
git status # must be clean
php please <preset-command>
yarn && yarn dev
First use case — a legacy theme that needs Tailwind back:
The most legitimate day-one task is reproducing an existing build. Check out a throwaway branch, run the preset, diff the generated tailwind.config.js and layout against what is committed, and confirm you can build the same CSS. Do not merge the installation; merge only the extracted configuration, or nothing at all.
If you are on a modern Statamic/Laravel stack: do not install this. Scaffold Tailwind via @tailwindcss/vite and a current official Statamic starter kit, then mine this preset only for its config structure and Antlers conventions.
Copy-then-own (the recommended pattern). Use the preset as a one-shot generator against a disposable branch, extract the three build files and the Antlers layout, then remove the package:
git checkout -b spike/preset-inspect
composer require --dev statamic/preset-tailwindcss
php please <preset-command>
git diff # inspect what it produced
git checkout - # abandon the branch after extracting files
The end state is an internally owned tailwind.config.js and a Vite (or pinned Mix) pipeline — not a Composer dependency.
Content-scanning pattern for Antlers. The preset's content/purge config predates Tailwind's modern JIT, so it typically lists static globs. Extend it to cover Antlers templates, partials, and PHP-rendered views:
// tailwind.config.js
module.exports = {
content: [
'./resources/views/**/*.antlers.html',
'./resources/views/**/*.antlers.php',
'./resources/views/**/*.html',
'./content/**/*.md',
'./site/**/*.yaml',
],
theme: { extend: {} },
plugins: [],
};
If you are still on a purge-era Tailwind, the equivalent key is purge with content and options, plus an explicit extraction pattern for .antlers.html.
Dynamic class names → safelist pattern. This is the pattern that matters most day to day. Antlers composes classes at render time, so Tailwind's scanner cannot see them:
<div class="bg-{{ color }}-500">…</div>
That class will be stripped. Two working patterns:
Pattern A — safelist the finite set:
safelist: [
{ pattern: /bg-(red|green|blue|indigo|gray)-(100|500|700)/ },
'text-white',
],
Pattern B — full class names in Antlers, mapped rather than concatenated:
{{ if status === 'error' }}
<div class="bg-red-500">…</div>
{{ elseif status === 'warning' }}
<div class="bg-yellow-500">…</div>
{{ /if }}
Pattern B survives any Tailwind upgrade and needs no config edits. Prefer it in new markup.
Antlers layout integration. The preset wires the compiled stylesheet and markup conventions into a layout. Keep the stylesheet reference centralised so you can swap Mix output for a Vite manifest later:
<!-- resources/views/layout.antlers.html -->
<link rel="stylesheet" href="{{ mix src='css/site.css' }}">
/* resources/css/site.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Mix build pattern (legacy only). The preset's webpack.mix.js is a thin Tailwind/PostCSS wrapper:
mix.postCss('resources/css/site.css', 'public/css', [
require('tailwindcss'),
]);
Scripts in package.json drive it day to day: yarn dev for the watch loop, yarn production for a minified purge build. Commit the lockfile — the preset's transitive Node deps are old enough that unpinned installs drift.
Incremental migration to Vite (the real endgame). Once you own the files, do not keep Mix alive:
webpack.mix.js with vite.config.js and @tailwindcss/vite.tailwind.config.js as the source of truth so visual output matches.{{ mix src='...' }} for @vite(['resources/css/site.css']).Guardrail pattern. Add the package to a dependency allowlist or CI check so it cannot be reintroduced:
# CI step
if composer show statamic/preset-tailwindcss 2>/dev/null; then
echo "Archived preset reintroduced — see ADR-xxx"; exit 1
fi
site/themes/<theme> structure differs, it will scatter files — inspect the command source before executing.php artisan, php please, and composer are the only surfaces.package.json pins a pre-1.0/1.x Tailwind and an old PostCSS chain. Installing it into a project already on a modern Tailwind will either fail resolution or silently downgrade behaviour. Pin Node and lockfiles explicitly, or extract the config and skip the install.@tailwind directives look like errors to editors and linters. Configure your editor's CSS language server or a Stylelint Tailwind plugin to suppress false positives; otherwise every CSS file shows red squiggles.php please clear:cache or your equivalent) and reload. If static caching or a CDN is in front, purge it too — otherwise you will debug a Tailwind issue that is actually stale HTML or stale CSS.tailwind.config.js. There is no plugin API, no events, and no hooks — anything the preset should "do" is a copy you own.How can I help you explore Laravel packages today?