Tailwind Compiler For Razor
$ dotnet add package Angelo.TailwindA zero-configuration Tailwind CSS compiler for ASP.NET Core. Automatically downloads the Tailwind CLI, watches for file changes, and compiles your CSS during development.
Scaffold Support — This package supports Angelo.Scaffold. Run the scaffold terminal to automatically configure your project.
input.css filedotnet add package Angelo.Tailwind
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTailwind();
var app = builder.Build();
app.UseStaticFiles();
app.UseTailwind();
app.Run();
Create an input.css file in one of these locations:
Tailwind/input.css (recommended)Styles/input.cssAssets/input.csswwwroot/css/input.css/* input.css */
@import "tailwindcss";
/* Your custom styles below */
<!-- Views/Shared/_Layout.cshtml -->
<link rel="stylesheet" href="~/css/tailwind.css" />
dotnet run
That's it. Tailwind will compile automatically and recompile whenever you save changes to your views.
All options are optional. Configure only what you need:
builder.Services.AddTailwind(options =>
{
// Tailwind CLI version (default: "v4.0.0")
options.Version = "v4.0.0";
// Input CSS file (auto-detected if not specified)
options.InputCss = "Tailwind/input.css";
// Output CSS file (default: "wwwroot/css/tailwind.css")
options.OutputCss = "wwwroot/css/tailwind.css";
// Content paths to scan for classes
options.ContentPaths = ["./Views/**/*.cshtml", "./Pages/**/*.cshtml"];
// File patterns to watch for changes
options.WatchPatterns = ["**/*.cshtml", "**/*.razor", "**/*.html"];
// Debounce delay in ms (default: 300)
options.DebounceMs = 300;
// Minify output (default: true)
options.Minify = true;
// Where to store the Tailwind binary (default: ".tailwind")
options.BinaryPath = ".tailwind";
// Additional CLI arguments
options.AdditionalArguments = ["--verbose"];
});
| Option | Default | Description |
|---|---|---|
Version | "v4.0.0" | Tailwind CLI version to download |
InputCss | Auto-detected | Path to your input CSS file |
OutputCss | "wwwroot/css/tailwind.css" | Where to write compiled CSS |
ContentPaths | ["./Views/**/*.cshtml", "./Pages/**/*.cshtml"] | Paths to scan for Tailwind classes |
WatchPatterns | ["**/*.cshtml", "**/*.razor", "**/*.html"] | File patterns that trigger recompilation |
DebounceMs | 300 | Delay before recompiling after changes |
Minify | true | Minify the output CSS |
BinaryPath | ".tailwind" | Directory for the Tailwind CLI binary |
BinaryUrl | Auto-detected | Override the binary download URL |
AdditionalArguments | [] | Extra arguments for the Tailwind CLI |
If you don't specify InputCss, Angelo.Tailwind searches these locations in order:
Tailwind/input.cssStyles/input.cssAssets/input.csswwwroot/css/input.csswwwroot/input.css./input.cssIf exactly one input.css is found, it's used automatically. If multiple are found, you'll be prompted to specify which one to use.
On first run, Angelo.Tailwind downloads the correct Tailwind CLI binary for your platform:
The binary is cached in the .tailwind directory. Add this to your .gitignore:
.tailwind/
Visual Studio creates CSS files with a UTF-8 BOM (Byte Order Mark) by default, which breaks Tailwind compilation. Angelo.Tailwind automatically detects and removes the BOM, logging a warning when it does so.
Angelo.Tailwind only runs in the Development environment. In Production, Staging, or any other environment, the middleware does nothing. For production builds, compile your CSS as part of your CI/CD pipeline or publish process.
For production, compile your CSS during the build/publish process:
Add to your .csproj:
<Target Name="CompileTailwind" BeforeTargets="Build" Condition="'$(Configuration)' == 'Release'">
<Exec Command="npx tailwindcss -i ./Tailwind/input.css -o ./wwwroot/css/tailwind.css --minify" />
</Target>
# Install Tailwind CLI
npm install -g tailwindcss
# Compile
tailwindcss -i ./Tailwind/input.css -o ./wwwroot/css/tailwind.css --minify
# Then publish
dotnet publish -c Release
Simply commit your compiled wwwroot/css/tailwind.css to source control. It will be included in your publish output.
Create an input.css file in one of the expected locations, or configure the path explicitly:
builder.Services.AddTailwind(options =>
{
options.InputCss = "path/to/your/input.css";
});
Specify which file to use:
builder.Services.AddTailwind(options =>
{
options.InputCss = "Tailwind/input.css";
});
Check the console output for errors. Enable debug logging for more detail:
// appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Angelo.Tailwind": "Debug"
}
}
}
If you're behind a corporate firewall or proxy, download the binary manually and configure the path:
https://github.com/tailwindlabs/tailwindcss/releases.tailwind/ directorytailwindcss-windows-x64.exe)Or override the URL:
builder.Services.AddTailwind(options =>
{
options.BinaryUrl = "https://internal-mirror.company.com/tailwindcss-windows-x64.exe";
});
Ensure your file patterns match your project structure:
builder.Services.AddTailwind(options =>
{
options.WatchPatterns =
[
"**/*.cshtml",
"**/*.razor",
"**/*.html",
"**/*.js" // Add if using classes in JS
];
});
MyProject/
├── Program.cs
├── Tailwind/
│ └── input.css ← Your Tailwind input
├── Views/
│ ├── Shared/
│ │ └── _Layout.cshtml ← Reference tailwind.css here
│ └── Home/
│ └── Index.cshtml
├── wwwroot/
│ └── css/
│ └── tailwind.css ← Compiled output (generated)
├── .tailwind/ ← CLI binary (gitignored)
└── .gitignore
@import "tailwindcss";
/* Custom base styles */
@layer base {
html {
font-family: 'Inter', sans-serif;
}
}
/* Custom components */
@layer components {
.btn {
@apply px-4 py-2 rounded-lg font-medium transition-colors;
}
.btn-primary {
@apply bg-blue-600 text-white hover:bg-blue-700;
}
}
/* Custom utilities */
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
| OS | Architecture | Supported |
|---|---|---|
| Windows | x64 | ✅ |
| Windows | ARM64 | ✅ |
| Linux | x64 | ✅ |
| Linux | ARM64 | ✅ |
| Linux | ARMv7 | ✅ |
| macOS | x64 | ✅ |
| macOS | ARM64 (Apple Silicon) | ✅ |
MIT License. See LICENSE for details.