Skip to content

brandnova/tailwind-build-pipeline

Repository files navigation

Tailwind Build Pipeline

A lightweight, framework-agnostic Tailwind CSS build pipeline with fully offline Font Awesome support, no CDNs, no runtime dependencies, no surprises in production.

Built to drop into the root of any backend project (Django, Go, PHP, or anything else that serves HTML), and get out of your way.


✨ Features

  • ✅ Tailwind CSS v3 with full tree-shaking (only the classes you use are included)
  • ✅ Offline Font Awesome v7, icons load without any internet connection
  • ✅ Works with any backend: Django, Go, PHP, plain HTML, you name it
  • ✅ One-command setup script (Linux/macOS and Windows)
  • ✅ Development watch mode + minified production builds
  • ✅ Isolated local test preview (no backend needed)
  • ✅ Clean, minimal pipeline, no webpack, no vite, no magic

📦 Project Structure

tailwind-build-pipeline/   ← lives in your project root (see note below)
 ┣ node_modules/
 ┣ src/
 ┃ ┗ styles.css            ← your CSS entry point
 ┣ .gitignore
 ┣ index.html              ← local preview + test page
 ┣ LICENSE
 ┣ package.json
 ┣ package-lock.json
 ┣ postcss.config.js
 ┣ README.md
 ┣ setup.sh                ← setup script for Linux/macOS
 ┣ setup.bat               ← setup script for Windows
 ┗ tailwind.config.js

And after setup, your static folder (one level up) will look like:

../static/
 ┣ css/
 ┃ ┗ tailwind.min.css      ← generated CSS, link this in your HTML
 ┗ webfonts/               ← Font Awesome icon fonts (copied by setup script)
     ┣ fa-brands-400.woff2
     ┣ fa-solid-900.woff2
     ┗ ... (all other font files)

📍 Where This Folder Lives

This pipeline is designed to live in the root of your project, as a sibling to your static folder. The build scripts output CSS to ../static/css/ and fonts go to ../static/webfonts/.

A typical Django project layout with this pipeline would look like:

my_django_project/
 ┣ tailwind-build-pipeline/   ← this repo goes here
 ┣ static/
 ┃ ┣ css/
 ┃ ┃ ┗ tailwind.min.css
 ┃ ┗ webfonts/
 ┣ templates/
 ┣ my_app/
 ┣ manage.py
 ┗ ...

A Go or PHP project would follow the same pattern, the pipeline sits next to wherever your static/ or public/ folder is.

Tip: You can rename the folder from tailwind-build-pipeline to anything you like, such as tw/ or assets/. Just keep it at the same level as your static folder.


🚀 Quick Start

Step 1 — Clone or copy into your project root

git clone https://github.com/brandnova/tailwind-build-pipeline.git
cd tailwind-build-pipeline

Or if you're adding it to an existing project, just drop the folder in next to your static/ directory.

Step 2 — Install dependencies

npm install

This installs Tailwind CSS, PostCSS, Autoprefixer, Font Awesome, and the typography plugin.

Step 3 — Run the setup script

Linux / macOS:

chmod +x setup.sh
bash setup.sh

or via npm:

npm run setup:lin

Windows:

setup.bat

or via npm:

npm run setup:win

What the setup script does

The setup script handles everything in one pass:

  1. Checks that node_modules is present (runs npm install if not)
  2. Creates ../static/css/ if it doesn't exist
  3. Creates ../static/webfonts/ if it doesn't exist
  4. Copies Font Awesome webfonts from node_modules/@fortawesome/fontawesome-free/webfonts/ into ../static/webfonts/
  5. Runs an initial Tailwind build against index.html so your CSS file exists before you start your server

After running it, your ../static/ folder will be ready to serve.

Step 4 — Link the CSS in your HTML

<link rel="stylesheet" href="/static/css/tailwind.min.css">

Or however your project handles static linking.

That's it. You're ready to build.


⚙️ Commands Reference

Command What it does
npm run setup:lin One-time setup: creates folders, copies webfonts, runs initial build
npm run setup:win Same as above, for Windows
npm run dev Watch mode: rebuilds CSS on every file change
npm run build Production build: minified, tree-shaken CSS
npm run test Local preview build: scans index.html only, outputs to ./dist/

👨‍💻 Development Workflow

During active development, run:

npm run dev

This watches your project files for changes and rebuilds ../static/css/tailwind.min.css automatically whenever you add, remove, or change Tailwind classes in your templates.

Important: Tailwind only knows about files you tell it about. Make sure your template paths are configured correctly in tailwind.config.js (see the Configuration section below). If a class isn't in any scanned file, it won't appear in the output CSS.


🏗️ Production Build

Before deploying, run:

npm run build

This generates a minified, fully tree-shaken CSS file, only the Tailwind classes you actually used are included. The output is a single file at ../static/css/tailwind.min.css.

Commit this file to your repository (or generate it as part of your CI/CD pipeline) so your server doesn't need Node.js to serve the styles.


🧪 Local Test Preview

To test the pipeline in isolation, without running a backend at all:

npm run test

This:

  • Scans index.html for Tailwind classes and Font Awesome icons
  • Generates a minimal CSS file at ./dist/tailwind.min.css
  • Copies index.html into ./dist/index.html

Open ./dist/index.html directly in your browser. If the button is blue and the icons render, everything is working.

