ForgeTrust.AppSurface.Web.Tailwind
0.1.0-rc.1
dotnet add package ForgeTrust.AppSurface.Web.Tailwind --version 0.1.0-rc.1
NuGet\Install-Package ForgeTrust.AppSurface.Web.Tailwind -Version 0.1.0-rc.1
<PackageReference Include="ForgeTrust.AppSurface.Web.Tailwind" Version="0.1.0-rc.1" />
<PackageVersion Include="ForgeTrust.AppSurface.Web.Tailwind" Version="0.1.0-rc.1" />
<PackageReference Include="ForgeTrust.AppSurface.Web.Tailwind" />
paket add ForgeTrust.AppSurface.Web.Tailwind --version 0.1.0-rc.1
#r "nuget: ForgeTrust.AppSurface.Web.Tailwind, 0.1.0-rc.1"
#:package ForgeTrust.AppSurface.Web.Tailwind@0.1.0-rc.1
#addin nuget:?package=ForgeTrust.AppSurface.Web.Tailwind&version=0.1.0-rc.1&prerelease
#tool nuget:?package=ForgeTrust.AppSurface.Web.Tailwind&version=0.1.0-rc.1&prerelease
ForgeTrust.AppSurface.Web.Tailwind
Tailwind CSS integration for AppSurface web applications with zero Node.js dependency.
Overview
This package wires the Tailwind standalone CLI into the AppSurface web build pipeline so your app can compile generated CSS during builds and run Tailwind in watch mode during development.
Release Guidance
AppSurface has cut the first coordinated v0.1.0 release candidate. Before installing this package from a prerelease feed, read the v0.1.0 RC 1 release note for current release risk, migration guidance, and package readiness.
Features
- No Node.js required: Uses the official standalone Tailwind CLI binaries.
- RID-aware runtime packages: Pulls in the platform-specific runtime package automatically when the package is restored.
- Build integration: Compiles
wwwroot/css/app.csstowwwroot/css/site.gen.cssby default. - Development watch mode: Starts Tailwind in
--watchduring development when you register the service.
Usage
First Tailwind page in five minutes
- Add the package to an AppSurface web project:
dotnet add package ForgeTrust.AppSurface.Web.Tailwind
- Create the default input file:
/* wwwroot/css/app.css */
@import "tailwindcss";
- Register watch mode for local development:
services.AddTailwind(options =>
{
options.InputPath = "wwwroot/css/app.css";
options.OutputPath = "wwwroot/css/site.gen.css";
});
- Reference the generated stylesheet from your layout:
<link rel="stylesheet" href="~/css/site.gen.css" asp-append-version="true" />
- Build and run:
dotnet build
dotnet run
The build should log Tailwind CSS: Running build for wwwroot/css/app.css -> wwwroot/css/site.gen.css, create wwwroot/css/site.gen.css, and include that file in static web assets when the output remains under wwwroot/.
Build and watch behavior
When OutputPath stays under wwwroot/, the generated file is registered as an ASP.NET Core static web
asset on clean builds and publish runs. That means Razor Class Libraries and other package-style consumers can
serve the generated CSS without checking site.gen.css into source control first.
That registration also stays in place for projects that disable the SDK's default content items and rely on the
package to declare the generated web-root asset explicitly.
Keep InputPath and OutputPath pointed at different files. The build target and the development watch service both reject configurations where the two paths resolve to the same file, even if one path uses a normalized relative form such as ./wwwroot/css/../css/app.css.
During development, the watch service is non-blocking. If the Tailwind CLI is not available on the current machine, the app still starts and serves any existing CSS while logging a warning that points developers to the runtime package or TailwindOptions.CliPath override. Other startup failures still log as errors.
Build mode uses a compiled MSBuild task instead of <Exec>. The task receives structured arguments, emits stable ASTW### diagnostics, and keeps build resolution behavior explicit. Build mode does not search PATH; use TailwindCliPath when you want a custom CLI during builds. Watch mode may use PATH as a development convenience after checking packaged runtime locations.
MSBuild property reference
| Property | Default | Behavior |
|---|---|---|
TailwindEnabled |
true |
Set to false to skip package-driven build integration. |
TailwindInputPath |
wwwroot/css/app.css |
CSS input path, resolved relative to the project directory. |
TailwindOutputPath |
wwwroot/css/site.gen.css |
Generated CSS path, resolved relative to the project directory. Keep it under wwwroot/ for static web asset registration. |
TailwindCliPath |
empty | Explicit build-time Tailwind CLI path. Relative paths resolve from the project directory. Build mode does not fall back to PATH. |
TailwindVersion |
from build/tailwind.version |
Tailwind standalone CLI version used by runtime packages. Override only when testing a coordinated runtime-package change. |
Runtime option reference
| Option | Default | Behavior |
|---|---|---|
Enabled |
true |
Set to false to disable development watch mode. |
InputPath |
wwwroot/css/app.css |
Watch-mode input path, resolved relative to the content root. |
OutputPath |
wwwroot/css/site.gen.css |
Watch-mode output path, resolved relative to the content root. |
CliPath |
null |
Explicit watch-mode Tailwind CLI path. Relative paths resolve from the content root. |
CI
ForgeTrust.AppSurface.Web.Tailwind hooks into the normal dotnet build and dotnet publish pipeline through MSBuild targets, so the default integration does not require a separate npm install or npm run build step in CI.
Runtime packages download the official Tailwind checksum file and standalone binary during build or publish, then verify the binary with SHA-256 before packaging it. These downloads retry transient network failures by default, which keeps CI resilient to brief GitHub release CDN 5xx responses and timeouts without weakening checksum validation.
The retry behavior is configurable with MSBuild properties:
<PropertyGroup>
<TailwindDownloadRetries>4</TailwindDownloadRetries>
<TailwindDownloadRetryDelayMilliseconds>5000</TailwindDownloadRetryDelayMilliseconds>
</PropertyGroup>
Raise these values for slower CI networks. Lower them only when you prefer fail-fast behavior and have another way to provide the Tailwind CLI, such as TailwindCliPath.
If you need to suppress the package-driven build temporarily, set TailwindEnabled=false in MSBuild, for example with dotnet build -p:TailwindEnabled=false or a project-level <TailwindEnabled>false</TailwindEnabled> property.
If you want to keep the package-driven build but point it at a different standalone Tailwind executable, set TailwindCliPath to an absolute path or a project-relative file path:
<PropertyGroup>
<TailwindCliPath>tools/tailwindcss/tailwindcss</TailwindCliPath>
</PropertyGroup>
Use the matching runtime option for development watch mode:
services.AddTailwind(options =>
{
options.CliPath = "tools/tailwindcss/tailwindcss";
});
On Windows, TailwindCliPath and TailwindOptions.CliPath can point at the standalone binary directly or at the npm-generated .cmd, .bat, or .ps1 shim. The package wraps those shims with the correct launcher while preserving argument boundaries for paths with spaces.
Tailwind diagnostics
Every build-task diagnostic includes a stable code, problem, cause, fix, and this troubleshooting anchor.
| Code | Meaning | Fix |
|---|---|---|
ASTW001 |
The build host could not be mapped to a supported Tailwind runtime identifier. | Build on Windows x64/Arm64, macOS x64/Arm64, or Linux x64/Arm64, or set TailwindCliPath. |
ASTW002 |
TailwindVersion could not be resolved. |
Ensure build/tailwind.version is present next to the targets file or set TailwindVersion. |
ASTW003 |
TailwindCliPath was set but the resolved file does not exist. |
Point TailwindCliPath at an existing standalone binary or remove it to use packaged runtimes. |
ASTW004 |
No build-mode Tailwind CLI was found. | Install the matching runtime package or set TailwindCliPath; build mode does not search PATH. |
ASTW005 |
The MSBuild task assembly could not load or the Tailwind process could not start. | Restore/build the package, verify build/tasks exists in the nupkg, and ensure the CLI file is executable. |
ASTW006 |
Tailwind exited with a non-zero code. | Read the captured output tail, fix the CSS/configuration error, and run the build again. |
ASTW007 |
MSBuild canceled the Tailwind task. | Re-run the build if cancellation was unintentional. |
ASTW008 |
Input and output resolve to the same file. | Set TailwindOutputPath to a generated file distinct from TailwindInputPath. |
If an error mentions build/tasks, inspect the packed package. A valid package contains build/ForgeTrust.AppSurface.Web.Tailwind.targets, build/tailwind.version, build/tasks/ForgeTrust.AppSurface.Web.Tailwind.Tasks.dll, and build/tasks/CliWrap.dll.
Escape hatch (plugin-heavy Tailwind setups)
If your Tailwind configuration depends on npm-only plugins or custom JavaScript tooling, keep your existing Node-based asset pipeline instead of forcing the standalone CLI path.
Disable the package-driven MSBuild integration with TailwindEnabled=false, and either omit services.AddTailwind() or set options.Enabled = false so the development watch service does not start. After that, run your existing npm, pnpm, or yarn Tailwind command as part of your normal frontend build.
If your custom setup still uses the standalone CLI but stores it outside the package runtime layout, prefer TailwindCliPath over editing the imported .targets file directly.
The v0.1 integration intentionally does not expose separate MSBuild knobs for minification, additional Tailwind arguments, working directory, template input globs, config input globs, or static web asset registration. Those defaults are part of the zero-Node path. Use TailwindEnabled=false and your own asset pipeline when a project needs full Tailwind command control.
Notes
- The generated CSS file is intended to be build output and is commonly ignored in source control.
- Generated CSS outside
wwwroot/still builds locally, but it is not exposed automatically through the static web asset pipeline. - The platform-specific
ForgeTrust.AppSurface.Web.Tailwind.Runtime.*packages are support packages consumed transitively by this package and are not usually installed directly. - Tailwind CLI selection follows the current build host, not
RuntimeIdentifier, because the standalone CLI runs during the build. Cross-targeted builds still execute the host-compatible binary. - Windows Arm64 hosts intentionally use the
win-x64runtime under emulation. There is noForgeTrust.AppSurface.Web.Tailwind.Runtime.win-arm64package because Tailwindv4.1.18does not ship a native Windows Arm64 standalone CLI.
| 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
- CliWrap (>= 3.10.1)
- ForgeTrust.AppSurface.Core (>= 0.1.0-rc.1)
- ForgeTrust.AppSurface.Web.Tailwind.Runtime.linux-arm64 (>= 0.1.0-rc.1)
- ForgeTrust.AppSurface.Web.Tailwind.Runtime.linux-x64 (>= 0.1.0-rc.1)
- ForgeTrust.AppSurface.Web.Tailwind.Runtime.osx-arm64 (>= 0.1.0-rc.1)
- ForgeTrust.AppSurface.Web.Tailwind.Runtime.osx-x64 (>= 0.1.0-rc.1)
- ForgeTrust.AppSurface.Web.Tailwind.Runtime.win-x64 (>= 0.1.0-rc.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ForgeTrust.AppSurface.Web.Tailwind:
| Package | Downloads |
|---|---|
|
ForgeTrust.AppSurface.Docs
ForgeTrust.AppSurface.Docs package for AppSurface application composition. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-rc.1 | 98 | 5/31/2026 |
| 0.1.0-preview.4 | 367 | 5/25/2026 |
| 0.1.0-preview.3 | 61 | 5/20/2026 |
| 0.1.0-preview.2 | 49 | 5/14/2026 |