
Ui Design
- 1.6k installs
- 21 repo stars
- Updated August 3, 2026
- starchild-ai-agent/official-skills
ui-design is an agent skill that agent skill for ui-design workflows documented in skill.md.
About
ui-design is an agent skill from starchild-ai-agent/official-skills that agent skill for ui-design workflows documented in skill.md. # UI Design Skill This skill is the **single entry point** for visual work. Use it for any user-facing HTML/CSS/JS output: landing pages, dashboards, product UI, internal tools, and portfolio pages. --- ## Step 1 — Pick the build track Choose deliberately before coding: - **Track A (hand-built)**: static preview, vanilla HTML/CSS/JS, quick cu Developers invoke ui-design during operate/infra work for cloud & infrastructure tasks. The skill documents triggers, prerequisites, and step-by-step workflows grounded in SKILL.md. Compatible with Claude Code, Cursor, and Codex agent runtimes that load marketplace skills. Review the Security Audits panel on this listing before installing in production environments.
- This skill is the **single entry point** for visual work.
- Use it for any user-facing HTML/CSS/JS output: landing pages, dashboards, product UI, internal tools, and portfolio page
- Step 1 — Pick the build track
- Choose deliberately before coding:
- Track A (hand-built)**: static preview, vanilla HTML/CSS/JS, quick custom pages
Ui Design by the numbers
- 1,645 all-time installs (skills.sh)
- +56 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #254 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
ui-design capabilities & compatibility
- Capabilities
- this skill is the **single entry point** for vis · use it for any user facing html/css/js output: l · step 1 — pick the build track · choose deliberately before coding: · track a (hand built)**: static preview, vanilla
- Use cases
- orchestration
What ui-design says it does
This skill is the **single entry point** for visual work.
Use it for any user-facing HTML/CSS/JS output: landing pages, dashboards, product UI, internal tools, and portfolio pages.
- **Track A (hand-built)**: static preview, vanilla HTML/CSS/JS, quick custom pages
npx skills add https://github.com/starchild-ai-agent/official-skills --skill ui-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.6k |
|---|---|
| repo stars | ★ 21 |
| Last updated | August 3, 2026 |
| Repository | starchild-ai-agent/official-skills ↗ |
What it does
Agent skill for ui-design workflows documented in SKILL.md.
Who is it for?
Developers working on cloud & infrastructure during operate tasks.
Skip if: Tasks outside Cloud & Infrastructure scope described in SKILL.md.
When should I use this skill?
Agent skill for ui-design workflows documented in SKILL.md.
What you get
Completed cloud & infrastructure workflow aligned with SKILL.md steps.
- responsive UI implementation
- accessibility-checked interface
- themed component layout
By the numbers
- ui-design version 1.2.0
- Integrates taste-skill overlay inside ui-design main trunk workflow
Files
UI Design Skill
This skill is the single entry point for visual work.
Use it for any user-facing HTML/CSS/JS output: landing pages, dashboards, product UI, internal tools, and portfolio pages.
---
Step 1 — Pick the build track
Choose deliberately before coding:
- Track A (hand-built): static preview, vanilla HTML/CSS/JS, quick custom pages
- Track B (component library): React/Vite/Next project using shadcn/ui, HeroUI, or coss ui
Track decision and component-library strategy are always owned by ui-design.
---
Step 2 — Taste Overlay Contract (mandatory)
Inside ui-design workflow, invoke taste-skill for exactly these 3 style blocks:
1. Brief Inference 2. Design Dials (layout variance / motion intensity / visual density) 3. Anti-slop hard rules
Boundary
ui-designkeeps ownership of engineering quality and delivery.taste-skillprovides style direction and anti-template taste constraints.
This avoids overlap with ui-design’s engineering references (component libraries, a11y, preview, data dashboard implementation).
---
Step 3 — Runtime order (use this every time)
1. Use ui-design to select Track A/B. 2. Run taste Brief Inference before writing UI code. 3. Apply taste Design Dials to set style direction. 4. For any interactive page, define a motion plan first (what animates, why, frequency, duration, easing, reduced-motion path). 5. Implement with ui-design engineering rules (a11y/theme/responsive/component strategy/performance). 6. Run taste Anti-slop check as final style gate before delivery.
One sentence summary:
- taste decides style character
- ui-design guarantees robust implementation
Hard rule: if the page has interactions, motion design is mandatory (at least tactile feedback + state transition feedback). Static-looking interaction states are treated as incomplete UI.
---
Step 4 — Conflict arbitration
When rules overlap:
- Style conflict → taste-skill wins
- Engineering safety/correctness conflict → ui-design wins
Engineering safety includes: accessibility, responsive stability, interaction reliability, runtime correctness, and performance constraints.
---
Step 5 — Where to read/download taste-skill (no local mirror)
Do not maintain a local mirror or version-stamp file.
Always read/update taste rules directly from GitHub:
- Repo:
https://github.com/Leonxlnx/taste-skill - Main skill to consult:
https://github.com/Leonxlnx/taste-skill/blob/main/skills/taste-skill/SKILL.md - Raw download URL:
https://raw.githubusercontent.com/Leonxlnx/taste-skill/main/skills/taste-skill/SKILL.md - Full skill package directory:
https://github.com/Leonxlnx/taste-skill/tree/main/skills
When taste-skill updates, re-check the GitHub source directly and apply needed changes in the ui-design overlay contract.
---
Engineering references
| File | Purpose |
|---|---|
references/design-process.md | Engineering quality gate (a11y/theme/responsive/interaction/runtime checklist) |
references/component-libraries.md | shadcn/ui · HeroUI · coss ui selection + lookup workflow |
references/animations.md | Motion implementation standards, interactive-motion requirements (integrated with emil-design-eng decision framework), and GSAP usage notes |
references/charts.md | Chart.js/ECharts implementation patterns |
references/dashboards.md | Data sourcing, real-time updates, dashboard structure, performance |
| taste-skill GitHub source | Read style rules directly from GitHub: https://github.com/Leonxlnx/taste-skill/tree/main/skills |
Aesthetic Direction Reference
Color Strategy: Choose a Level First
Before picking any colors, decide your strategy level. This determines how much color your design uses.
| Level | Description | When to Use | Example |
|---|---|---|---|
| Restrained | Near-monochrome. One accent used sparingly (links, active states, one CTA). Surface does the work. | Data tools, documentation, professional dashboards | Notion, Linear, Stripe Docs |
| Committed | One accent color used boldly — in headers, illustrations, key UI elements. Still disciplined. | SaaS products, portfolios, marketing pages | Vercel, Figma, Raycast |
| Full palette | 3-5 harmonious colors, each with a role. Requires careful balance. | Creative tools, consumer apps, editorial | Slack, Notion (with databases), Pitch |
| Drenched | Color IS the brand. Saturated backgrounds, colored surfaces, bold combinations. | Fashion, entertainment, gaming, art | Spotify, Discord, Gumroad |
The strategy level should match your Design Read. A clinical developer tool at "Drenched" will feel wrong. A gaming landing page at "Restrained" will feel lifeless.
---
How to Build a Color Palette From Scratch
Do NOT copy a preset palette. Build one from your design direction.
Step 1: Pick a Base Surface Color
Start with the background — the most impactful decision.
- Light surfaces: Pure white or a very subtle tint. To tint, add 1-3% of your accent hue to white. Avoid warm neutrals (cream, beige, sand) unless the Design Read explicitly calls for warmth.
- Dark surfaces: Near-black, not pure
#000. Add 2-5% of your accent hue for depth. Write a "scene sentence" first — what physical space does this dark mode evoke? See the Dark Surface Tint Guide below for scene-to-color mapping. NEVER use the default#0a-#0fblue-black range. - Colored surfaces: A saturated or muted color AS the background (deep navy, forest green, dusty rose). This is bold — commit fully.
Step 2: Derive Your Neutral Scale
From your base surface, create 3-5 shades for hierarchy. Name them by purpose, not appearance:
- Primary surface → your base background
- Secondary surface → slightly offset for sections, sidebars, alternating areas
- Elevated surface → cards, containers, floating elements
- Interactive surface → hover and active states
For dark themes: each step adds ~5-10% lightness. You need MORE levels than light themes (at least 4). For light themes: each step subtracts ~2-5% lightness.
Choose your own CSS custom property names that make sense for your project. Don't use the same naming scheme every time.
Step 3: Choose Your Accent Color
Pick a single accent color that:
- Has meaning for the content OR deliberately subverts expectations
- Contrasts well against your surface (test at 4.5:1 ratio)
- Is NOT the AI default (avoid generic blue and AI purple)
- Is NOT the "anti-AI-default" default (teal/emerald have become the new AI purple — vary further)
- Is NOT in the banned accent list (see Banned Color Reference below)
Derive a hover state by adjusting lightness ±10%.
Subversion principle: If the topic strongly implies a color (blue for finance, green for health, red for food), consider whether a less obvious choice would be more distinctive. A finance dashboard in warm amber or deep indigo can be more memorable than yet another blue one.
Step 4: Set Text Colors
Create 3 levels of text hierarchy:
- Primary text → high contrast against surface (≥ 7:1 for body text)
- Secondary text → medium contrast (≥ 4.5:1) for supporting text
- Muted text → lower contrast (≥ 3:1) for captions, timestamps, labels
For dark themes: white → light gray → medium gray For light themes: near-black → dark gray → medium gray
Step 5: Define Semantic Colors
Always include functional colors regardless of aesthetic:
- A success green that works on your surface
- A warning amber that works on your surface
- An error red that works on your surface
- A subtle border/separator color
Step 6: Assemble as CSS Custom Properties
Define all colors in :root using semantic names. Choose names that reflect your project's vocabulary — there is no single correct naming convention. The goal is clarity and consistency within the project, not conformity across projects.
For dark mode: use the same property names with different values under a theme selector ([data-theme="dark"], .dark, or prefers-color-scheme: dark).
---
How to Choose Typography
Step 1: Match Font Character to Content
| Content Type | Font Character | Why |
|---|---|---|
| Data/analytics dashboard | Geometric sans or monospace | Precision, clarity, tabular alignment |
| Creative portfolio | Distinctive display font | Personality, memorability |
| Professional tool | Clean humanist sans | Readability, trust |
| Editorial/content | Serif or humanist sans | Reading comfort, authority |
| Developer tool | Monospace | Code familiarity, alignment |
| Playful/social | Rounded sans | Friendliness, approachability |
Step 2: Browse Google Fonts with Intent
Go to fonts.google.com and filter by:
- Category (sans-serif, serif, monospace, display)
- Number of styles (pick fonts with 4+ weights for flexibility)
- Trending / recently updated (for freshness)
The anti-repetition rule: If you've used a font in a recent generation, pick a different one. Also avoid converging on the same "safe alternative" fonts (Space Grotesk, DM Sans, Outfit, Plus Jakarta Sans, Manrope) — these have become AI anti-defaults. When a Style Preset is active, use the preset's specified font instead of choosing your own.
Step 3: Set Up the Type Scale
Build a consistent type scale. Use clamp() for responsive heading sizes. Key constraints:
| Level | Size Range | Weight | Line Height | Letter Spacing |
|---|---|---|---|---|
| h1 | Responsive, max ~3rem | 600-800 | 1.05-1.15 | -0.02em to -0.03em |
| h2 | Responsive, max ~2rem | 600 | 1.15-1.25 | -0.01em |
| h3 | Responsive, max ~1.25rem | 500-600 | 1.25-1.35 | normal |
| Body | 16px minimum | 400 | 1.5-1.6 | normal |
| Small | 14px | 400-500 | 1.4 | normal |
| Caption | 12px | 400-500 | 1.3 | 0.01em |
Adjust the specific values to match your design direction — airy designs use larger sizes with more spacing, dense designs use tighter scales. Don't use the exact same values every time.
Real-World Typography References (from 73 major brands)
These are actual values extracted from production websites. Use them as calibration points, not templates. Organized by aesthetic category.
Minimal / Developer Platform
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| Apple | 56px | 600 | -0.28px | 17px | 1.47 | 0 |
| Vercel | 48px | 600 | -2.4px | 16px | 1.5 | 0 |
| Linear | 56px | 500 | -3px | 16px | 1.5 | 0 |
| Expo | 64px | 600 | -1.92px | 16px | 1.5 | 0 |
| Ollama | 36px | 500 | 0 | 16px | 1.5 | 0 |
Editorial / Magazine
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| ElevenLabs | 64px | 300 | -1.92px | 16px | 1.5 | +0.16px |
| Mistral | 84px | 400 | -1.5px | 16px | 1.55 | 0 |
| Resend | 96px | 400 | -0.96px | 16px | 1.5 | -0.8px |
| Wired | 64px | 400 | -0.5px | 19px (serif) | 1.47 | +0.108px |
| Replicate | 72px | 700 | -1.8px | 16px | 1.5 | 0 |
Enterprise / Infrastructure
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| IBM | 76px | 300 | -0.5px | 16px | 1.5 | +0.16px |
| HashiCorp | 80px | 700 | -2.5px | 16px | 1.5 | 0 |
| HP | 72px | 500 | 0 | 16px | 1.38 | 0 |
| NVIDIA | 48px | 700 | 0 | 16px | 1.5 | 0 |
| MongoDB | 72px | 500 | -1.5px | 16px | 1.55 | 0 |
Consumer / Commerce
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| Airbnb | 28px | 700 | 0 | 16px | 1.5 | 0 |
| Uber | 52px | 700 | 0 | 16px | 1.5 | 0 |
| Meta | 64px | 500 | 0 | 16px | 1.5 | -0.16px |
| Shopify | 96px | 330 | +2.4px | 16px | 1.5 | 0 |
| 70px | 600 | -1.2px | 16px | 1.4 | 0 | |
| Mastercard | 64px | 500 | -1.28px | 16px | 1.4 | 0 |
| Revolut | 136px | 500 | -2.72px | 16px | 1.5 | +0.24px |
Luxury / Automotive
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| Ferrari | 80px | 500 | -1.6px | 14px | 1.5 | 0 |
| Lamborghini | 120px | 400 | 0 | 16px | 1.5 | 0 |
| SpaceX | 80px | 700 | +1.6px | 16px | 1.5 | +0.32px |
| Renault | 56px | 700 | 0 | 16px | 1.4 | 0 |
AI / Developer Tools
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| MiniMax | 80px | 600 | -2px | 16px | 1.5 | 0 |
| Mintlify | 72px | 600 | -2px | 16px | 1.5 | 0 |
| Miro | 80px | 500 | -2px | 16px | 1.5 | 0 |
| Intercom | 72px | 500 | -2.0px | 16px | 1.5 | 0 |
| Sanity | 112px | 400 | -4.48px | 16px | 1.5 | 0 |
Entertainment / Gaming
| Brand | Display Size | Display Weight | Display Letter-Spacing | Body Size | Body LH | Body LS |
|---|---|---|---|---|---|---|
| PlayStation | 54px | 300 | -0.1px | 18px | 1.5 | +0.1px |
| The Verge | 107px | 900 | +1.07px | 16px | 1.6 | 0 |
| Vodafone | 144px | 800 | -1px | 18px | 1.56 | 0 |
| Superhuman | 64px | 540 | 0 | 16px | 1.5 | 0 |
Key insights from 73 brands: 1. 85% use negative letter-spacing on display — the range is -0.28px to -4.48px. AI skips this entirely. 2. Display weight 400-500 is the sweet spot — 45% of brands use this range. Only 15% use 700+. 3. Body line-height clusters at 1.5 — with 1.4-1.55 as the full range. 1.6+ is rare outside editorial. 4. Positive body letter-spacing is a premium signal — IBM +0.16px, ElevenLabs +0.16px, Revolut +0.24px, SpaceX +0.32px. 5. Display sizes go much larger than AI defaults — Vodafone 144px, Revolut 136px, Lamborghini 120px, Sanity 112px. AI rarely exceeds 64px.
Real-World Border-Radius References (from 73 major brands)
Sharp / Angular (0-4px)
| Brand | Buttons | Cards | Pills/Tags | Input Fields | Signature |
|---|---|---|---|---|---|
| IBM | 0px | 0px | 0px | 0px | Carbon: everything square |
| Ferrari | 0px | 0px | 9999px (badge) | 4px | Luxury precision |
| Lamborghini | 0px | 0px | 2px | 20px (switch) | Aggressive angular |
| NVIDIA | 2px | 2px | 2px | 2px | Engineering grade |
| Warp | 3px | 3px | 9999px | 3px | Terminal aesthetic |
| OpenCode | 4px | 4px | 4px | 4px | Monospace discipline |
Moderate (6-12px)
| Brand | Buttons | Cards | Pills/Tags | Input Fields | Signature |
|---|---|---|---|---|---|
| Vercel | 6px | 12px | 999px | 6px | Developer standard |
| Expo | 8px | 12px | 9999px | 8px | React Native standard |
| Intercom | 8px | 12px | 9999px | 8px | SaaS standard |
| Mistral | 8px | 12px | 9999px | 8px | Editorial sober |
| Sentry | 8px | 12px | 4px | 8px | Developer playful |
| Kraken | 12px | 12px | 6px | 12px | Crypto standard |
Soft (16-32px)
| Brand | Buttons | Cards | Pills/Tags | Input Fields | Signature |
|---|---|---|---|---|---|
| Apple | 980px (pill) | 18px | 980px | 12px | Pill buttons + soft cards |
| Airbnb | 8px | 14px | 999px | 8px | Warm marketplace |
| Uber | 999px (pill) | 16px | 36px | 8px | Pill + moderate cards |
| HP | 4px | 16px | 9999px | 4px | Sharp buttons + soft cards |
| 16px | 16px | 9999px | 16px | Unified 16px | |
| Meta | 100px (pill) | 32px | 100px | 8px | Pill + large cards |
| Miro | 9999px (pill) | 28px | 9999px | 8px | Pill + pastel cards |
Extreme (40px+ / Full Pill)
| Brand | Buttons | Cards | Pills/Tags | Input Fields | Signature |
|---|---|---|---|---|---|
| Mastercard | 20px | 40px | 999px | 999px | Stadium shapes |
| MiniMax | 9999px | 32px (hero) / 16px (std) | 9999px | 8px | Dual-radius system |
| Revolut | 9999px | 20px | 9999px | 8px | Fintech pill |
| MongoDB | 9999px | 12px | 6px | 8px | Green pill + moderate cards |
Key insights from 73 brands: 1. Card radius: 12px is the mode — 35% of brands use 12px for cards. 16px is second at 20%. 24px+ is rare (~10%). 2. Button radius is bimodal — either sharp (0-8px, ~30%) or full pill (9999px, ~40%). The 12-16px middle ground is uncommon. 3. The "two-tier" pattern — many brands use sharp/moderate buttons with softer cards (HP: 4px buttons + 16px cards) or pill buttons with moderate cards (MongoDB: pill + 12px cards). 4. 0px radius = luxury/enterprise signal — IBM, Ferrari, Lamborghini all use 0px. It reads as precision and authority. 5. AI over-rounds everything — AI defaults to 24px+ cards and 8-12px buttons. Real brands are either sharper or more committed to pills.
---
How to Design Layout
Match Layout to Content Type
| Content | Layout | Why |
|---|---|---|
| Dashboard with KPIs + charts | Sidebar + grid content | Navigation always visible, data organized |
| Single-purpose tool | Top nav + centered content | Focus on the task |
| Portfolio / showcase | Full-width sections | Each project gets full attention |
| Data-heavy table view | Top nav + full-width table | Maximum horizontal space |
| Multi-panel monitoring | Bento grid | Different data types, different sizes |
| Article / documentation | Single column, max-width 65ch | Optimal reading experience |
| Marketing / landing page | Full-width sections with varied layouts | Visual storytelling |
Layout Variety Within a Page
A page with 5+ sections must NOT repeat the same layout pattern. Audit your sections top-to-bottom:
- If section 1 is centered text, section 2 should NOT also be centered text
- If sections 2-3 alternate image-left/image-right (zigzag), section 4 must break the pattern
- Vary content width: some sections full-bleed, some contained, some narrow
Don't Default to the Same Layout
If your last generation used a sidebar layout, try top nav or bento grid next. If it was a card grid, try a table or split panel. Variety in layout is as important as variety in color.
---
Surface Treatments (Optional Depth)
These are techniques to add visual depth. Use 0-2 per project, not all of them. Implement fresh each time — don't copy the same code.
| Technique | What It Does | When to Use | When NOT to Use |
|---|---|---|---|
| Noise/grain texture | SVG feTurbulence overlay at very low opacity on a fixed pseudo-element | Editorial, analog, luxury aesthetics | Clean/minimal designs, data-dense dashboards |
| Gradient orbs | Radial gradients using accent color at low opacity, positioned as fixed background | Dark tech/AI themes that need atmospheric depth | Light themes, corporate/clean designs |
| Glass/blur cards | backdrop-filter: blur with semi-transparent background and hairline border | Dark themes with layered depth, floating nav bars | Scrolling content areas (kills mobile perf), light themes |
| Nested card (double-bezel) | Outer shell with subtle bg + inner content card with smaller border-radius | Premium/luxury feel, hero feature cards | Every card on the page (use sparingly, 1-2 max) |
| Subtle gradient background | Linear or radial gradient on body, very low saturation | Pastel/soft aesthetics, wellness/education | Data dashboards, professional tools |
| Dot grid pattern | Repeating radial-gradient dots at low opacity | Technical/engineering aesthetics | Organic/warm designs |
Rules:
- Pick 0-2 treatments per project. More than 2 is visual noise.
- A clean surface with no effects is always a valid choice — often the best one.
backdrop-filter: bluronly on fixed/sticky elements, never on scrolling containers.- All overlays must be
pointer-events: noneandposition: fixed.
---
Dark Surface Tint Guide
When the Design Dials select a dark or tinted surface (indices 2, 3, or 4), use the Scene Sentence to determine the tint direction. NEVER default to the `#0a-#0f` blue-black range — this is the #1 cause of AI design sameness.
Scene-to-Tint Mapping
| Scene Environment | Tint Direction | Example Base | Example Elevated | CSS Custom Property Hint |
|---|---|---|---|---|
| Studio with warm lighting | Warm charcoal | #1a1816 | #242220 | --surface: hsl(30, 8%, 9%) |
| Forest cabin at night | Deep green-black | #0f1512 | #1a201c | --surface: hsl(150, 15%, 7%) |
| Wine cellar / luxury lounge | Deep wine/burgundy | #1a1014 | #24181c | --surface: hsl(340, 25%, 8%) |
| Industrial workshop | Warm gray-brown | #1c1a18 | #26241f | --surface: hsl(40, 8%, 10%) |
| Cinema / theater | Pure neutral black | #111111 | #1a1a1a | --surface: hsl(0, 0%, 7%) |
| Underwater / aquatic | Deep teal-black | #0f1614 | #1a211e | --surface: hsl(160, 20%, 7%) |
| Desert night | Warm sand-black | #181614 | #22201c | --surface: hsl(30, 10%, 8%) |
| Arctic / ice | Cool blue-gray | #14161a | #1e2024 | --surface: hsl(220, 12%, 9%) |
How to Use This Table
1. Write your Scene Sentence (see SKILL.md Step 0.5) 2. Find the closest matching environment in the table above 3. Use the example colors as a starting point, then adjust to match your specific scene 4. Derive 4+ surface levels by incrementing lightness by 5-10% per step 5. Verify all text contrast ratios against your chosen surface
Banned Dark Surface Colors
These specific hex values are absolutely banned as dark surface backgrounds — they are the AI default dark mode palette:
/* BANNED — AI default blue-black surfaces */
#0a0e1a /* Most common AI deep blue-black */
#0d1117 /* GitHub-style deep blue-black */
#0f172a /* Tailwind slate-900 */
#111827 /* Tailwind gray-900 */
#1e1b4b /* Tailwind indigo-950 */Any background color in the #07-#0f range with a blue hue component is suspect. If your dark surface has more blue than any other hue channel, reconsider.
---
Banned Color Reference
A comprehensive list of colors to avoid as defaults. These are the most common AI-generated color choices across thousands of outputs.
AI Default Accents
/* BANNED as default accent — AI's go-to colors */
#3b82f6 /* Tailwind blue-500 — the #1 AI accent */
#6366f1 /* Tailwind indigo-500 */
#8b5cf6 /* Tailwind violet-500 */
#a855f7 /* Tailwind purple-500 */Exemption: Only if the Design Read explicitly demands blue/purple (e.g., a brand whose identity IS blue), document the justification in a code comment.
AI Default Warm Neutral Backgrounds
/* BANNED as default background — 2025-2026 AI warm neutral wave */
#f5f1ea
#f7f5f1
#fbf8f1
#efeae0
#ece6db
#faf7f1
#e8dfcbAny warm neutral with OKLCH L 0.84-0.97, C < 0.06, hue 40-100 falls in this category.
AI Default Premium Accents
/* BANNED as default — AI "premium-consumer" palette */
#b08947 /* brass */
#b6553a /* clay */
#9a2436 /* oxblood */
#9c6e2a /* ochre */
#bc7c3a /* amber-brown */
#7d5621 /* dark gold */
/* BANNED — AI "premium" text colors */
#1a1714 /* espresso */
#1a1814 /* espresso variant */
#1b1814 /* espresso variant */Anti-Default Defaults (the trap one tier deeper)
These aren't banned outright, but be aware they are becoming the new AI defaults:
- Teal/emerald — has become "the new AI purple" (the go-to when told to avoid blue/purple)
- Warm amber/gold — becoming the "sophisticated alternative" to blue
- Sage green — the "calming, natural" default
When you find yourself reaching for these, ask: "Am I choosing this because it's right for the content, or because it's my safe alternative?" If the latter, explore further.
---
Curated Color Palettes by Aesthetic Family
These are starting points, not templates. Pick one as inspiration, then adjust to match your specific Design Read. Never copy a palette verbatim across projects.
Swiss/International
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #fafafa | #141414 | Near-white / near-black, no tint |
| Elevated | #ffffff | #1e1e1e | Pure contrast |
| Accent | #e63946 | #ff6b6b | Swiss red, bold and singular |
| Text | #1d1d1f | #f0f0f0 | Maximum readability |
| Muted | #86868b | #8e8e93 | Functional gray |
Neo-brutalist
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #fffdf5 | #1a1a1a | Warm white / true black |
| Elevated | #ffffff | #2a2a2a | With thick black borders |
| Accent | #ff5722 | #ff7043 | Loud, unapologetic |
| Secondary | #ffeb3b | #fdd835 | Yellow highlight |
| Text | #000000 | #ffffff | Pure black/white |
| Border | #000000 (3px) | #ffffff (3px) | Thick, visible |
Editorial/Magazine
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #f8f6f3 | #1c1917 | Warm paper / warm dark |
| Elevated | #ffffff | #262220 | Subtle warmth |
| Accent | #c2452d | #e05a3a | Editorial red-orange |
| Text | #2c2825 | #e8e2da | Warm, not pure black |
| Caption | #8a8078 | #9a9088 | Warm gray |
Soft-tech
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #f0f4ff | #161a2e | Soft blue tint |
| Elevated | #ffffff | #1e2240 | Gentle lift |
| Accent | #6c5ce7 | #a29bfe | Soft purple |
| Secondary | #00cec9 | #55efc4 | Mint complement |
| Text | #2d3436 | #dfe6e9 | Soft contrast |
| Shadow | rgba(108,92,231,0.08) | rgba(162,155,254,0.12) | Tinted shadows |
Industrial/Utilitarian
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #e8e6e3 | #141413 | Concrete / carbon |
| Elevated | #f2f0ed | #1c1c1a | Subtle lift |
| Accent | #f59e0b | #fbbf24 | Warning amber |
| Status Green | #22c55e | #4ade80 | System go |
| Status Red | #ef4444 | #f87171 | System alert |
| Text | #1c1917 | #d4d4d4 | Functional |
| Mono | JetBrains Mono | JetBrains Mono | Monospace throughout |
Art Deco/Geometric
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #1a1a2e | #0d0d1a | Deep midnight |
| Elevated | #25254a | #16162e | Rich depth |
| Accent | #d4af37 | #e8c547 | True gold |
| Secondary | #c9a96e | #d4b87a | Antique brass |
| Text | #f0e6d3 | #e8dcc8 | Warm cream on dark |
| Pattern | rgba(212,175,55,0.1) | rgba(212,175,55,0.15) | Geometric overlays |
Organic/Natural
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #f5f2ed | #1a1c18 | Parchment / forest floor |
| Elevated | #faf8f4 | #242620 | Natural warmth |
| Accent | #5a7247 | #7d9a6a | Moss green |
| Secondary | #c17f59 | #d4956e | Terracotta |
| Text | #2d2a26 | #e0dcd6 | Earth tone |
| Muted | #8a8279 | #9a9289 | Stone gray |
Retro-futuristic
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #1a0a2e | #0a0518 | Deep purple-black |
| Elevated | #2a1548 | #150d28 | Neon-ready dark |
| Accent | #00ff88 | #00ff88 | Neon green |
| Secondary | #ff006e | #ff3388 | Hot pink |
| Tertiary | #00b4d8 | #48cae4 | Cyan |
| Text | #e0ffe8 | #d0ffd8 | Green-tinted white |
| Glow | 0 0 20px rgba(0,255,136,0.3) | 0 0 30px rgba(0,255,136,0.4) | Neon glow effect |
Minimalist/Zen
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #ffffff | #111111 | Pure, no tint |
| Elevated | #fafafa | #1a1a1a | Barely there |
| Accent | #9ca3af | #6b7280 | Muted gray as accent |
| Text | #374151 | #d1d5db | Soft, not harsh |
| Muted | #d1d5db | #4b5563 | Whisper |
| Border | #f3f4f6 | #1f2937 | Nearly invisible |
Data-dense/Mission Control
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #f1f3f5 | #0c0c0e | Cool neutral |
| Elevated | #ffffff | #161618 | Panel background |
| Accent | #3b82f6 | #60a5fa | Functional blue (allowed here) |
| Success | #10b981 | #34d399 | System nominal |
| Warning | #f59e0b | #fbbf24 | Attention needed |
| Critical | #ef4444 | #f87171 | Alert |
| Text | #1e293b | #e2e8f0 | High contrast |
| Grid | rgba(0,0,0,0.06) | rgba(255,255,255,0.06) | Panel borders |
Playful/Toy-like
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #fff8e1 | #1a1520 | Warm yellow / playful dark |
| Elevated | #ffffff | #252030 | Bouncy cards |
| Primary | #ff6b6b | #ff8a8a | Coral red |
| Secondary | #4ecdc4 | #6ee7de | Turquoise |
| Tertiary | #ffe66d | #fff08a | Sunny yellow |
| Quaternary | #a06cd5 | #b88ae0 | Playful purple |
| Text | #2d3436 | #f0eef5 | Warm dark |
Luxury/Refined
| Role | Light Theme | Dark Theme | Notes |
|---|---|---|---|
| Surface | #0a0a0a | #050505 | Deep black |
| Elevated | #141414 | #0f0f0f | Subtle lift |
| Accent | #c9a55c | #d4b06a | Matte gold (not shiny brass) |
| Secondary | #8a7e6b | #9a8e7b | Warm stone |
| Text | #e8e4de | #f0ece6 | Warm white |
| Muted | #6b6560 | #7a746e | Understated |
| Border | rgba(201,165,92,0.15) | rgba(201,165,92,0.2) | Gold whisper |
Usage Notes
- Light-first families (Swiss, Editorial, Organic, Minimalist, Playful): The light theme is the "hero" — design it first, then derive the dark variant.
- Dark-first families (Art Deco, Retro-futuristic, Luxury, Industrial): The dark theme is the "hero" — design it first, then derive the light variant.
- Neutral families (Neo-brutalist, Soft-tech, Data-dense): Both themes are equally important.
- Never use these palettes as-is — they are starting points. Adjust hue, saturation, and lightness to match your specific Design Read and Scene Sentence.
---
The Creativity Rule
The examples and techniques in this file are starting points for thinking, not templates to copy. The best designs come from:
1. Understanding the content and audience first (Design Read) 2. Choosing a color strategy level that matches the atmosphere 3. Making intentional choices for each dimension 4. Combining familiar techniques in unfamiliar ways 5. Knowing the rules well enough to break them purposefully
If you find yourself reaching for the same combination you used before, stop and explore a different direction. The goal is that every project feels like it was designed specifically for its content — not generated from a template.
Animation & Motion Reference
Guidelines and timing standards for UI animation. These are constraints and principles — implement the actual CSS/JS fresh each time based on your design direction.
---
Core Principles
1. Animate only `transform` and `opacity`. Never animate width, height, top, left, margin, padding — they trigger layout recalculation. 2. No `transition: all`. Always specify exact properties: transition: transform 200ms, opacity 200ms. 3. No `linear` or default `ease-in-out`. Use custom cubic-bezier curves that match your design's personality. 4. Exit faster than enter. Exit animations should be ~70% of enter duration. 5. Motion must have purpose. Every animation should communicate something (feedback, orientation, continuity). Decorative-only animation is noise. 6. Respect `prefers-reduced-motion`. Provide a reduced alternative (opacity fade or instant) for every animation. 7. Delight scales inversely with frequency. High-frequency interactions (button clicks, tab switches) need near-invisible transitions. Low-frequency moments (page load, first reveal) can be more expressive.
---
Animation Decision Framework (integrated from emil-design-eng)
Before writing animation code, answer these in order:
1. Should this animate at all?
| Frequency | Decision |
|---|---|
| 100+ times/day (keyboard shortcuts, command palette toggles) | No animation |
| Tens of times/day (hover/list navigation) | Keep near-instant or minimal |
| Occasional (modal/drawer/toast) | Standard animation |
| Rare or first-time | Can add delight |
2. What is the purpose?
Valid purposes only: feedback, state indication, spatial continuity, preventing jarring transitions, explanatory storytelling. If no clear purpose, remove the animation.
3. Which easing and duration fit?
- UI entrances/exits: prefer strong
ease-out - On-screen morph/movement:
ease-in-out(custom curve) - Hover/color transitions:
ease - Constant motion only:
linear - Avoid
ease-infor entrances (feels sluggish)
Mandatory interaction motion rule
If a page has interactions, motion design is required.
Minimum bar for interactive UI:
- press feedback (
:activescale 0.95-0.98) - visible state transitions (open/close/select/sort/filter)
- reduced-motion fallback
Practical implementation patterns
Press feedback (required for pressable controls)
.button {
transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.button:active {
transform: scale(0.97);
}Never animate from scale(0)
/* Bad */
.entering { transform: scale(0); }
/* Better */
.entering {
transform: scale(0.95);
opacity: 0;
}Origin-aware popover motion
/* Radix UI */
.popover {
transform-origin: var(--radix-popover-content-transform-origin);
}Interruptible UI: transitions over keyframes
.toast {
transition: transform 280ms cubic-bezier(0.23, 1, 0.32, 1), opacity 200ms ease;
}Touch-safe hover animations
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-2px); }
}---
Easing Philosophy
Choose easing curves that match your design's atmosphere. Define them as CSS custom properties, but use your own names and values — don't copy the same curves every time.
Guidelines for choosing curves:
- Entrances and reveals: Ease-out curves (fast start, gentle landing). The element "arrives" with confidence.
- Slides and panels: Slightly less aggressive ease-out. Smooth, continuous movement.
- Dramatic reveals: Exponential ease-out for hero animations and page-load sequences.
- Micro-interactions: Quick, subtle curves. The user should feel the response, not watch it.
Never use: linear (robotic), ease-in alone (sluggish entrances), default ease-in-out (generic, the browser default).
Real-world easing references (from major brands — use as starting points, not templates):
| Brand | Signature Curve | Feel |
|---|---|---|
| Apple | cubic-bezier(0.25, 0.1, 0.25, 1) | Smooth, confident |
| Stripe | cubic-bezier(0.4, 0, 0.2, 1) | Quick start, gentle land |
| Linear | cubic-bezier(0.16, 1, 0.3, 1) | Snappy, precise |
| Framer | cubic-bezier(0.76, 0, 0.24, 1) | Dramatic, poster-like |
| Spotify | cubic-bezier(0.3, 0, 0, 1) | Fast, musical |
| Tesla | cubic-bezier(0.5, 0, 0, 0.75) | Engineered, restrained |
| Airbnb | cubic-bezier(0.2, 0, 0, 1) | Warm, welcoming |
Vary your curves between projects. If every project uses the same cubic-bezier values, the motion becomes an AI signature. Adjust the control points to match the design's energy — snappier for technical tools, softer for editorial, bouncier for playful contexts.
---
Timing Standards
These are ranges, not fixed values. Choose within the range based on your design's density and energy.
| Element | Enter Duration | Exit Duration | Notes |
|---|---|---|---|
| Button hover/press | 80-150ms | 80-100ms | Should feel instant. High-frequency. |
| Card hover | 150-250ms | 120-180ms | Subtle lift or border change. |
| Tooltip/popover | 120-180ms | 80-120ms | Fast in, faster out. |
| Dropdown/select | 150-250ms | 120-180ms | Match card hover timing. |
| Modal/dialog | 200-300ms | 150-220ms | Scale + opacity. |
| Drawer/panel | 250-350ms | 200-280ms | Slide from edge. |
| Scroll reveal | 400-700ms | — | One-shot, no exit needed. |
| Page load stagger | 300-600ms | — | Stagger delay 30-80ms per item. |
Asymmetric timing rule: For high-frequency UI (tabs, toggles, accordions), consider making the entrance near-instant (0-50ms) and only animating the exit (100-150ms). The user's action should feel immediate.
---
Scroll Reveal
Every page should have scroll reveal on content sections. Use IntersectionObserver to add a class when elements enter the viewport.
Implementation approach (not a template — write fresh each time): 1. Mark revealable elements with a data attribute or class 2. Set their initial state in CSS (hidden: reduced opacity, slight transform offset) 3. Create an IntersectionObserver that adds a "visible" class on intersection 4. The "visible" class transitions to the final state using your easing variables 5. Unobserve after revealing (one-shot, not toggle)
Reveal styles — choose ONE per page and use it consistently:
- Fade up: opacity 0 + slight translateY → visible
- Fade in: opacity 0 → visible (simpler, calmer)
- Scale up: opacity 0 + slight scale → visible (more dramatic)
- Slide in: opacity 0 + translateX → visible (directional, editorial)
Stagger rules for grids/lists:
- Delay per item: 30-80ms (vary based on energy level)
- Total stagger duration: never exceed 400ms (so max ~5-8 items staggered)
- For longer lists, only stagger the first visible batch
---
Reduced Motion
Always include a prefers-reduced-motion media query that effectively disables animations and transitions. This is a hard requirement, not optional.
The implementation should:
- Set all
animation-durationandtransition-durationto near-zero - Apply to all elements including pseudo-elements
- Use
!importantto override inline styles
---
Interaction Feedback
- Button press: Slight scale-down on
:activefor tactile feedback - Card hover: Subtle lift (translateY) OR border/shadow change. Not both.
- Link hover: Color change or underline animation. Keep it simple.
- Focus: Visible focus ring for keyboard navigation. Never remove
:focus-visiblestyles.
---
Modal & Overlay Animation
- Overlay: Fade in opacity with optional backdrop blur
- Modal content: Scale from slightly smaller + fade in. Never start from
scale(0)— nothing appears from nothing. - Drawer: Slide from edge (translateX or translateY depending on direction)
- Exit: Reverse the animation, but faster (70% of enter duration)
- Overlay and content animate independently — the overlay fades while the content transforms
---
Skeleton Loading
- Use a horizontal shimmer effect (gradient sweep from left to right)
- Match skeleton shapes to the content they replace (text lines, avatars, cards)
- Animation: infinite loop, ~1.5s duration
- Disable shimmer animation when
prefers-reduced-motionis active — show static placeholder instead
---
Anti-Patterns
- ❌
transition: all— animates unintended properties, causes jank - ❌ Animating layout properties (
width,height,top,left,margin) - ❌
lineareasing on UI elements - ❌ Starting from
scale(0)— nothing appears from nothing - ❌ Permanent
will-change— only during active animation - ❌
backdrop-bluron scrolling containers — kills mobile performance - ❌ Symmetric enter/exit timing — exit should be faster
- ❌ Animations without
prefers-reduced-motionfallback - ❌ Bouncy/elastic easing on UI elements (save for marketing/playful contexts only)
- ❌ Same easing curves and timing on every project — vary to match the design's energy
- ❌ Scroll-triggered animations that replay on scroll-up (use one-shot reveals)
---
GSAP — Advanced Motion Layer (when CSS isn't enough)
GSAP (GreenSock Animation Platform) is the production-grade JS animation engine for the moments CSS transitions can't cover: scroll-driven sequences, timelines, text-into-characters reveals, SVG morph/draw, FLIP layout animations, draggable UI. As of April 2025 it is 100% free including commercial use (Webflow now sponsors it) — the formerly-paid plugins (ScrollTrigger, SplitText, MorphSVG, DrawSVG, Flip, Physics2D, etc.) are all free. Apache-style open availability, no license gate.
Why it fits both tracks: GSAP is framework-agnostic plain JavaScript. It loads via a <script> CDN tag with no build step, so it works in a Track A static preview and in a Track B React app. This is the key difference from the component libraries — you can reach for GSAP even in a throwaway preview.
When to use GSAP vs plain CSS
| Use CSS transitions/keyframes (the default) | Reach for GSAP |
|---|---|
| Hover, press, focus, tab/accordion toggles | Multi-step timelines (sequence/overlap several animations precisely) |
| Simple one-shot scroll reveal (IntersectionObserver) | Scroll-driven animation: pin sections, scrub progress to scroll, parallax (ScrollTrigger) |
| Modal/drawer enter-exit | Text reveals by line/word/char (SplitText) |
| Skeleton shimmer | SVG morphing (MorphSVG) or line drawing (DrawSVG) |
| Anything achievable in <10 lines of CSS | FLIP layout transitions (animate elements between DOM states), physics, draggable, complex stagger |
Rule of thumb: don't pull GSAP for what CSS already does well — it's ~50KB+ and overkill for a button hover. Use it when the motion is a feature (a landing-page scroll story, a hero text reveal), not decoration. All the timing/easing/prefers-reduced-motion discipline in this file still applies — GSAP makes ignoring it easier, so be disciplined.
Load it (look up the current version — don't trust a memorized number)
GSAP iterates; check the current version and exact CDN paths at build time at gsap.com/docs/v3/Installation (the install helper there generates the right tags). Pattern (Track A, CDN):
<!-- core -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<!-- only the plugins you actually use -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js"></script>
<script>
gsap.registerPlugin(ScrollTrigger); // every plugin must be registered once
</script>Track B (build step): npm i gsap → import gsap from "gsap" + import { ScrollTrigger } from "gsap/ScrollTrigger" → gsap.registerPlugin(ScrollTrigger).
Core API in three shapes (full reference: gsap.com/docs/v3)
// 1. Tween — animate to/from. Note: GSAP durations are in SECONDS, not ms.
gsap.to(".box", { x: 200, opacity: 1, duration: 0.6, ease: "power3.out" });
gsap.from(".card", { y: 24, opacity: 0, duration: 0.5, stagger: 0.06 }); // built-in stagger
// 2. Timeline — sequence/overlap with precise control
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.5 } });
tl.from(".title", { y: 30, opacity: 0 })
.from(".subtitle", { y: 20, opacity: 0 }, "-=0.3") // overlap previous by 0.3s
.from(".cta", { scale: 0.9, opacity: 0 }, "<"); // start with previous
// 3. ScrollTrigger — bind animation to scroll position
gsap.from(".reveal", {
y: 40, opacity: 0, duration: 0.7,
scrollTrigger: { trigger: ".reveal", start: "top 80%", once: true } // one-shot
});GSAP has its own named eases (power1–power4, expo, back, elastic, circ, custom via CustomEase) — visualize/choose at the GSAP ease visualizer. Map them to the same atmosphere rules above (ease-out for entrances, restrained for UI; save elastic/back for playful contexts only).
Plugins (all free now) — look up usage per-plugin, don't memorize
Don't write plugin code from memory; open the plugin's doc page for current API. Most useful for UI work:
| Plugin | Use for | Docs |
|---|---|---|
| ScrollTrigger | scroll-scrub, pin sections, reveal-on-scroll, parallax | /docs/v3/Plugins/ScrollTrigger |
| SplitText | split headings into lines/words/chars for staggered text reveals | /docs/v3/Plugins/SplitText |
| Flip | animate elements smoothly between two layout/DOM states | /docs/v3/Plugins/Flip |
| DrawSVG | animate SVG strokes drawing themselves | /docs/v3/Plugins/DrawSVGPlugin |
| MorphSVG | morph one SVG shape into another | /docs/v3/Plugins/MorphSVGPlugin |
| Draggable | drag/throw/snap interactions | /docs/v3/Plugins/Draggable |
Browse all at gsap.com/docs/v3/Plugins.
React: use the official hook
In a React/Next app, don't call GSAP in a raw useEffect — use `useGSAP()` from @gsap/react. It scopes selectors to a container ref and auto-cleans up all animations/ScrollTriggers on unmount (prevents the classic memory-leak + duplicate-trigger bugs). See gsap.com/resources/React.
import { useGSAP } from "@gsap/react";
const container = useRef();
useGSAP(() => {
gsap.from(".item", { y: 20, opacity: 0, stagger: 0.05 });
}, { scope: container }); // selectors resolve inside container; cleanup automaticGSAP non-negotiables
- Register every plugin once (
gsap.registerPlugin(...)) before use, or it silently no-ops. - Durations are seconds.
duration: 0.3, not300. - `prefers-reduced-motion` still applies. Guard scroll/timeline animations: if the user prefers reduced motion, skip the animation or jump to the end state. Wrap setup in
gsap.matchMedia()or amatchMedia("(prefers-reduced-motion: reduce)")check — a flashy GSAP scroll story with no reduced-motion path is a defect. - Clean up. In SPAs, kill ScrollTriggers/timelines on teardown (React:
useGSAPdoes this for you; vanilla: keep refs and.kill()/ScrollTrigger.getAll().forEach(t => t.kill())on route change). - Don't GSAP-animate what CSS does fine. Reserve it for timelines, scroll, text, SVG, FLIP, physics, drag.
- Still animate `transform`/`opacity`, not layout properties — GSAP doesn't exempt you from compositor rules.
- Look up current version + plugin APIs at build time from gsap.com — don't ship memorized snippets for fast-moving plugins.
Charts & Data Visualization Reference
Guidelines for creating professional charts in dashboards. These are design standards — implement the actual chart code fresh each time.
---
Library Selection
Load via CDN in <script> tag:
| Library | Use When |
|---|---|
Chart.js (chart.js@4) | Most dashboards. Simple API, good defaults, lightweight (~65KB) |
ECharts (echarts@5) | Complex/interactive dashboards. Rich features, larger (~300KB) |
uPlot (uplot@1) | High-performance time series. Minimal, fast (~35KB) |
Default to Chart.js unless the dashboard needs advanced interactions (drill-down, linked charts, complex tooltips).
---
Chart Type Selection
| Data Pattern | Use | Don't Use |
|---|---|---|
| Trend over time | Line chart | Bar chart (unless discrete periods) |
| Comparing categories | Vertical bar chart | Pie chart |
| Long category labels | Horizontal bar chart | Vertical bar (labels get truncated) |
| Parts of a whole (≤5 segments) | Donut chart | Pie chart with >5 segments |
| Parts of a whole (>5 segments) | Horizontal bar chart | Pie or donut (too many slices) |
| Distribution | Area chart | Pie chart |
| Single metric vs target | Progress bar or gauge | Full chart (overkill) |
| Inline trend indicator | Sparkline (canvas mini-chart) | Full chart in a stat card |
Never use: 3D charts, radar charts for simple data, pie charts with >5 segments.
---
Styling Rules
Colors
- Use your page's CSS custom properties for chart colors. Never use library default colors.
- Read CSS variables with
getComputedStyle(document.documentElement).getPropertyValue(...). - For multi-series: derive variations from your accent (adjust opacity or lightness), or use a harmonious set that matches your palette.
- All data colors must pass 3:1 contrast against the chart background.
Grid & Axes
- Grid lines: very subtle — use your border/separator color or lower opacity. Grid should never compete with data.
- Axis labels: use your muted text color, 12px font size.
- Include units on axis labels ($ / % / K / M).
- Hide the axis border line.
- X-axis grid: usually hidden. Y-axis grid: subtle horizontal lines.
Tooltips
- Style tooltips to match your page theme (background, text color, border, border-radius).
- Show exact values on hover/tap.
- Use crosshair or index mode for better hover behavior on line/area charts.
Legend
- Always show legend for multi-series charts.
- Position: below the chart or inline with the title. Never detached far from the chart.
- Use point-style (small circles) instead of rectangles for cleaner look.
Responsiveness
- Charts must resize with their container. Set responsive mode and disable fixed aspect ratio.
- Set chart container height explicitly (e.g., 200-320px range depending on importance).
- On mobile, consider simplifying: fewer data points, abbreviated labels, hidden legend.
---
Chart Container Anti-Expansion (CRITICAL)
Problem: Chart.js and ECharts in responsive mode will infinitely expand their height if the container doesn't have a strictly fixed height. This happens because: 1. The chart reads the container's height → renders at that height 2. The render increases the container's scrollHeight → triggers a resize observer 3. The resize observer re-reads the (now larger) height → re-renders taller 4. Infinite loop → page becomes unusable
The fix — always use this exact container pattern:
<!-- ✅ CORRECT: Fixed-height wrapper with position:relative + canvas -->
<div class="chart-card">
<h3>Chart Title</h3>
<div class="chart-container" style="height: 280px; position: relative;">
<canvas id="myChart"></canvas>
</div>
</div>/* ✅ CORRECT: Chart container CSS */
.chart-container {
position: relative; /* REQUIRED — canvas positions relative to this */
height: 280px; /* REQUIRED — explicit px height, NOT min-height, NOT auto */
width: 100%; /* OK — width can be flexible */
overflow: hidden; /* SAFETY — prevent any overflow from expanding parent */
}
/* ❌ WRONG — these will cause infinite expansion: */
.chart-container {
height: auto; /* ❌ auto height = chart decides = infinite growth */
min-height: 280px; /* ❌ min-height without max = can grow forever */
flex: 1; /* ❌ flex child without explicit height = expansion */
height: 100%; /* ❌ percentage of flex/grid parent = unstable */
}Chart.js configuration (mandatory):
new Chart(ctx, {
// ...
options: {
responsive: true,
maintainAspectRatio: false, // REQUIRED — let container control height
// ...
}
});ECharts configuration (mandatory):
const chart = echarts.init(container);
// Container MUST have explicit px height before init
// If you need to handle resize:
window.addEventListener('resize', () => {
chart.resize(); // ECharts resize — reads container dimensions
});
// Do NOT call chart.resize() inside a ResizeObserver on the chart container itself — infinite loop!Additional safety rules:
- Never put a chart container inside a CSS Grid or Flexbox child without an explicit
heightin px - Never use
height: 100%on a chart container unless the parent chain all the way up has explicit heights - Never call
chart.resize()orchart.update()inside a ResizeObserver that observes the chart's own container - Always set
overflow: hiddenon the chart container as a safety net - If using CSS Grid for dashboard layout, set
grid-template-rowswith explicit values (e.g.,280px), notautoor1fr
---
Chart Container Design
Every chart should be wrapped in a card with: 1. Title (left-aligned, semibold) 2. Optional period selector (right-aligned, small toggle buttons) 3. Chart area (fixed height via explicit px, responsive width) 4. Optional footer (summary text or legend)
---
Empty & Error States
- No data: Show a centered message with a muted icon. Never show an empty chart frame with axes but no data.
- Loading: Show a skeleton placeholder matching the chart's dimensions. Not a spinner.
- Error: Show error message with a retry action. Never show a broken/partial chart.
---
Mock Data
When generating dashboards, create realistic mock data:
Time Series
- Generate 7-30 data points with natural fluctuation (random walk with mean reversion)
- Don't use round numbers (not 1000, 2000, 3000 — use 1,247, 2,089, 2,834)
- Include a general trend (upward, downward, or seasonal) — not flat lines
- Use realistic date labels
Category Data
- Use real-world category names (actual product names, city names, department names)
- Values should have natural variance — not evenly distributed
- Include both positive and negative changes where appropriate
Proportional Data
- Segments should have realistic proportions (not equal slices)
- Include one dominant segment (40-60%) and several smaller ones
- Labels should be specific ("Desktop Chrome" not "Category A")
---
Dashboard Layout Principles
Don't copy a fixed layout template. Instead, follow these principles:
Information Hierarchy
1. KPI summary row at the top — the most important metrics at a glance (typically 3-5 stat cards) 2. Primary chart — the main data story, given the most space 3. Supporting charts — secondary data, smaller than the primary 4. Detail table — granular data for users who want to drill down
Layout Guidelines
- Use CSS Grid. Vary column spans — not every chart should be the same width.
- The primary chart should be visually dominant (wider or taller than supporting charts).
- KPI cards stack to 2-column on tablet, single column on mobile.
- Charts stack vertically on mobile.
- Tables get horizontal scroll on mobile.
Constraints
- Maximum 3-4 charts + 1 table per dashboard view. More than that overwhelms.
- Not every chart should be the same height. Vary: one tall primary + shorter supporting charts.
- Choose the 4-6 most important KPIs. Don't show every metric.
---
Checklist
- [ ] Chart type matches the data pattern
- [ ] Colors match the page palette (not library defaults)
- [ ] Axis labels include units
- [ ] Tooltips show exact values
- [ ] Grid lines are subtle
- [ ] Chart is responsive
- [ ] Empty/error states handled
- [ ] Mock data looks realistic (not round numbers, has variance)
- [ ] Legend visible for multi-series
- [ ] Font sizes readable (≥12px)
- [ ] Dashboard layout varies chart sizes (not all identical)
- [ ] Primary chart is visually dominant
Component Libraries — shadcn/ui · HeroUI · coss ui (Track B)
Open-source component libraries do the boring, error-prone work for you: accessible primitives, keyboard handling, focus management, consistent spacing, dark mode, and battle-tested component APIs. Reaching for one reduces the amount of markup/CSS you hand-write and raises the floor on quality — you spend your effort on layout, data, and taste instead of re-deriving a date picker.
Core rule of this file: never paste component source into this skill, and never rely on memorized component APIs. These libraries ship fast and their APIs drift. Always look up the current component and its props at build time from the sources listed below (docs page, llms.txt, MCP server, or CLI registry). Memorized snippets are how you ship broken props. Treat the library's own docs/registry as the source of truth, every time.---
When a component library is the right tool
| Situation | Use a component library? |
|---|---|
| Static HTML preview, quick dashboard, no build step | No — hand-build with Track A (design-process.md) + CDN Tailwind/Chart.js. React libraries need a bundler. |
| Real React / Next.js / Vite app the user will keep and extend | Yes — pull components, don't hand-roll. |
| App with forms, modals, dropdowns, tables, date pickers, command palettes | Yes — these are exactly what the libraries get right and what hand-rolled code gets wrong (a11y, focus traps, keyboard). |
| User explicitly wants "shadcn", "HeroUI", "Cal.com style", "Origin UI" | Yes — use the named one. |
| Tiny widget, email HTML, or anything without a build step | No — Track A. |
The build-step reality (Starchild `preview`): shadcn/ui, HeroUI, and coss ui are all React + Tailwind. They require a bundler (Vite or Next.js) and a preview started with a command + port, not the static file server. If the task is a throwaway preview with no build, stay on Track A. If you're scaffolding a real app, set up Vite + Tailwind first, then add the library. (HeroUI's raw CSS can be applied to plain HTML via Tailwind, but its component behavior is React — don't fake it.)
---
The three libraries at a glance
| shadcn/ui | HeroUI v3 | coss ui | |
|---|---|---|---|
| Former name | — | NextUI | Origin UI |
| Primitives | Radix UI (and Base UI option) | React Aria Components | Base UI |
| Styling | Tailwind | Tailwind v4 | Tailwind |
| Distribution | Copy-paste via CLI/registry — you own the source | npm package — a living, auto-updating library | Copy-paste — you own the source |
| You maintain the code? | Yes (it's in your repo) | No (you update the package) | Yes (it's in your repo) |
| License | MIT | Apache 2.0 | open source (COSS) |
| Maturity | Very mature, huge ecosystem | Stable, production-ready | Early access / beta (Base UI also beta) |
| Best when | You want full control + the biggest registry ecosystem | You want polish out-of-the-box with zero maintenance | You want dense, production-grade Cal.com-style UI and you're OK with churn |
Copy-paste vs package, in one line: copy-paste (shadcn, coss ui) = maximum control, you edit files directly, you own upgrades. Package (HeroUI) = minimum maintenance, you npm update and bug fixes/new features arrive for free, but customization is via props/CSS vars/slots rather than editing source.
---
How each one helps the agent (and how to look things up)
shadcn/ui — the registry + CLI + MCP model
What it gives you: a CLI that copies a component's source into your project, plus a registry system so the same workflow pulls from the official registry, third-party registries, or a private one. This is the single biggest lever for "reduce agent work" because the agent never writes the component — it requests it by name and gets correct, accessible source.
Where to look things up (in priority order): 1. MCP server (best for AI): add to the project's MCP config and drive it with natural language.
// .mcp.json (Claude Code / Codex / Cursor / VS Code all supported)
{ "mcpServers": { "shadcn": { "command": "npx", "args": ["shadcn@latest", "mcp"] } } }Then prompt: "list components in the shadcn registry", "add button, dialog, card", "build a login form from shadcn". The MCP bridges your assistant ↔ registry ↔ CLI. 2. CLI (works without MCP): npx shadcn@latest init once, then npx shadcn@latest add <component> (e.g. add button card dialog). For namespaced/third-party registries: npx shadcn add @<registry>/<component>. 3. Docs site for the current component API and examples: https://ui.shadcn.com/docs/components/<name> — read this for props/anatomy before wiring, do not guess. 4. Registry directory (browse what's installable, incl. third-party): https://ui.shadcn.com/docs/directory. 5. Registries config lives in components.json under "registries" — multiple sources, private ones via "headers": { "Authorization": "Bearer ${TOKEN}" }.
Workflow: init → discover via MCP/directory → add the components you need → read the docs page for each component's props → compose. Never hand-write a shadcn component.
HeroUI v3 — the package + llms.txt + MCP model
What it gives you: a maintained npm package of polished, accessible React components (React Aria under the hood). Because it's a package, you don't carry or maintain component source — you import and update. "Beautiful by default" means less time spent styling.
Where to look things up: 1. Quick start / install: https://heroui.com/docs/react/getting-started (and quick-start). Install @heroui/react (or per-component packages to shrink the CSS bundle). Needs Tailwind CSS v4 + React 19. 2. `llms.txt` — HeroUI publishes an AI-readable index of the library. Fetch it to get an accurate, current map of components and APIs instead of relying on memory. (Linked from the docs; check heroui.com for the current llms.txt path.) 3. MCP server — HeroUI ships an MCP for code generation; configure it the same way as shadcn's and ask for components by name. 4. Per-component docs: https://heroui.com/docs/components/<name> — read for props, slots, and the isDisabled/onPress React-Aria-style API conventions before using. 5. Plain HTML escape hatch: the CSS can be applied to plain HTML (see HeroUI's Tailwind Play example) — useful if you want HeroUI's look in a non-React page, but you lose the component behavior.
Workflow: install package → fetch llms.txt (or use MCP) to confirm the component exists and its current props → import + use. Customize via Tailwind utilities, CSS variables, BEM-style modifiers, or by composing the component's parts/slots.
coss ui (Origin UI) — copy-paste, Base UI, layered model
What it gives you: copy-paste components built on Base UI (not Radix), styled with Tailwind — the design system Cal.com is adopting. Explicitly written to be "clear, readable, predictable" so LLMs can reason about and modify them. Good when you want dense, production-grade UI and are comfortable with beta churn.
Its layered model (pick the abstraction you need):
- Primitives — unstyled, accessible Base UI building blocks (the foundation).
- Particles — pre-assembled patterns (auth forms, tables, date pickers) —
https://coss.com/ui/particles. - Atoms — API-enhanced particles that wire UI to real data/services (e.g. Cal.com scheduling) —
https://cal.com/atoms.
Where to look things up: 1. Docs / intro: https://coss.com/ui/docs. 2. Component search: https://coss.com/ui (and the search page) to find a component, then copy its current source. 3. Migration guide if coming from shadcn/Radix: https://coss.com/ui/docs/radix-shadcn-migration. 4. Base UI docs for the underlying primitive behavior/props: https://base-ui.com/.
Workflow: search the component on coss.com → copy the current source into your repo → adjust. Because it's early access + Base UI is beta, re-check the docs each time rather than trusting an earlier copy.
---
Decision shortcut
Need a React app with components?
├─ Want zero maintenance, polished defaults, just update a package → HeroUI
├─ Want to own/edit every component + the largest registry ecosystem → shadcn/ui
└─ Want Cal.com-style dense production UI on Base UI (OK with beta) → coss ui
Single-file preview / no build step → Track A (hand-built, design-process.md)When the user names a library, use it. When they don't and a build step is justified, default to shadcn/ui (largest ecosystem, MCP + CLI make it the lowest-effort for an agent) unless "zero maintenance" or "Cal.com look" points elsewhere.
---
Non-negotiables when using any library
- Look up before you wire. Open the component's current docs page (or MCP/
llms.txt) and confirm props/anatomy. Do not write component code from memory. - One library per project. Don't mix shadcn + HeroUI component sets; you'll get clashing tokens and duplicated primitives.
- Taste still comes from you. The library gives correct, accessible components; it does NOT give a point of view. Apply the palette, typography, layout rhythm, anti-slop and copy rules from
design-process.mdon top — otherwise every library app looks identically generic. - Theme via the library's tokens, not ad-hoc hex. shadcn → CSS variables in
globals.css; HeroUI → its theme/CSS vars + Tailwind; coss ui → its token layer. Keep the Track-A color discipline (no AI-default blue/purple, scene-anchored dark) but express it through the library's theming system. - Verify it renders. After scaffolding, actually start the dev server / build and check the preview. A component that imports but throws at runtime is not done.
Component Design Reference
Rules for building UI components. These are constraints and quality standards — not templates to copy. Implement each component fresh based on your design direction.
---
Navigation
Sidebar Navigation
- Width: 240-280px, fixed position, full viewport height
- Items: icon (20px) + label, 10-12px vertical padding per item
- Active state: must be visually obvious — background highlight, accent color, or bold text. Pick one approach and commit.
- Mobile: hide sidebar off-screen, reveal with hamburger toggle. Use
transform: translateXfor the slide animation. - Dividers between nav groups, not between every item
Top Navigation
- Height: 64-72px (the most common range across 73 major brands; max 80px). Never let the nav eat >10% of the viewport.
- Must render on a single line at desktop (1024px). If items don't fit, condense labels or use hamburger.
- Sticky with
backdrop-filter: bluron scroll - Logo left, nav links center or left, actions right
- Active link: distinct from hover state (different treatment)
- Mobile: collapse nav links into hamburger menu
General Nav Rules
- Never mix sidebar + bottom nav + top nav at the same hierarchy level
- Active state must be visible without relying on color alone
- Navigation placement stays the same across all pages
Navigation Anti-Example
A top nav with a blurred sticky bar, centered logo, and hamburger on the right looks polished — but when every AI-generated page uses the exact same pattern, it becomes a tell. Vary: logo position, nav link placement (left-aligned vs centered vs right), sticky behavior (always sticky vs sticky-after-scroll vs static), and mobile treatment (hamburger vs bottom tab bar vs slide-out drawer).
---
Hero Sections
The hero is the first thing users see. It sets the tone for the entire page.
Structure Discipline
- Maximum 4 text elements in the hero stack. Common combinations:
- Heading + subheading + CTA (3 elements)
- Eyebrow + heading + subheading + CTA (4 elements — the maximum)
- Heading + CTA (2 elements — bold and minimal)
- More than 4 text elements creates visual noise and decision paralysis.
Viewport Fit
- The hero should fill the viewport on load. The primary CTA must be visible without scrolling at 768px viewport height.
- Top padding should not exceed 20vh. Excessive padding pushes content below the fold.
Layout Variety
- Not every hero needs to be centered. Consider:
- Left-aligned text with right-side visual
- Split-screen (text left, image/visual right)
- Asymmetric layout with off-center text
- Full-bleed image with overlaid text
- Editorial style with large typography and minimal imagery
- Choose based on the Design Read, not habit. If you always default to centered or always default to split-screen, you're creating a pattern.
Hero Anti-Patterns
- ❌ Centered heading + 3 equal feature cards below (the #1 AI layout)
- ❌ Hero with more than 4 text elements
- ❌ CTA below the fold at 768px height
- ❌ Div-based fake screenshots as hero images
- ❌ Generic stock photo backgrounds
Hero Anti-Example
A split-screen hero (text left, gradient orb right) with a geometric sans heading and a single CTA button looks premium — until you realize it's the go-to "anti-centered-hero" that most AI agents converge on. If you find yourself building this exact layout, ask: could this hero be editorial (large serif, minimal imagery)? Could it be full-bleed image with overlaid text? Could it be asymmetric with off-center positioning?
---
Cards
Design Rules
border-radius: 8-16px maximum (12px is the most common across 73 major brands). Never 24px+ on cards — that's the AI tell.- Choose ONE card treatment and use it consistently: border only, shadow only, or background contrast. Never combine thick border + heavy shadow. Real brand trend: 60% of major brands prefer hairline borders (1px) over drop shadows for card elevation. Shadows are used sparingly, mainly on hover or for floating elements.
- Shadows should be subtle: max blur 16px, low opacity. Heavy shadows look dated.
- Hover: subtle lift (
translateY(-2px)) or border color change. Not both. - Padding: 20-28px. Consistent within the same card type.
- Cards are not the answer to everything. Consider: tables for tabular data, inline lists for simple items, sections with dividers for sequential content.
Card Anti-Example
Three equal-width cards in a row with an icon on top, a heading, and a short description is the single most common AI card layout. It looks "clean" but is instantly recognizable as generated. Vary: card sizes (span 2 columns for the featured item), mix cards with non-card elements (inline stats, pull quotes), or replace the card grid entirely with a different pattern (accordion, timeline, comparison table).
Stat/KPI Cards
- Structure: label (small, muted) → value (large, bold, tabular-nums) → change indicator (badge with color)
- Value should be the visually dominant element
- Change badges: green for positive, red for negative. Include direction arrow or +/- sign — don't rely on color alone.
- Optional: sparkline or mini chart below the value
Content Cards
- Structure: optional icon/image → title → description → optional action
- Don't make every card the same size. Vary grid spans for visual interest.
- If you have 3+ cards in a row that look identical, reconsider the layout.
---
Buttons & CTAs
Button Design
- Primary: filled background with accent color. One primary button per view. Real brand trend: ~25% of major brands (Nike, Uber, Figma, Shopify, Expo, Intercom) use pure black as their primary CTA color — a confident, editorial choice. ~40% use pill-shaped buttons (border-radius: 9999px), ~30% use sharp corners (0-8px). Commit to one shape system, don't mix.
- Secondary: outlined or ghost (transparent bg + border). For secondary actions.
- Hover: brightness shift or color darken. Not a completely different color.
- Active/press:
scale(0.97-0.98)for tactile feedback - Disabled: reduced opacity (0.4-0.5) +
cursor: not-allowed - Loading: disable button + show inline spinner. Never let users double-submit.
- Labels: verb + object ("Save changes", "Export data"). Not just "Submit" or "OK".
- Icon buttons: minimum 36×36px touch target. Include
aria-label.
CTA Discipline
- No duplicate intent: Two CTAs on the same page must not say the same thing. "Get Started" in the hero and "Get Started" in the footer = duplicate intent. Differentiate: "Start free trial" vs "See pricing".
- Button text wrapping: CTA text must never wrap to two lines. If it wraps, shorten the text or increase the button's min-width.
- Contrast check: Primary CTA must have ≥ 4.5:1 contrast between text and button background. Test this explicitly.
- One primary per viewport: At any scroll position, only one primary-styled button should be visible. Multiple competing primaries dilute the call to action.
CTA Anti-Example
A rounded pill button with a gradient background and a right-arrow icon (→) has become the AI-default "premium CTA". If you catch yourself building this, consider: a sharp-cornered button with no icon, a text-link CTA with an underline animation, a ghost button with a bold border, or a button that uses the page's accent color as a flat fill without gradients.
---
Tables
- Use
font-variant-numeric: tabular-numsfor number columns — prevents layout shift - Header row: smaller font, uppercase or muted color, sticky if table is long
- Row hover: subtle background change
- Align numbers and currency to the right
- Wrap table in a container with
overflow-x: autofor mobile - Zebra striping is optional — if used, keep the contrast very subtle
- Don't truncate important data. If columns don't fit, prioritize which columns to show on mobile.
---
Badges & Status
- Shape: pill (
border-radius: 999px) or rounded rect - Size: small (font-size 11-12px, padding 2px 8px)
- Semantic colors: green=success, amber=warning, red=error, gray=neutral
- Always pair color with text label or icon — never color alone (accessibility)
- Don't overuse badges. If everything has a badge, nothing stands out.
---
Forms
- Every input must have a visible
<label>. Never use placeholder as the only label. - Input height: 40-44px for comfortable touch targets
- Focus state: accent-colored border + subtle ring shadow. Must be visible.
- Error messages: below the field, in red/error color, with specific guidance ("Email must include @")
- Group related fields visually (fieldset or spacing)
- Required fields: mark with asterisk or "(required)" text
- Submit button: disabled until form is valid, with loading state during submission
Form Anti-Example
Rounded input fields with a light gray background, no visible border, and a floating label that animates up on focus — this pattern is clean but has become the default AI form style. Vary: use bordered inputs with a visible 1px border, use underline-only inputs for minimal aesthetics, or use a traditional label-above-input layout. The "right" choice depends on the Design Read, not on what looks most modern.
---
Loading States
- Use skeleton placeholders that match the shape of the content they replace
- Skeleton animation: horizontal shimmer (gradient sweep), not pulsing opacity
- Show skeletons immediately — don't show a blank screen then suddenly populate
- For actions (button clicks, form submits): inline spinner or progress indicator
- If loading takes >3 seconds: show a message explaining what's happening
---
Empty States
- Never show a blank area. Always show:
1. An icon or illustration (subtle, not dominant) 2. A clear title ("No projects yet") 3. A helpful description ("Create your first project to get started") 4. A primary action button
- Empty states are an opportunity to guide the user, not just fill space
---
Tooltips & Popovers
- Appear on hover (desktop) or tap (mobile)
- Position: above the trigger by default, flip if near viewport edge
- Animation: fade + slight translateY, quick timing
- Dismiss: on mouse leave or click outside
- Keep text short (1-2 lines max)
- Use
aria-describedbyfor accessibility
---
Modals & Drawers
- Overlay: semi-transparent dark backdrop with optional
backdrop-filter: blur - Modal: centered, scale from slightly smaller + fade in
- Drawer: slides from edge
- Always provide a close button AND clicking the overlay to dismiss
- Trap focus inside the modal while open
- Exit animation should be faster than enter
---
Icons
- Use ONE icon library per project. Don't mix Lucide with Heroicons with Phosphor.
- Consistent stroke width across all icons
- Sizes: 16px (inline text), 20px (buttons), 24px (navigation)
- Never use emoji as structural icons (navigation, status, actions)
- Emoji is acceptable only in user-generated content or deliberately playful contexts
---
Data Display
- Numbers: always use
font-variant-numeric: tabular-numsin data contexts - Currency: include symbol, use locale-appropriate formatting
- Percentages: include % sign, color-code positive/negative
- Dates: use relative time for recent ("2 hours ago"), absolute for older ("Jan 15, 2026")
- Large numbers: abbreviate with K/M/B suffix (e.g., "12.4K" not "12,400")
- Trend indicators: up/down arrow + color. Green=up is not always correct — for costs, up=red.
Dashboards — data, real-time, layout, performance
Use this when the visual output is a multi-panel monitoring view (portfolio, price tracker, system health, multi-asset comparison). It is the use-case layer on top of the general design gate. Charts setup lives in charts.md; visual taste lives in design-process.md.
Golden rule: build the simplest dashboard that meets the requirement. Don't over-engineer.
---
1. Find the data first (before any UI)
Check Starchild's own data sources before searching outside
Starchild proxies many paid APIs for free (credentials injected by sc-proxy). Prefer a skill over raw HTTP whenever one exists — it has the right endpoints, auth, and quirks:
- Crypto spot/markets →
coingecko· derivatives (funding/OI/liq) →coinglass· unlocks →tokenomist - Stocks/forex/commodities →
twelvedata(prices/K-line),us-stock/cn-stock(fundamentals) - TA indicators →
taapi· DeFi TVL/yields →defillama· on-chain/wallets →debank,birdeye - Options →
massive-options-data
To see what HTTP APIs are proxied directly (for scripts), read core/http_client.py (DEFAULT_PROXIED_APIS, DOMAIN_TO_API_TYPE). Always route script calls through from core.http_client import proxied_get, proxied_post and add a SC-CALLER-ID header for cost tracking. Never fabricate numbers — every figure on a dashboard must come from a real call.
Premium vs free — do the rate-limit math, don't guess
daily_calls = (60 / update_interval_minutes) * 24 * num_assetsExample: 5 assets, every 2 min → 30/hr × 24 × 5 = 3,600 calls/day. If that exceeds the quota, the dashboard breaks silently — switch to a lower frequency or a free no-auth source. Decision order of preference for browser dashboards: no-auth > API key > OAuth. Use premium/Starchild APIs for medium/low frequency and historical OHLC; research a free alternative for high-frequency or public-facing dashboards.
When researching free APIs: check github.com/public-apis/public-apis first, prefer 2025-2026-maintained sources, verify CORS works in-browser, and test an endpoint before trusting a blog post. Red flags: last commit 2+ years ago, unclear limits, "free tier" needing a credit card, region locks.
---
2. Architecture
- Quick static preview (most common): HTML + CSS + JS files (split for maintainability), Tailwind via CDN, Chart.js via CDN, fetch on a timer. Apply the full Track-A design gate. Served by the static
preview. - Real app: Vite/Next + a component library (
component-libraries.md) for the shell (sidebar, cards, tables), Chart.js/ECharts/ApexCharts for viz. Needs apreviewwithcommand+port. - Backend needed only when you require SSE/WebSocket or server-side aggregation — otherwise keep it client-side.
Whatever the stack, drive every panel from one fetch cycle that returns a single data object, then update cards/charts from it. One source of truth, one refresh path.
---
3. Real-time updates
| Mechanism | Use when | Notes |
|---|---|---|
Polling (setInterval + fetch) | Default for client-only dashboards; low/medium frequency | Simplest, most compatible. Always do an initial fetch immediately, then interval. |
SSE (EventSource) | Server-to-client streaming, you control a backend | Auto-reconnects, one-way, simpler than WebSocket for dashboards. Format: event: name\ndata: {json}\n\n. |
| WebSocket | True bidirectional or sub-second latency (trading) | More work (reconnect logic); only when polling/SSE genuinely aren't enough. |
For real-time chart updates, push the new point, cap history (e.g. keep last 20-30 points by shift()-ing), and call the chart's update with animation disabled (chart.update('none')) to avoid jank.
---
4. Layout & UX (dashboard-specific)
- Visual hierarchy: most-critical metric top-left (natural eye flow), secondary top-right, detail charts center/below, filters in a top bar or sidebar.
- Responsive grid: mobile-first — KPI cards stack to one column < 768px, 2-up tablet, 3-4-up desktop. Use CSS Grid; let a wide chart
grid-column: span 2. - KPI cards: label + big value (
font-variant-numeric: tabular-nums) + signed delta with color and an arrow/word (never color alone). Don't fake precision — round sensibly and label mock data as mock. - States are mandatory: every panel needs a loading state (skeleton, not just a spinner), an error state with a retry, and an empty state with a helpful message. A dashboard that shows
0or blank on fetch failure is a bug. - Density: dashboards earn the right to be denser than landing pages, but still respect spacing rhythm and contrast from
design-process.md. Status colors must pass contrast and pair with icon/text.
---
5. Performance
- Debounce
resizebefore callingchart.resize()(~250ms). - Decimate large series to ~100-200 points before plotting.
- Lazy-init off-screen charts with
IntersectionObserver. - Cache fetched data with a short TTL (e.g. 5 min) so multiple panels reusing the same source don't multiply API calls.
- In a
previewiframe, heavy real-time canvas work can freeze the tab — throttle update frequency and keep point counts bounded.
---
6. Deployment / sharing
- Local view →
preview(static for single-file;command+portfor built apps). - Public URL on Telegram/WeChat or for sharing → use the
community-publishskill (publish_preview), never hand-roll hosting. - Use relative asset paths in preview HTML (
./static/app.js, not/static/app.js) — the proxy serves under/preview/{id}/.
Design Process — Engineering Quality Gate (Track A: hand-built UI)
This file defines engineering implementation quality for hand-built HTML/CSS/JS.
Style direction is provided via ui-design's Taste Overlay Contract:
- Brief Inference
- Design Dials
- Anti-slop hard rules
Implement style from taste-skill first, then validate with this engineering gate.
---
Scope
ui-design owns:
- accessibility implementation
- theme mechanics (light/dark)
- responsive stability
- interaction-state reliability
- runtime correctness and delivery checklist
taste-skill overlay owns:
- style inference and art direction
- layout variation strategy
- visual density and motion intensity style targets
- anti-template/anti-slop style filtering
---
Mandatory workflow (Track A)
1. Resolve style using taste-skill overlay in ui-design flow. 2. If the page is interactive, write a motion plan before implementation. 3. Build HTML/CSS/JS. 4. Validate against this engineering gate. 5. Run final taste anti-slop check. 6. Deliver only after both gates pass.
Motion plan requirement for interactive pages
For any interactive UI (buttons, tabs, dropdowns, drawers, modals, sortable lists, drag/swipe gestures), motion is mandatory and must include:
- purpose per motion (feedback, state change, orientation, continuity)
- frequency-aware decision (high-frequency actions should be near-instant or unanimated)
- easing and duration choice (avoid default/browser-generic feel)
- reduced-motion fallback
No motion plan = incomplete implementation.
---
Required implementation baseline
1) Document and structure
- Valid
<!doctype html>,charset,viewport - Semantic landmarks where applicable (
header,main,nav,section,footer) - One clear
h1; heading order must be sequential
2) Theme system (mandatory)
- Support both light and dark themes
- Use CSS custom properties for color tokens
- Theme toggle persists in
localStorage - Initial theme respects
prefers-color-schemeif no saved choice - Both themes fully usable (not invert-only)
3) Accessibility baseline (mandatory)
- Body text contrast >= 4.5:1
- Large text / UI controls >= 3:1
- Visible keyboard focus on all interactive elements
- Icon-only buttons require
aria-label - Inputs require visible
<label> - Color is never the only status signal
- Touch targets >= 44×44 on mobile
- Meaningful images require
alt(decorative usealt="")
4) Responsive stability
- No horizontal overflow at 375px width
- Avoid mobile viewport jump: use
100dvhwhere full-height is required - Layout degrades gracefully desktop → mobile
5) Interaction reliability
- Never use
transition: all - Animate safe properties for common UI (
transform,opacity) - Deterministic states: default / hover / active / disabled / loading
- For interactive pages, include tactile motion feedback (e.g., press scale, state transition, enter/exit transition)
- For actions >300ms, show loading feedback (skeleton preferred)
- Keyboard-triggered high-frequency actions should be instant or near-instant (avoid decorative animation)
6) Motion safety
- Respect
prefers-reduced-motion: reduce - Reduce or disable non-essential motion when requested
7) Forms and feedback
- Required fields visibly marked
- Validation errors shown near related fields
- Destructive actions require confirmation
- Success/error feedback explicit after submit actions
---
Charts / data UI (if present)
- Theme-aware chart colors (token-driven)
- Theme switch refreshes chart palette correctly
- Axes/tooltips/legends readable in both themes
- Never use fabricated production data
---
Technical hard-fail list
- Missing dark theme or broken theme toggle
- Contrast below threshold for core text/UI
- No visible keyboard focus
- Horizontal overflow on mobile
- Broad use of
transition: all - Missing disabled/loading behavior on actionable controls
- Icon-only controls without labels
- Interactive page shipped with no motion feedback for interactions/state changes
---
Pre-delivery checklist (blocking)
Accessibility
- [ ] Contrast passes (body >=4.5:1, large/UI >=3:1)
- [ ] Keyboard focus visible and usable
- [ ] Heading hierarchy valid with one
h1 - [ ] Inputs have visible labels
- [ ] Icon-only controls have
aria-label - [ ] Touch targets >=44×44 on mobile
Theme
- [ ] Light/dark toggle works
- [ ] Theme preference persists via
localStorage - [ ]
prefers-color-schemedefault works - [ ] Both themes readable and complete
Responsive
- [ ] No horizontal scroll at 375px
- [ ] Full-height areas use
100dvhwhere needed - [ ] Core interactions usable on desktop and mobile
Motion / interaction
- [ ] Reduced-motion path implemented
- [ ] No
transition: all - [ ] Hover/active/disabled/loading states are clear
- [ ] Interactive pages include tactile feedback + state-transition motion
- [ ] High-frequency keyboard actions are instant or nearly instant
Runtime quality
- [ ] No broken asset references
- [ ] No runtime-breaking console errors in core path
- [ ] Key panels handle empty/loading/error states
Related skills
How it compares
Pick ui-design over generic frontend-design skills when projects need an engineering quality gate with explicit accessibility, performance, and project-builder integration rather than style-only guidance.
FAQ
What does ui-design do?
Agent skill for ui-design workflows documented in SKILL.md.
When should I use ui-design?
During operate infra work for cloud & infrastructure.
Is ui-design safe to install?
Review the Security Audits panel on this listing before production use.