---
name: scaffold-theme
description: Bootstrap src/index.css with Tailwind v4 + Shoelace token overrides + design tokens from the PRD theme slice (or SmartStack defaults). Idempotent overwrite.
group: D
phase: devFrontend
kind: main
section_label: 'SCAFFOLD-THEME (CSS variables + Shoelace tokens for the generated client app)'
allowed-tools: [Read, Write, Edit, Glob, Grep]
---

# scaffold-theme — Theme bootstrap for the generated client app

## Context

You are scaffolding the **theme entry point** of a SmartStack-generated React + Vite + Tailwind v4 + Shoelace client app. Without this file, every component renders with browser defaults: no token-based palette, no dark-mode contract, no Shoelace `--sl-color-*` overrides — the UI looks unbranded and inconsistent across components.

This skill is invoked by `ba-develop` Phase 3, sub-phase 3.0 (theme + layout), BEFORE any pages are scaffolded — so pages can reference design tokens directly via `var(--color-*)` Tailwind classes (e.g. `bg-[var(--color-accent-500)]`).

## Invocation

```
npx --prefer-offline tsx skills/development/frontend/theme/cli/scaffold-theme/index.ts \
  --spec '{"projectPath":"<abs>","appCode":"<app>","prdSlice":<theme-slice-or-null>}'
```

`--spec` is a JSON object:

| Field | Type | Required | Notes |
|---|---|---|---|
| `projectPath` | string | yes | Absolute path to the web root (holds `src/`). |
| `appCode` | string | yes | Lowercased app code (used for branding label only). |
| `prdSlice` | object \| null | no | Optional theme tokens from the PRD. Falls back to SmartStack defaults. |
| `force` | boolean | no | Overwrite even when content matches. Default `false` (no-op when content unchanged). |
| `useShoelace` | boolean | no | Emit the `@shoelace-style/shoelace` light/dark theme imports in `src/index.css`. Default `false` — set to `true` only when the project lists the package as a dependency. |

## What it produces

- **`src/index.css`** — Tailwind v4 entry + Shoelace `--sl-color-*` overrides + design tokens (`--color-accent-*`, `--bg-app`, `--success-*`, `--warning-*`, `--error-*`, `--info-*`) — all rooted on `:root` and overridden under `.dark` for dark-mode contract.

## Idempotency contract

- **Re-run safe.** If the existing `src/index.css` has the **exact same content** as what would be generated, the CLI returns `filesCreated: []` and exits 0 (no-op).
- **Overwrite on drift.** If the file exists but content has drifted (manual edits or stale generation), the file is overwritten unless the user marks it with `/* @customised */` at the top — that marker tells the scaffolder to preserve the file.
- The generated file always carries a `/* AUTO-GENERATED — re-run scaffold-theme to refresh. Add @customised at top to opt out. */` header so re-runs are predictable.

## When NOT to use

- Customising specific tokens for a single page → put overrides in a sibling `.css` next to the page, not in `src/index.css`.
- Adding new design tokens that aren't in the PRD theme slice → extend the PRD theme schema first, then re-run; ad-hoc additions in `src/index.css` are wiped on the next re-run.
