Files
orion/docs/frontend/tailwind-css.md
Samir Boulahtit d648c921b7
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
docs: add consolidated dev URL reference and migrate /shop to /storefront
- Add Development URL Quick Reference section to url-routing overview
  with all login URLs, entry points, and full examples
- Replace /shop/ path segments with /storefront/ across 50 docs files
- Update file references: shop_pages.py → storefront_pages.py,
  templates/shop/ → templates/storefront/, api/v1/shop/ → api/v1/storefront/
- Preserve domain references (orion.shop) and /store/ staff dashboard paths
- Archive docs left unchanged (historical)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:23:44 +01:00

6.8 KiB

Tailwind CSS Build Guide

Version: 2.0 Last Updated: December 2024 Audience: Frontend Developers


Overview

The platform uses Tailwind CSS v4 with the Standalone CLI - no Node.js required. Each frontend (admin, store, shop, platform) has its own dedicated CSS configuration.


Architecture

How It Works

Tailwind Standalone CLI (single binary, no npm)
    │
    ├── static/admin/css/tailwind.css     → tailwind.output.css (Admin)
    ├── static/store/css/tailwind.css    → tailwind.output.css (Store)
    ├── static/storefront/css/tailwind.css      → tailwind.output.css (Shop)
    └── static/public/css/tailwind.css  → tailwind.output.css (Platform)

Key Files

File Purpose
~/.local/bin/tailwindcss Standalone CLI binary (v4.x)
static/*/css/tailwind.css CSS-first source configuration
static/*/css/tailwind.output.css Compiled output (do not edit)

Template Loading

Each frontend loads its own CSS:

<!-- Admin -->
<link rel="stylesheet" href="{{ url_for('static', path='admin/css/tailwind.output.css') }}" />

<!-- Store -->
<link rel="stylesheet" href="{{ url_for('static', path='store/css/tailwind.output.css') }}" />

<!-- Shop -->
<link rel="stylesheet" href="{{ url_for('static', path='shop/css/tailwind.output.css') }}" />

<!-- Platform -->
<link rel="stylesheet" href="{{ url_for('static', path='platform/css/tailwind.output.css') }}" />

CSS-First Configuration (Tailwind v4)

Tailwind v4 uses CSS-first configuration instead of tailwind.config.js. All customization happens directly in CSS files.

Source File Structure

/* static/admin/css/tailwind.css */

/* Import Tailwind */
@import "tailwindcss";

/* Content sources for tree-shaking */
@source "../../../app/templates/admin/**/*.html";
@source "../../js/**/*.js";

/* Custom theme (colors, fonts, spacing) */
@theme {
  --color-gray-50: #f9fafb;
  --color-gray-900: #121317;
  --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
}

/* Dark mode variant */
@variant dark (&:where(.dark, .dark *));

/* Custom utilities */
@layer utilities {
  .shadow-outline-purple {
    box-shadow: 0 0 0 3px hsla(262, 97%, 81%, 0.45);
  }
}

/* Custom components */
@layer components {
  .form-input { ... }
  .btn-primary { ... }
}

Key Directives

Directive Purpose Example
@import "tailwindcss" Import Tailwind base Required at top
@source Content paths for purging @source "../../../app/templates/**/*.html"
@theme Custom design tokens --color-purple-600: #7e3af2;
@variant Custom variants @variant dark (&:where(.dark, .dark *))
@layer utilities Custom utility classes .shadow-outline-*
@layer components Custom components .form-input, .btn-*

Custom Color Palette

All frontends share the same Windmill Dashboard color palette:

@theme {
  /* Gray (custom darker palette) */
  --color-gray-50: #f9fafb;
  --color-gray-100: #f4f5f7;
  --color-gray-200: #e5e7eb;
  --color-gray-300: #d5d6d7;
  --color-gray-400: #9e9e9e;
  --color-gray-500: #707275;
  --color-gray-600: #4c4f52;
  --color-gray-700: #24262d;
  --color-gray-800: #1a1c23;
  --color-gray-900: #121317;

  /* Purple (primary) */
  --color-purple-600: #7e3af2;

  /* Plus: red, orange, yellow, green, teal, blue, indigo, pink, cool-gray */
}

Building Tailwind CSS

Prerequisites

Install the standalone CLI (one-time setup):

make tailwind-install

Or manually:

curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64
chmod +x tailwindcss-linux-x64
mv tailwindcss-linux-x64 ~/.local/bin/tailwindcss

Development Build

Build all frontends (includes all classes, larger files):

make tailwind-dev

Production Build

Build with minification (smaller files):

make tailwind-build

Watch Mode

Watch for changes during development:

make tailwind-watch

Makefile Targets

Target Description
make tailwind-install Install Tailwind standalone CLI
make tailwind-dev Build all CSS (development)
make tailwind-build Build all CSS (production, minified)
make tailwind-watch Watch for changes

Dark Mode

The platform uses class-based dark mode with the .dark class on the <html> element:

<html :class="{ 'dark': dark }">
  <body class="bg-white dark:bg-gray-900">

Toggle dark mode with JavaScript:

document.documentElement.classList.toggle('dark');
localStorage.setItem('darkMode', dark);

Adding Custom Utilities

Add custom utilities in the source CSS file:

@layer utilities {
  .shadow-outline-purple {
    box-shadow: 0 0 0 3px hsla(262, 97%, 81%, 0.45);
  }

  .text-balance {
    text-wrap: balance;
  }
}

Adding Custom Components

Add reusable component classes:

@layer components {
  .form-input {
    @apply block w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm;
    @apply focus:border-purple-500 focus:ring-1 focus:ring-purple-500;
    @apply dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200;
  }

  .btn-primary {
    @apply px-4 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg;
    @apply hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500;
  }
}

Troubleshooting

Classes not appearing

  1. Check @source paths - Ensure your templates are in a scanned directory
  2. Check class exists - Tailwind v4 may have renamed some classes
  3. Rebuild CSS - Run make tailwind-dev after config changes

Dynamic classes in Alpine.js

Tailwind v4 uses JIT compilation and scans for complete class names. Dynamic classes work automatically if the full class name appears in your templates:

<!-- This works - full class names visible -->
<div :class="isActive ? 'bg-green-600' : 'bg-red-600'">

Class name changes (v2 → v4)

v2.x v4.x
overflow-ellipsis text-ellipsis
flex-grow-0 grow-0
flex-shrink-0 shrink-0

Best Practices

  1. Always rebuild after CSS changes

    make tailwind-dev
    
  2. Use production builds for deployment

    make tailwind-build
    
  3. Keep each frontend's CSS isolated - Don't cross-import between frontends

  4. Use @apply sparingly - Prefer utility classes in templates when possible

  5. Test in both light and dark modes