(Note: Icons might not render because the webfonts folder does not exist in your ./dist directory. webfonts need to be in the same level as the parent folder containing your minified CSS file for fonts to work)


🔧 Configuration

Telling Tailwind where your templates are

Open tailwind.config.js and edit the content array to include your template files:

content: [
  "./index.html",
  "../templates/**/*.html",       // Django HTML templates
  "../**/*.php",                   // PHP files
  "../templates/**/*.html",        // Go templates
  "../src/**/*.{js,jsx,ts,tsx}",   // React components
],

Tailwind scans these files at build time and removes any class that doesn't appear in them. If a class is missing from your output CSS, it's almost always because the file containing it isn't listed here.

Adding custom colors, fonts, or spacing

Extend the theme in tailwind.config.js:

theme: {
  extend: {
    colors: {
      brand: {
        DEFAULT: '#4F46E5',
        light: '#818CF8',
        dark: '#3730A3',
      },
    },
    fontFamily: {
      display: ['"Playfair Display"', 'serif'],
    },
    spacing: {
      '18': '4.5rem',
      '128': '32rem',
    },
  },
},

Enabling dark mode

Dark mode is pre-configured to use the class strategy. Add the dark class to your root <html> element to activate it:

<html class="dark">

You can toggle it with a bit of JavaScript:

document.documentElement.classList.toggle('dark');

In your templates, use dark: variants:

<div class="bg-white text-gray-900 dark:bg-gray-900 dark:text-white">
  ...
</div>

🎨 Using Font Awesome Icons

Font Awesome is bundled from node_modules and served entirely offline. Use icons the same way you always have:

<!-- Solid icons -->
<i class="fas fa-lock"></i>
<i class="fas fa-check"></i>
<i class="fas fa-arrow-right"></i>

<!-- Regular icons -->
<i class="far fa-envelope"></i>

<!-- Brand icons -->
<i class="fab fa-github"></i>
<i class="fab fa-twitter"></i>

<!-- Sizing -->
<i class="fas fa-star text-xl"></i>
<i class="fas fa-star text-2xl text-yellow-400"></i>

Why offline? CDN-loaded Font Awesome can fail in restricted environments, slow connections, or offline-first PWAs. This pipeline bakes the fonts directly into your static folder so they always load, no internet required.

The webfonts dependency

Font Awesome's CSS references icon font files (.woff2, .ttf, etc.) using a relative path that resolves to ../webfonts/ relative to where the CSS file is served from.

Because your CSS is served from /static/css/tailwind.min.css, the fonts must be at /static/webfonts/, exactly where the setup script puts them.

If icons are rendering as blank squares or tofu characters, it almost always means the webfonts folder is missing or not being served. Double-check that:

  1. ../static/webfonts/ exists and contains .woff2 files
  2. Your backend is configured to serve the static/ directory
  3. You've run the setup script (or manually copied the fonts)

🌐 Backend-Specific Notes

Django

Make sure STATICFILES_DIRS or STATIC_ROOT is configured to pick up your static/ folder. In settings.py:

import os

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

During development, Django's runserver serves static files automatically. For production, run collectstatic and serve the files via your web server (Nginx, etc.) or a storage backend.

Go

Serve your static/ folder as a file server:

fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))

PHP / Plain HTML

Point your web server's document root at the parent directory and ensure static/ is accessible. Reference the CSS normally:

<link rel="stylesheet" href="/static/css/tailwind.min.css">

🔄 Re-running Setup (After npm install)

The setup script is safe to run multiple times. It will overwrite the webfonts with a fresh copy and regenerate the CSS. Run it again whenever you:

  • Clone the project onto a new machine
  • Delete and reinstall node_modules
  • Upgrade Font Awesome to a new version

⚠️ Important Notes

  • Do not use the Font Awesome CDN alongside this setup. The CDN version will conflict with the offline version. Remove any <link> to cdnjs.cloudflare.com or kit.fontawesome.com.
  • Commit ../static/css/tailwind.min.css to your repository so it's available on your server without needing Node.js installed.
  • Do not commit node_modules/, it's gitignored. Anyone cloning the project runs npm install then bash setup.sh.
  • The dist/ folder generated by npm run test is also gitignored. It's for local previewing only.
  • If you rename the tailwind-build-pipeline folder, the relative paths (../static/) still resolve correctly as long as it remains a direct sibling of your static/ folder.

📁 Example: After Full Setup

my_project/
 ┣ tailwind-build-pipeline/
 ┃ ┣ node_modules/
 ┃ ┣ src/
 ┃ ┃ ┗ styles.css
 ┃ ┣ dist/                  ← test builds (gitignored)
 ┃ ┣ .gitignore
 ┃ ┣ index.html
 ┃ ┣ package.json
 ┃ ┣ postcss.config.js
 ┃ ┣ setup.sh
 ┃ ┣ setup.bat
 ┃ ┗ tailwind.config.js
 ┣ static/
 ┃ ┣ css/
 ┃ ┃ ┗ tailwind.min.css     ← link this in your HTML
 ┃ ┗ webfonts/              ← Font Awesome fonts (auto-copied by setup)
 ┗ ... (your backend files)

📄 License

MIT, free for personal and commercial use. See LICENSE.

About

Framework-agnostic Tailwind CSS build pipeline with offline Font Awesome support. No bundlers, no CDNs

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors