Assets

Stylesheets And Tailwind

Compile Tailwind CSS into embedded public stylesheets with lazy tailwind.

By Guillermo Alvarez - Published Updated

Stylesheet ownership

GoLazy serves CSS as ordinary public assets. Templates keep linking the public stylesheet through the asset helper:

{{stylesheet "/styles.css"}}

lazy tailwind is a development and build helper. It runs Tailwind separately from the Go process, writes the compiled stylesheet into public files, and then the normal GoLazy asset registry fingerprints and embeds that final CSS.

The framework runtime does not import Tailwind and does not require Node.js.

Default paths

For a conventional app, the default Tailwind source is:

app/styles/application.css

The default output is:

app/public/styles.css

For a root single-file app, the defaults are:

styles/application.css
public/styles.css

Override either path when needed:

lazy tailwind --input app/styles/site.css --output app/public/site.css

First run

Run the build from the application module root:

lazy tailwind

The command:

  • creates the input stylesheet when it is missing;
  • seeds that input from an existing public styles.css so current CSS is not discarded;
  • adds tailwindcss and @tailwindcss/cli to devDependencies when missing;
  • preserves existing package versions if either package already exists in dependencies or devDependencies;
  • runs the detected package manager install;
  • runs the Tailwind CLI to write the compiled public stylesheet.

The initial input starts with:

@import "tailwindcss";

Keep custom CSS in this source file. Treat the public output as generated build output that must be refreshed before Go builds embed it.

Default GoLazy apps do not require a tailwind.config.js file. Tailwind v4 can be configured from the stylesheet with CSS-first directives such as @theme, @custom-variant, and @source. Add a Tailwind config file only when an app needs JavaScript-based Tailwind configuration or plugins.

For class-driven dark mode, define the variant in the input stylesheet:

@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

Then opt the document into dark mode:

<html class="dark scheme-dark">

Templates can then use normal dark: utilities alongside their light-mode classes.

Watch mode

During UI work, run Tailwind in its own terminal:

lazy tailwind --watch

Run the application separately:

lazy

When Tailwind rewrites app/public/styles.css, lazy sees the public file change, rebuilds the temporary app binary, restarts the app, and reloads HTML browser pages. Production binaries embed the CSS bytes that exist at Go build time.

Source detection

Tailwind scans the application root for class-like tokens. GoLazy templates, Go files, and app-owned browser modules are ordinary source files from Tailwind's point of view.

Use complete class names in templates and code. Dynamically assembled class names are hard for Tailwind to detect. When a project needs explicit source paths or exclusions, add Tailwind @source directives to the input stylesheet.

Relationship to JavaScript

lazy tailwind is separate from lazy js:

  • lazy tailwind compiles CSS into a public stylesheet.
  • lazy js bundles manifest-declared JavaScript libraries, app modules from app/js, and writes an importmap.

Run the command that matches the files you changed. If both JavaScript libraries and Tailwind inputs changed, run both commands before tests and production builds.

Commit outputs

Commit:

app/styles/application.css
app/public/styles.css
package.json
package-lock.json

Also commit the matching lockfile if the project uses pnpm or yarn.

Do not commit node_modules.