cicadel

Style with Tailwind

Tailwind CSS is Cicadel’s default way to style components. New projects come with Tailwind v4 input, compiled CSS and a static route that serves it.

The server runs no Tailwind or Node process and needs no CDN. You can still use another CSS system: see Use another stylesheet system.

#Ask your agent

Text
Read https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md.
Style [component] using this application's existing Tailwind setup.
Use complete utility classes, keep labels and focus states accessible,
and run the matching Cicadel ui build and ui check commands.

#The authoring loop

In a generated project, after go mod tidy:

Terminal
# Once per development/CI machine; explicit network download.
go tool cicadel ui css install

# After editing .templ, Go class variants, or CSS input.
go tool cicadel ui build
go tool cicadel ui check --json
go test -race ./...
go build -trimpath -o bin/server .

In the framework checkout, use go run ./cmd/cicadel in place of go tool cicadel.

The starter ships with real compiler-generated CSS. Its first run works without downloading any CSS tool. Tests that compile CSS need the installed compiler, including the framework’s scaffold and docs tests. CI installs it first.

#Which toolchain

The toolchain pins Tailwind v4.3.3. Cicadel uses the upstream standalone CLI.

It does not use npm, PostCSS, a custom CSS compiler or a browser-time Tailwind script.

#Commands

CommandWhat it does
ui css installDownloads the pinned executable, verifies its SHA256 and installs it in the OS user cache. A valid installation is not downloaded again.
ui buildGenerates .templ Go, then builds CSS if ui.css.json exists.
ui generateGenerates markup only. Use it for component-only libraries.
ui css buildBuilds and minifies CSS only. Replaces the output atomically after success.
ui check --jsonChecks markup and configured CSS freshness, then compiles Go and tests without running them.
ui css checkRecompiles CSS and compares it, without changing the committed output.

What the commands never do:

  • build and check never download the Tailwind executable or add a Go dependency.
  • Package resolution uses read-only go list.
  • check uses temporary files and caches. It leaves generated source and CSS unchanged.

Go and CSS toolchains still need their normal local caches. Install Go dependencies with Go tooling before an offline build.

#Errors

ProblemDiagnostic
Compiler not installedUI_CSS_TOOL
Output is staleUI_CSS_STALE

Every failed command exits nonzero. Use the top-level ui check --json for machine diagnostics. The ui css ... commands print human-readable errors.

#Configuration: ui.css.json

A generated project has this ui.css.json:

JSON
{
  "version": "v4.3.3",
  "input": "project/styles/input.css",
  "output": "project/static/app.css",
  "packages": []
}
  • Paths are relative to the project or module directory where you run the command.
  • input and output must be different local .css paths.
  • Unknown fields, unsupported versions and invalid paths fail with an error.
  • Commands do not search parent directories.
  • The framework’s pinned version and the config version must match. Upgrading Tailwind is a reviewed framework and toolchain upgrade, never an implicit latest fetch.

#The input file

project/styles/input.css imports Tailwind with automatic detection turned off. It lists the project’s .templ and ordinary Go source patterns explicitly.

  • Generated *_templ.go files and tests are excluded. Stale generated classes and test payloads cannot leak into your CSS.
  • Source paths are relative to the input file, not your current directory.

See upstream source detection.

#Customize the theme

Tailwind v4 is configured in CSS. Add theme values to the input file:

CSS
@theme {
  --color-brand-600: #4f46e5;
}

Then write class="bg-brand-600 text-white" in .templ.

  • Keep the existing @import and @source declarations.
  • Local CSS imports resolve relative to the input file.
  • Do not use v3 @tailwind base directives. A tailwind.config.js is not loaded automatically.
  • The standalone build does not promise to bundle arbitrary npm plugins. Those need their own explicitly maintained build integration.
  • CSS is trusted authored source, never request input.

#Classes and variants

Write complete utilities with responsive and state variants:

templ
<button class="rounded-lg bg-indigo-600 px-4 py-2 text-white hover:bg-indigo-700 focus-visible:outline-2 sm:px-6">
    Save
</button>

Tailwind scans text. It does not run Go. So for dynamic variants, choose between complete literal strings in Go. Never build utility names from values such as "bg-" + color + "-600".

For a finite set of classes that cannot appear literally in scanned source, add an explicit CSS @source inline(...) declaration. Never safelist an unbounded set derived from user input.

Good to know

ui.Merge combines distinct class tokens. It is not tailwind-merge and does not decide which conflicting utility wins. The generated CSS cascade does. Prefer a typed variant that picks one spacing or color utility per state.

#Classes from installed packages

You register an app through Go imports and manifests as usual. Its classes are a separate step: add the exact Go import path of each package that contains Tailwind classes to packages.

JSON
{
  "version": "v4.3.3",
  "input": "project/styles/input.css",
  "output": "project/static/app.css",
  "packages": ["example.com/your-library/cards"]
}

That path is an example. For each entry, Cicadel:

  1. Resolves the path through the host’s selected Go module graph.
  2. Adds that directory as an explicit Tailwind source for the build.
  • This works with installed module-cache sources and local replacements.
  • No path into one user’s module cache is committed.
  • Scans include subdirectories, so point at the narrow component package.
  • packages does not install modules, activate apps or grant permissions.
  • A missing package fails with UI_CSS_PACKAGE. Install it with normal Go tooling first.

Library releases must include their class-bearing source or literal candidates. Tailwind cannot find utilities hidden in runtime-only data. Library authors are responsible for sensible source directory contents and dependency declarations.

#Serve the CSS

The starter publishes project/static/ as the project app’s App.Static files.

  1. The home handler resolves app.css to its content-hashed URL with static.URL(r.Context(), "project", "app.css").
  2. It passes the URL to layout.Page through the optional Props.Stylesheet.
  3. layout.Page emits a contextually escaped <link rel="stylesheet">.

See static files for caching and CDN collection.

The renderer and layout never insert CSS into other applications on their own. Existing pages keep their current stylesheet.

#Production

  • Commit CSS input, config and generated CSS together with the generated component Go.
  • Run ui check before the production build.
  • After UI changes, run ui build, then restart or rebuild the Go server to refresh embedded assets.
  • There is no HMR or watch server, and no CSS compilation at runtime in production.
  • To serve the CSS from a CDN, set CICADEL_STATIC_URL and upload the output of go run manage.go collectstatic DIR.

Tailwind v4 targets modern browsers. Use the upstream compatibility guidance to choose browser support. This integration verifies generated CSS and its HTTP delivery, not pixel-identical rendering across browser engines.

#Use another stylesheet system

  1. Remove ui.css.json.
  2. Replace project/static/app.css with your own stylesheet or build output.
  3. Keep or change the explicit stylesheet link.

ui build and ui check then handle markup only. Do not leave a Tailwind config pointing at output that a different compiler maintains.

#Add Tailwind to an existing project

  1. Add ui.css.json.
  2. Add an input file that imports Tailwind with explicit source directories.
  3. Choose an output location owned by your static pipeline.
  4. Add the stylesheet link.
  5. Install the tool, then run ui build and ui check.
  6. Verify that the asset route serves the CSS.

Upgrading Cicadel does not restyle existing apps.

Type to search this version.