Tailwind CSS 79 🎨 Standalone Binary CLI Distribution in Non-Node.js Workflows (Go, Rust, Rails)
A Tailwind project has traditionally required Node.js. The package.json holds the dependency, the node_modules holds the engine, and the build runs through npm scripts or a bundler plugin. For a Go service, a Rust application, or a Rails monolith, that requirement is friction. The project already has a build pipeline, and adding a second runtime for the CSS is the extra dependency the team did not want. The standalone CLI is the answer. It is a single, self-contained executable that bundles the Tailwind engine and runs without Node.js, npm, or the node_modules directory. This chapter covers the binary, the download, the @source directive, and the integration with the three ecosystems.
Key point: The standalone CLI is the same engine as the npm package, compiled to a native binary. It reads the input CSS, scans the source files, and writes the output CSS. The @source directive tells the binary where to look, and the --watch flag rebuilds on the change. The binary is the distribution, and the Node.js is the optional.
Why the standalone CLI exists
The Node.js dependency problem. A Go or a Rust project does not have the Node.js. Adding it for the CSS means installing the runtime, the package manager, and the node_modules tree on every developer machine and every CI runner. The standalone binary is the one file, and the runtime is the none.
The build-pipeline problem. The project already has the Makefile, the Cargo build, or the Rails asset pipeline. Adding the npm script means the second pipeline, the second lockfile, and the second set of the tools to maintain. The standalone binary integrates with the existing pipeline.
The binary-distribution problem. The npm package requires the network access to the registry, the version resolution, and the cache. The standalone binary is the download, the checksum, and the run. The distribution is the simpler.
The version-pinning problem. The package.json pins the version, and the lockfile pins the transitive. The standalone binary is the one version, and the checksum is the integrity.
The performance problem. The binary is the native, and it starts faster than the Node.js process. The Oxide engine is the same, and the startup is the smaller.
The offline problem. The air-gapped environment cannot reach the npm registry. The standalone binary is the download once, and the run offline.
The multi-platform problem. The releases cover the Linux, the macOS, and the Windows, on the x64 and the arm64. The Go, the Rust, and the Rails projects on the any platform use the same command.
a. The download and the setup
The binary is the GitHub release. The download is the platform-specific, and the checksum is the verification.
The download
The releases page lists the assets. The naming is the tailwindcss-<platform>-<arch>.
# The Linux x64
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64
# The macOS arm64
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64
# The Windows x64
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-windows-x64.exe
The latest resolves to the newest release. The pinned version replaces the latest for the reproducibility.
The executable permission
chmod +x tailwindcss-linux-x64
mv tailwindcss-linux-x64 tailwindcss
The chmod adds the execute bit, and the mv renames to the short name.
The verification
# The checksum
sha256sum tailwindcss
# Compare with the release page.
The checksum is the integrity, and the release page publishes it.
The basic command
./tailwindcss -i ./input.css -o ./output.css
The -i is the input, the -o is the output, and the command runs once.
The command flags
| The flag | The purpose |
|---|---|
-i, --input | The input CSS |
-o, --output | The output CSS |
--watch | The rebuild on the change |
--minify | The minify the output |
--cwd | The working directory |
--content | The legacy content (the v3) |
The v4 input CSS
@import "tailwindcss";
@source "./**/*.go";
@source "./templates/**/*.html";
The @import loads the framework, and the @source tells the binary where the class names are.
The watch
./tailwindcss -i ./input.css -o ./output.css --watch
The --watch rebuilds on the change. The binary watches the @source paths and the input.
The minify
./tailwindcss -i ./input.css -o ./output.css --minify
The --minify produces the production output.
The setup table
| The step | The command |
|---|---|
| The download | curl -sLO ... |
| The permission | chmod +x ... |
| The rename | mv ... tailwindcss |
| The verify | sha256sum ... |
| The run | ./tailwindcss -i ... -o ... |
b. The integration with the Go
The Go project does not have the Node.js. The standalone binary is the downloaded file, and the Makefile is the build.
The project structure
myapp/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ └── handlers/
│ └── home.go
├── web/
│ ├── templates/
│ │ └── home.templ
│ └── static/
│ ├── css/
│ │ ├── input.css
│ │ └── output.css
│ └── tailwindcss
├── Makefile
└── go.mod
The tailwindcss binary is the web/static directory, and the input.css is the web/static/css.
The input CSS
@import "tailwindcss";
@source "../../../internal/**/*.go";
@source "../templates/**/*.templ";
The @source points to the Go files and the templ files. The templ is the templating engine for the Go.
The Makefile
.PHONY: build css css-watch run
build: css
go build -o bin/server ./cmd/server
css:
./web/static/tailwindcss \
-i ./web/static/css/input.css \
-o ./web/static/css/output.css \
--minify
css-watch:
./web/static/tailwindcss \
-i ./web/static/css/input.css \
-o ./web/static/css/output.css \
--watch
run: build
./bin/server
The make css produces the output, and the make build depends on it. The make css-watch is the development.
The templ class usage
templ Home() {
<div class="flex items-center gap-4 p-4 bg-blue-600 text-white">
<h1 class="text-2xl font-bold">Hello</h1>
</div>
}
The classes are the Tailwind, and the @source scans the .templ file.
The Go table
| The aspect | The approach |
|---|---|
| The binary | The web/static |
| The input | The web/static/css/input.css |
| The output | The web/static/css/output.css |
| The source | The internal/**/*.go, the templates/**/*.templ |
| The build | The Makefile |
| The watch | The make css-watch |
c. The integration with the Rust
The Rust project has the Cargo build. The standalone binary is the build-dependency or the downloaded tool.
The project structure
myapp/
├── src/
│ └── main.rs
├── style/
│ └── input.css
├── public/
│ └── output.css
├── tailwindcss
└── Cargo.toml
The tailwindcss binary is the project root, and the style/input.css is the input.
The input CSS
@import "tailwindcss";
@source "../src/**/*.rs";
The @source points to the Rust files. The classes are in the view! macro or the equivalent.
The build script
// build.rs
use std::process::Command;
fn main() {
let status = Command::new("./tailwindcss")
.args([
"-i", "style/input.css",
"-o", "public/output.css",
"--minify",
])
.status()
.expect("The tailwindcss failed");
if !status.success() {
panic!("The tailwindcss exited with the error");
}
println!("cargo:rerun-if-changed=style/input.css");
println!("cargo:rerun-if-changed=src");
}
The build.rs runs the binary at the Cargo build. The rerun-if-changed tells Cargo to re-run on the input or the source change.
The Leptos class usage
view! {
<div class="flex items-center gap-4 p-4 bg-blue-600 text-white">
<h1 class="text-2xl font-bold">"Hello"</h1>
</div>
}
The classes are the Tailwind, and the @source scans the .rs file.
The Pocopine automation
The Pocopine framework downloads and caches the correct binary on the first run. The manual setup is the alternative.
The Rust table
| The aspect | The approach |
|---|---|
| The binary | The project root |
| The input | The style/input.css |
| The output | The public/output.css |
| The source | The src/**/*.rs |
| The build | The build.rs |
| The rerun | The cargo:rerun-if-changed |
d. The integration with the Rails
The Rails has the tailwindcss-rails gem, which manages the binary for the developer.
The installation
# The Gemfile
bundle add tailwindcss-rails
# The installer
./bin/rails tailwindcss:install
The bundle add adds the gem, and the installer sets up the files.
The generated files
app/assets/tailwind/application.css
The installer creates the input file. The output goes to the app/assets/builds/tailwind.css.
The input CSS
@import "tailwindcss";
@source "../../../app/views/**/*.erb";
@source "../../../app/helpers/**/*.rb";
@source "../../../app/javascript/**/*.js";
The @source points to the Rails directories.
The Rake tasks
| The task | The purpose |
|---|---|
tailwindcss:build | The one-off build |
tailwindcss:watch | The development |
tailwindcss:clobber | The clean |
tailwindcss:install | The setup |
The tailwindcss:build is the production, and the tailwindcss:watch is the development.
The asset pipeline
The Rails 7+ uses the Propshaft or the Sprockets. The tailwindcss-rails integrates with the assets:precompile task.
./bin/rails assets:precompile
The task runs the tailwindcss:build before the asset compilation.
The Procfile
web: bin/rails server
css: bin/rails tailwindcss:watch
The bin/dev runs the two processes. The Rails 7 has the bin/dev with the Procfile.dev.
The ERB class usage
<div class="flex items-center gap-4 p-4 bg-blue-600 text-white">
<h1 class="text-2xl font-bold">Hello</h1>
</div>
The classes are the Tailwind, and the @source scans the .erb file.
The Rails table
| The aspect | The approach |
|---|---|
| The gem | The tailwindcss-rails |
| The input | The app/assets/tailwind/application.css |
| The output | The app/assets/builds/tailwind.css |
| The source | The app/views, the app/helpers, the app/javascript |
| The build | The tailwindcss:build |
| The watch | The tailwindcss:watch |
Complete Example Session
/* ============================================
PART 1: THE INPUT CSS
============================================ */
@import "tailwindcss";
@source "./**/*.go";
@source "./templates/**/*.html";
/* ============================================
PART 2: THE DOWNLOAD
============================================ */
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64
chmod +x tailwindcss-linux-x64
mv tailwindcss-linux-x64 tailwindcss
/* ============================================
PART 3: THE BASIC RUN
============================================ */
./tailwindcss -i ./input.css -o ./output.css
/* ============================================
PART 4: THE WATCH
============================================ */
./tailwindcss -i ./input.css -o ./output.css --watch
/* ============================================
PART 5: THE MINIFY
============================================ */
./tailwindcss -i ./input.css -o ./output.css --minify
/* ============================================
PART 6: THE GO MAKEFILE
============================================ */
build: css
go build -o bin/server ./cmd/server
css:
./web/static/tailwindcss -i ./web/static/css/input.css -o ./web/static/css/output.css --minify
css-watch:
./web/static/tailwindcss -i ./web/static/css/input.css -o ./web/static/css/output.css --watch
/* ============================================
PART 7: THE RUST BUILD SCRIPT
============================================ */
fn main() {
let status = Command::new("./tailwindcss")
.args(["-i", "style/input.css", "-o", "public/output.css", "--minify"])
.status()
.expect("The tailwindcss failed");
if !status.success() {
panic!("The tailwindcss exited with the error");
}
println!("cargo:rerun-if-changed=style/input.css");
println!("cargo:rerun-if-changed=src");
}
/* ============================================
PART 8: THE RAILS INSTALL
============================================ */
bundle add tailwindcss-rails
./bin/rails tailwindcss:install
/* ============================================
PART 9: THE RAILS TASKS
============================================ */
./bin/rails tailwindcss:build
./bin/rails tailwindcss:watch
/* ============================================
PART 10: THE COMPLETE PATTERN
============================================ */
// 1. Download the binary for the platform.
// 2. chmod +x and rename.
// 3. The @source points to the source files.
// 4. The -i and -o are the input and the output.
// 5. The --watch is the development.
// 6. The --minify is the production.
// 7. The Go uses the Makefile.
// 8. The Rust uses the build.rs.
// 9. The Rails uses the tailwindcss-rails.
// 10. The Node.js is the optional.
The ten parts showed the input CSS, the download, the basic run, the watch, the minify, the Go Makefile, the Rust build script, the Rails install, the Rails tasks, and the complete pattern.
Quick Reference
The CLI Flags
| The flag | The purpose |
|---|---|
-i, --input | The input CSS |
-o, --output | The output CSS |
--watch | The rebuild |
--minify | The minify |
--cwd | The working directory |
--content | The v3 content |
The Download
| The platform | The file |
|---|---|
| The Linux x64 | tailwindcss-linux-x64 |
| The Linux arm64 | tailwindcss-linux-arm64 |
| The macOS x64 | tailwindcss-macos-x64 |
| The macOS arm64 | tailwindcss-macos-arm64 |
| The Windows x64 | tailwindcss-windows-x64.exe |
The Integration
| The ecosystem | The mechanism |
|---|---|
| The Go | The Makefile |
| The Rust | The build.rs |
| The Rails | The tailwindcss-rails gem |
The Rails Tasks
| The task | The purpose |
|---|---|
tailwindcss:build | The one-off |
tailwindcss:watch | The development |
tailwindcss:clobber | The clean |
tailwindcss:install | The setup |
The @source Directives
| The ecosystem | The source |
|---|---|
| The Go | The **/*.go, the **/*.templ |
| The Rust | The **/*.rs |
| The Rails | The app/views/**/*.erb |
Best Practices
✅ Do This:
# Download the platform binary.
curl -sLO .../tailwindcss-linux-x64 # ✅
# chmod and rename.
chmod +x tailwindcss-linux-x64 && mv tailwindcss-linux-x64 tailwindcss # ✅
# Use the @source directive.
@source "./**/*.go"; # ✅
# Use the --watch in the development.
./tailwindcss -i input.css -o output.css --watch # ✅
# Use the --minify in the production.
./tailwindcss -i input.css -o output.css --minify # ✅
# Pin the version for the reproducibility.
curl -sLO .../download/v4.0.0/tailwindcss-linux-x64 # ✅
# Verify the checksum.
sha256sum tailwindcss # ✅
# Integrate with the Makefile or the build.rs.
build: css # ✅
❌ Don’t Do This:
# Don't use the latest in the production.
curl -sLO .../releases/latest/download/... # ⚠️ The unpinned
# Don't skip the checksum.
./tailwindcss # ⚠️ The integrity
# Don't forget the @source.
@import "tailwindcss"; # ❌ The no classes
# Don't use the Node.js-specific content array.
# The v4 uses the @source. # ❌
# Don't forget the rerun-if-changed in the build.rs.
// The cargo does not rebuild. # ❌
# Don't commit the output.
git add public/output.css # ❌ The generated
Common Pitfalls
| The pitfall | The reason | The fix |
|---|---|---|
| The classes not generated | No @source | Add the directive |
| The binary not executable | No chmod | Add the permission |
| The wrong platform | The wrong download | Use the platform file |
| The build slow | The full scan | Narrow the @source |
| The Cargo not rebuild | No rerun-if-changed | Add the directive |
| The Rails not rebuild | No tailwindcss:build | Add the task |
| The output committed | The generated | Use the .gitignore |
Real-World Examples
1. The Download
curl -sLO .../tailwindcss-linux-x64
2. The chmod
chmod +x tailwindcss
3. The Input CSS
@import "tailwindcss";
@source "./**/*.go";
4. The Basic Run
./tailwindcss -i input.css -o output.css
5. The Watch
./tailwindcss -i input.css -o output.css --watch
6. The Go Makefile
css:
./tailwindcss -i input.css -o output.css --minify
7. The Rust build.rs
Command::new("./tailwindcss").args(["-i", "input.css", "-o", "output.css"]).status();
8. The Rails Install
./bin/rails tailwindcss:install
9. The Rails Tasks
./bin/rails tailwindcss:build
10. The Complete Pattern
./tailwindcss -i input.css -o output.css --minify
Visual
The Standalone CLI
┌────────────────────────────────────────────────────────────┐
│ THE STANDALONE CLI │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The tailwindcss binary │ │
│ │ - The Rust engine │ │
│ │ - The Oxide, the Lightning CSS │ │
│ │ - The no Node.js │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The input.css │ │
│ │ @import "tailwindcss"; │ │
│ │ @source "./**/*.go"; │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The output.css │ │
│ │ The generated utilities │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
The Go Integration
┌────────────────────────────────────────────────────────────┐
│ THE GO INTEGRATION │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The Makefile │ │
│ │ build: css │ │
│ │ go build -o bin/server ./cmd/server │ │
│ │ │ │
│ │ css: │ │
│ │ ./tailwindcss -i input.css -o output.css │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The @source │ │
│ │ "./internal/**/*.go" │ │
│ │ "./templates/**/*.templ" │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The templ classes │ │
│ │ <div class="flex items-center gap-4"> │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
The Rust Integration
┌────────────────────────────────────────────────────────────┐
│ THE RUST INTEGRATION │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The build.rs │ │
│ │ fn main() { │ │
│ │ Command::new("./tailwindcss") │ │
│ │ .args(["-i", "input.css", │ │
│ │ "-o", "output.css", │ │
│ │ "--minify"]).status(); │ │
│ │ │ │
│ │ println!("cargo:rerun-if-changed=src"); │ │
│ │ } │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The view! macro │ │
│ │ <div class="flex items-center gap-4"> │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
The Rails Integration
┌────────────────────────────────────────────────────────────┐
│ THE RAILS INTEGRATION │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The Gemfile │ │
│ │ gem "tailwindcss-rails" │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The application.css │ │
│ │ @import "tailwindcss"; │ │
│ │ @source "../../../app/views/**/*.erb"; │ │
│ └────────────────────────┬─────────────────────────┘ │
│ │ │
│ v │
│ ┌──────────────────────────────────────────────────┐ │
│ │ The bin/dev │ │
│ │ web: bin/rails server │ │
│ │ css: bin/rails tailwindcss:watch │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
Summary
| The item | The value |
|---|---|
| The standalone CLI | The single binary |
| The engine | The Rust, the Oxide |
The -i | The input CSS |
The -o | The output CSS |
The --watch | The rebuild |
The --minify | The production |
The @source | The class scan |
| The Go | The Makefile |
| The Rust | The build.rs |
| The Rails | The tailwindcss-rails |
Key takeaways:
- The standalone CLI is the single binary. It bundles the Tailwind engine and runs without the Node.js, the npm, or the
node_modules. The distribution is the download, and the runtime is the none. - The download is the platform-specific. The releases cover the Linux, the macOS, and the Windows, on the x64 and the arm64. The checksum is the verification.
- The
@sourcedirective tells the binary where the class names are. The@source "./**/*.go"scans the Go files, and the@source "./templates/**/*.templ"scans the templ. The directive is the v4 replacement for thecontentarray. - The
-iand the-oare the input and the output. The-ireads the CSS with the@importand the@source, and the-owrites the generated. The--watchrebuilds on the change. - The
--minifyproduces the production output. The minified CSS is the smaller, and the CI should run the command. - The Go integration is the Makefile. The
make cssruns the binary, and themake builddepends on it. Themake css-watchis the development. - The Rust integration is the
build.rs. The script runs the binary at the Cargo build, and thererun-if-changedtells the Cargo to re-run on the change. - The Rails integration is the
tailwindcss-railsgem. The gem manages the binary, and the Rake tasks run the build. Theassets:precompileincludes thetailwindcss:build.
Remember: The standalone CLI is the Tailwind engine in the single binary. It runs without the Node.js, integrates with the Go, the Rust, and the Rails, and produces the same CSS as the npm package. The result is the CSS in the build pipeline the project already has, and the Node.js is the optional.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!