| name | frontend-design |
| description | Aesthetic and convention guide for editing AI Atelie's own chrome — the editor, canvas frame, toolbars, sidebars, dialogs, settings, projects screen. Use whenever the diff touches `web/src/` (especially `*.module.css`, `index.css`, `styles/themes.css`, `lib/theme.ts`) or any user-facing component on the host app. Opts into the canonical craft rulebook at `atelier/` and layers the host-app-specific posture (two-axis theme×design system, warm-cream + Claude rust, restraint over flourish) on top. NOT for user-generated designs inside the canvas — those use the product skill at `skills/frontend-design/`. |
| craft | {"requires":["typography","color","anti-ai-slop","state-coverage","animation-discipline","accessibility-baseline"]} |
frontend-design (dev-time)
A contributor workflow for editing AI Atelie's own chrome — the parts of the host app a user sees regardless of what they're designing inside the canvas. Dev-time only; does not load into adapter sessions spawned by the editor.
If you're editing the canvas frame, the chat sidebar, the toolbar, the projects screen, the settings dialog, or any CSS module under web/src/, this skill applies. If you're editing a SKILL.md under skills/<name>/ that governs user-generated designs, this skill does NOT apply — that's the product skill, a different surface.
Read the atelier first
atelier/ is AI Atelie's canonical craft rulebook. Tokens in web/src/index.css decide what the brand looks like; the atelier files decide how a competent designer uses them.
The frontmatter craft.requires declares which sections this skill depends on. Pull these into context before touching chrome — they are the floor, not aspiration:
| Atelier file | What it covers | When you need it |
|---|
| atelier/typography.md | Type scale, line height, ALL CAPS tracking floor (≥0.06em), font pairing, three-weight system, line length | Any text on screen |
| atelier/color.md | Palette structure (70-90% neutrals / 5-10% brand / 0-5% semantic / <1% effect), ≤2 visible --brand uses per screen, ink scale by job, contrast minimums, semantic naming | Any styled surface |
| atelier/anti-ai-slop.md | The 7 P0 cardinal sins (lint-enforced): no Tailwind indigo, no two-stop trust gradients, no emoji-as-icons, no hardcoded display fonts, no rounded-card-with-left-border, no invented metrics, no filler copy. Plus soft tells and a chrome-PR checklist | Every chrome PR |
| atelier/state-coverage.md | Empty / loading / error states for any data-fetching surface | Anything that lists, fetches, or paginates |
| atelier/animation-discipline.md | Motion tokens, prefers-reduced-motion, when motion earns its place | Anything that animates |
| atelier/accessibility-baseline.md | Contrast, keyboard, focus rings, ARIA on chrome | Any interactive control |
If a question comes up that one of those files answers, check there first before improvising. Don't duplicate the rules into this skill — the atelier is the source of truth.
Chrome posture (what atelier doesn't already cover)
The chrome serves the canvas. Restraint over flourish. Maximalism belongs inside the canvas (user-generated designs); the toolbars surrounding it should recede.
Three things shape every chrome decision in AI Atelie that the universal atelier rules don't address:
Two axes drive the chrome. Defined in web/src/lib/theme.ts.
theme — system | light | dark | retro — brightness preference.
design — null | violet | mono | paper | espresso | coral | ember | vinyl | scarlet | glacier | phosphor | hornet | prism — opt-in decorative overlay; 12 palettes generated by tools/gen-themes.mjs.
- Both apply through one
data-theme attribute on <html>. Picking a theme clears the design (so "click → see change" stays honest).
Every chrome edit must work across the canonical (theme + design = null) AND across Dark and Retro themes; spot-check Violet + Mono designs as a smoke test.
Canonical default look. Warm cream surface (--app-bg: #faf9f5) + Claude rust accent (--brand: #c96442) + dense alpha ink scale (25+ stops from --ink-02 through --ink-92). The 12 designs are decoration the user opts into — build for the canonical first, verify in overlays after.
Six fonts loaded globally. index.css:11 imports JetBrains Mono / Archivo / Syne / Noto Sans JP / Antonio / Instrument Serif. Use them with intent — mono for code, paths, kbd hints; display for hero or section openers; italic serif for editorial flourish. Don't add a font import inside a single component — extend the global @import with a documented reason.
Hard rules specific to chrome — and what to do INSTEAD
These complement atelier/anti-ai-slop.md, which has the universal lint-enforced rules. Below are the rules specific to AI Atelie's two-axis chrome.
- Don't ship chrome that's only verified in default theme. A token that exists in only one theme silently breaks when the user switches. INSTEAD: after implementing, toggle through Light → Dark → Retro using the theme picker (foot pill or Settings → Appearance). Spot-check Violet + Mono designs. If anything breaks, the tokens picked were too narrow.
- Don't add a token at
:root without mirroring it in every override block. INSTEAD: edit :root, then [data-theme="dark"] and [data-theme="retro"] (both at the bottom of index.css), then either regenerate the 12 designs via tools/gen-themes.mjs or hand-edit styles/themes.css for each. A token that exists in only one theme is a bug.
- Don't write
[data-theme="dark"] .myComponent { ... } overrides inside a component's CSS module. That bypasses the token layer. INSTEAD: add the token at :root with one default value, then a different value per theme override block. The component reads var(--token) once. (This is also called out in atelier/anti-ai-slop.md as a soft tell.)
- Don't introduce a new design or theme axis on a feature PR. INSTEAD: scope theme system changes to dedicated PRs (mirror #80 for the prior 12-palette landing). Decoration drift on feature PRs erodes the system.
- Don't reach for a font import inside a component. INSTEAD: pick the existing role from the six globally loaded faces. If a new role genuinely is missing, extend
@import in index.css and explain the new role in the commit body.
When to invoke
- Any diff that adds, modifies, or removes CSS in
web/src/.
- Any diff that adds or modifies a TSX/JSX component with visible UI.
- Any change to
web/src/lib/theme.ts or the generated styles/themes.css.
- Before creating a new component — read the closest neighbour's module first.
- When the user says "make this prettier", "the editor looks broken in Dark", "match the design language", or "ship a UI polish pass".
Skip when:
- The change is api-only, mcp-only, or build-config-only with no UI surface.
- The diff touches only
web/projects/ (user data, not chrome).
- The diff is to
skills/<name>/SKILL.md — that's the product skill, a different scope.
Workflow
- Read the atelier sections in
craft.requires at the top of this file. Open them in your context before editing — the loader for the craft field is not yet implemented, so the agent must pull them in directly.
- Read the neighbour first. Open the closest sibling component's
*.module.css and adopt its conventions before inventing new ones.
- Read the relevant section of index.css. The annotation comments are part of the design-system docs.
- Implement using only tokens. No literals, no per-component fonts, no inline color styles.
- Run
bun run dev. Vite binds localhost/IPv6 (not 127.0.0.1); the live-preview process auto-restarts on :5173 if killed, so don't fight it.
- Verify the canonical theme works via
.claude/skills/verify-with-playwright/SKILL.md.
- Spot-check the other axes. In the running browser, open Settings, switch theme through Light → Dark → Retro, then turn on Violet and Mono designs. Fix at the token layer, not the component, if anything breaks.
- Commit via
.claude/skills/semantic-commit/SKILL.md with scope=web.
When this skill is wrong
This skill encodes the conventions in place when it was written. If the user is intentionally evolving the system — landing a new design overlay, refactoring the token layer, replacing the font stack, expanding the atelier — the rules describe the current state, not a constraint on the future. Follow the user's lead, then update this skill (and the relevant atelier file, if changed) in the same PR so the next contributor sees the new ground truth.
See also