Angelo.Tailwind
1.0.3
dotnet add package Angelo.Tailwind --version 1.0.3
NuGet\Install-Package Angelo.Tailwind -Version 1.0.3
<PackageReference Include="Angelo.Tailwind" Version="1.0.3" />
<PackageVersion Include="Angelo.Tailwind" Version="1.0.3" />
<PackageReference Include="Angelo.Tailwind" />
paket add Angelo.Tailwind --version 1.0.3
#r "nuget: Angelo.Tailwind, 1.0.3"
#:package Angelo.Tailwind@1.0.3
#addin nuget:?package=Angelo.Tailwind&version=1.0.3
#tool nuget:?package=Angelo.Tailwind&version=1.0.3
Angelo.Tailwind
A 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.
Features
- Zero Configuration — Works out of the box with sensible defaults
- Auto-Detection — Automatically finds your
input.cssfile - Self-Contained — Downloads the correct Tailwind CLI binary for your platform
- Hot Reload — Watches for file changes and recompiles automatically
- Visual Studio Friendly — Automatically handles UTF-8 BOM issues
- Development Only — Runs only in Development environment, no overhead in production
Installation
dotnet add package Angelo.Tailwind
Quick Start
1. Add the service
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTailwind();
var app = builder.Build();
app.UseStaticFiles();
app.UseTailwind();
app.Run();
2. Create your input.css
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 */
3. Reference the output in your layout
<link rel="stylesheet" href="~/css/tailwind.css" />
4. Run your application
dotnet run
That's it. Tailwind will compile automatically and recompile whenever you save changes to your views.
Configuration
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"];
});
Options Reference
| 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 |
How It Works
Auto-Detection
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.css
If exactly one input.css is found, it's used automatically. If multiple are found, you'll be prompted to specify which one to use.
Binary Management
On first run, Angelo.Tailwind downloads the correct Tailwind CLI binary for your platform:
- Windows x64/ARM64
- Linux x64/ARM64
- macOS x64/ARM64
The binary is cached in the .tailwind directory. Add this to your .gitignore:
.tailwind/
UTF-8 BOM Handling
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.
Development Only
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.
Production Builds
For production, compile your CSS during the build/publish process:
Option 1: MSBuild Target
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>
Option 2: CI/CD Script
# 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
Option 3: Commit Compiled CSS
Simply commit your compiled wwwroot/css/tailwind.css to source control. It will be included in your publish output.
Troubleshooting
"Could not find 'input.css' in your project"
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";
});
"Multiple 'input.css' files found"
Specify which file to use:
builder.Services.AddTailwind(options =>
{
options.InputCss = "Tailwind/input.css";
});
Compilation fails silently
Check the console output for errors. Enable debug logging for more detail:
// appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Angelo.Tailwind": "Debug"
}
}
}
Binary download fails
If you're behind a corporate firewall or proxy, download the binary manually and configure the path:
- Download from:
https://github.com/tailwindlabs/tailwindcss/releases - Place in
.tailwind/directory - Ensure the filename matches the expected pattern (e.g.,
tailwindcss-windows-x64.exe)
Or override the URL:
builder.Services.AddTailwind(options =>
{
options.BinaryUrl = "https://internal-mirror.company.com/tailwindcss-windows-x64.exe";
});
Changes not detected
Ensure your file patterns match your project structure:
builder.Services.AddTailwind(options =>
{
options.WatchPatterns =
[
"**/*.cshtml",
"**/*.razor",
"**/*.html",
"**/*.js" // Add if using classes in JS
];
});
Example Project Structure
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
Sample input.css
@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;
}
}
Requirements
- .NET 10.0 or later
- ASP.NET Core
- Internet connection (first run only, to download CLI)
Supported Platforms
| OS | Architecture | Supported |
|---|---|---|
| Windows | x64 | ✅ |
| Windows | ARM64 | ✅ |
| Linux | x64 | ✅ |
| Linux | ARM64 | ✅ |
| Linux | ARMv7 | ✅ |
| macOS | x64 | ✅ |
| macOS | ARM64 (Apple Silicon) | ✅ |
License
MIT License. See LICENSE for details.
Links
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.