| name | design-foundations |
| description | Establish the design-system foundations of a full-stack Rails 8.1 app — the color/spacing/typography tokens, the theming strategy, dark mode, and the modular type & spacing scale — on top of the app's chosen CSS stack (Tailwind v4 CSS-first `@theme`, Tailwind v3 `tailwind.config.js`, daisyUI semantic themes, or plain CSS custom properties). Menu-driven with a Recommended default per menu; detects the Tailwind major and any installed UI kit first (v4 configures tokens in CSS via `@theme`, v3 in JS), and verifies the stylesheet builds and the tokens render. Start here before building components — every other design-* skill consumes these tokens. Web apps only; API-only apps have no design layer. |
| metadata | {"owner":"rails-design","status":"stable"} |
| user-invocable | true |
| argument-hint | [token-or-theme] |
design-foundations
Purpose
Owns the design-system primitives every other design-* skill builds on: the
tokens (color, spacing, typography, radius, shadow), the theming strategy
(single brand theme vs multi-theme), dark mode, and the modular scale for
type and spacing. It works within the CSS stack that ../rails-hotwire/ /
../rails-skills/rails-scaffold/ already chose — it does not pick Tailwind vs
anything else — and it adapts to the Tailwind major: v4 defines tokens in CSS
via @theme, v3 in tailwind.config.js. Start here; components, layout, forms, and
interactions all consume the tokens this skill establishes.
When to Apply
Use this skill when the task is:
- Defining or changing design tokens — brand colors, spacing scale, font
families, type scale, radius, shadows
- Setting up theming (one brand theme, or multiple switchable themes)
- Adding dark mode (class toggle, OS preference, or
data-theme)
- Establishing a typographic / spacing scale for visual rhythm
- Auditing color contrast at the token level before it propagates everywhere
Do not use this skill when the task is:
- Building actual components/buttons/cards from these tokens → read
../design-components/SKILL.md
- App shell / navbars / page layout → read
../design-layout-navigation/SKILL.md
- Choosing the CSS framework or asset pipeline for a new app → read
../rails-hotwire/SKILL.md (it owns the stack; this skill works within it)
- Per-component ARIA / focus / full WCAG audit → read
../design-accessibility/SKILL.md (this skill only sets contrast-safe tokens)
- Anything on an API-only app — there is no UI; stop and route to
../rails-skills/
Detect Before You Generate
grep -nE "api_only" config/application.rb
grep -E "tailwindcss-rails|tailwindcss|daisyui|bootstrap" Gemfile.lock package.json 2>/dev/null
grep -rolE "@import \"tailwindcss\"|@tailwind (base|utilities)" app/assets 2>/dev/null
ls tailwind.config.js tailwind.config.ts 2>/dev/null
grep -rnoE "@theme|@plugin \"daisyui\"" app/assets 2>/dev/null
find app/assets -name 'application*.css' -o -name 'application.tailwind.css' 2>/dev/null
- Detect the Tailwind major before touching tokens.
@import "tailwindcss" (and
no tailwind.config.js) → v4: tokens live in CSS under @theme. @tailwind base; + a tailwind.config.js → v3: tokens live in theme.extend in JS.
tailwindcss-rails ~> 4 ships v4. Don't assert one — read the entrypoint.
- If daisyUI is installed, its semantic theme tokens (
--color-primary, etc.) are
already your theming layer — extend them, don't fight them.
- If there's no Tailwind (plain CSS / Bootstrap), tokens go in
:root CSS custom
properties.
- Match the existing entrypoint filename —
tailwindcss-rails v4 uses
app/assets/tailwind/application.css; older setups use
app/assets/stylesheets/application.tailwind.css. Detect, don't guess.
Menu
Three menus, each via AskUserQuestion; the modern default marked Recommended.
Ask only what the detected stack leaves open.
Token & config model
| Option | One-line trade-off | Deep dive |
|---|
| Tailwind theme tokens (Recommended) | Tokens in @theme (v4) or theme.extend (v3); first-class utility classes, tree-shaken. The default when Tailwind is present. | tokens-tailwind-config.md |
| daisyUI semantic themes | Named semantic tokens (primary/base-100/…) + 35+ prebuilt themes; least CSS to write, opinionated palette. | theming-daisyui.md |
| Plain CSS custom properties | :root { --color-… }; framework-free, total control, no utility ergonomics. For non-Tailwind apps. | css-variables.md |
Dark mode
| Option | One-line trade-off | Deep dive |
|---|
| Class-based toggle (Recommended) | dark: variants + a dark class on <html>, toggled and persisted by a Stimulus controller. User-controllable, the common choice. | dark-mode.md |
| OS preference only | prefers-color-scheme; zero JS, but the user can't override the OS. | dark-mode.md |
daisyUI data-theme | Swap data-theme="dark"; integrates with daisyUI's theme system, ties you to it. | dark-mode.md |
Type & spacing scale
| Option | One-line trade-off | Deep dive |
|---|
| Tailwind default scale (Recommended) | The built-in modular type/spacing scale; battle-tested rhythm, nothing to maintain. | typography-scale.md |
| Custom modular scale | Define your own ratio-based scale as tokens; bespoke rhythm, more to own. | typography-scale.md |
Decision Flow
- Token model follows the stack. Tailwind present → Tailwind theme tokens
(in
@theme for v4, theme.extend for v3). daisyUI present → lean on its
semantic themes and only add brand overrides. No Tailwind → CSS custom
properties in :root.
- Dark mode: default to the class-based toggle — users expect to control it,
and it persists across visits. Use OS-only when you want zero JS and no toggle.
Use
data-theme when daisyUI already owns theming.
- Scale: keep the Tailwind default scale unless a brand demands a specific
ratio — a custom scale is real ongoing maintenance for marginal gain.
- Set contrast-safe tokens once. Pick color pairs that pass WCAG AA at the token
level so every component downstream inherits accessible defaults — see
color-and-contrast.md; the full audit lives in
../design-accessibility/.
Problem → Reference
Verify
Tokens are only "set up" once the stylesheet builds and the values actually render:
bin/rails tailwindcss:build 2>/dev/null || bin/rails assets:precompile
grep -rqE "(--color-brand|text-brand|--brand)" app/assets/builds public/assets 2>/dev/null \
&& echo "✓ token present in compiled CSS"
bin/rails server -d && sleep 3
curl -fsS localhost:3000/ -o /dev/null -w "root=%{http_code}\n"
kill "$(cat tmp/pids/server.pid)"
Open the app and confirm: brand colors render, dark mode flips, and the type scale
reads with clear hierarchy. Then route to ../design-components/ to build components
from these tokens, and ../design-accessibility/ for the full contrast/ARIA audit.