
Frontend Design
- 368 installs
- 8.1k repo stars
- Updated August 4, 2026
- vudovn/antigravity-kit
frontend-design is an AI agent skill from vudovn/antigravity-kit that applies anti-slop design thinking, brief inference, and production UI rules for developers building landing pages, portfolios, and web redesigns.
About
frontend-design is a Design & UI/UX skill in the vudovn/antigravity-kit (ag-kit) repository, one of 45 domain skills paired with 20 agent personas. Its 1,221-line SKILL.md teaches agents to read a brief, output a one-line Design Read, tune three dials (DESIGN_VARIANCE, MOTION_INTENSITY, VISUAL_DENSITY), and ship React or Next.js interfaces that avoid generic AI-purple templates. Conditional files cover minimalist, brutalist, and redesign workflows, plus two Python audit scripts (ux_audit.py, accessibility_checker.py). The skill maps briefs to 12 official design systems—including shadcn/ui, Fluent UI, Carbon, GOV.UK Frontend, and Tailwind v4—and defaults to Motion for animation. Developers reach for frontend-design when an agent must design or rebuild marketing sites, portfolios, or SaaS landing pages before coding components and layouts.
- frontend-design
Frontend Design by the numbers
- 368 all-time installs (skills.sh)
- +2 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,157 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vudovn/antigravity-kit --skill frontend-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 368 |
|---|---|
| repo stars | ★ 8.1k |
| Last updated | August 4, 2026 |
| Repository | vudovn/antigravity-kit ↗ |
How do AI agents avoid generic landing page UI?
Use frontend-design for development tasks
Who is it for?
Developers using Claude Code or Cursor who need an AI agent to design distinctive SaaS landing pages, portfolios, or marketing-site redesigns in React or Next.js.
Skip if: Developers building native mobile apps, data-dense dashboards, or teams that only need post-build accessibility linting without design-direction guidance.
When should I use this skill?
A developer asks an agent to design or build web UI—components, layouts, color, typography, landing pages, portfolios, or redesigns—and the task is not a mobile app.
What you get
Design Read summary, dial-tuned layout and typography decisions, React/Next.js component code, and optional UX or accessibility audit reports from Python scripts.
- Design Read one-liner
- React/Next.js UI components
- UX or accessibility audit output
By the numbers
- SKILL.md spans 1,221 lines across 14 sections and 3 appendices
- Bundles 3 conditional reference files and 2 Python audit scripts
- Part of ag-kit with 45 skills, 20 agents, and 13 workflows
Files
Frontend Design System
Philosophy: Every pixel has purpose. Restraint is luxury. User psychology drives decisions.
Core Principle: THINK, don't memorize. ASK, don't assume.
---
🎯 Selective Reading Rule (MANDATORY)
Read REQUIRED files always, OPTIONAL only when needed:
| File | Status | When to Read |
|---|---|---|
| ux-psychology.md | 🔴 REQUIRED | Always read first! |
| color-system.md | ⚪ Optional | Color/palette decisions |
| typography-system.md | ⚪ Optional | Font selection/pairing |
| visual-effects.md | ⚪ Optional | Glassmorphism, shadows, gradients |
| animation-guide.md | ⚪ Optional | Animation needed |
| motion-graphics.md | ⚪ Optional | Lottie, GSAP, 3D |
| decision-trees.md | ⚪ Optional | Context templates |
🔴 ux-psychology.md = ALWAYS READ. Others = only if relevant.
---
🔧 Runtime Scripts
Execute these for audits (don't read, just run):
| Script | Purpose | Usage |
|---|---|---|
scripts/ux_audit.py | UX Psychology & Accessibility Audit | python scripts/ux_audit.py <project_path> |
scripts/accessibility_checker.py | Focused accessibility checks (contrast, ARIA, focus) | python scripts/accessibility_checker.py <project_path> |
---
⚠️ CRITICAL: ASK BEFORE ASSUMING (MANDATORY)
STOP! If the user's request is open-ended, DO NOT default to your favorites.
When User Prompt is Vague, ASK:
Color not specified? Ask:
"What color palette do you prefer? (blue/green/orange/neutral/other?)"
Style not specified? Ask:
"What style are you going for? (minimal/bold/retro/futuristic/organic?)"
Layout not specified? Ask:
"Do you have a layout preference? (single column/grid/asymmetric/full-width?)"
⛔ DEFAULT TENDENCIES TO AVOID (ANTI-SAFE HARBOR):
| AI Default Tendency | Why It's Bad | Think Instead |
|---|---|---|
| Bento Grids (Modern Cliché) | Used in every AI design | Why does this content NEED a grid? |
| Hero Split (Left/Right) | Predictable & Boring | How about Massive Typography or Vertical Narrative? |
| Mesh/Aurora Gradients | The "new" lazy background | What's a radical color pairing? |
| Glassmorphism | AI's idea of "premium" | How about solid, high-contrast flat? |
| Deep Cyan / Fintech Blue | Safe harbor from purple ban | Why not Red, Black, or Neon Green? |
| "Orchestrate / Empower" | AI-generated copywriting | How would a human say this? |
| Dark background + neon glow | Overused, "AI look" | What does the BRAND actually need? |
| Rounded everything | Generic/Safe | Where can I use sharp, brutalist edges? |
🔴 "Every 'safe' structure you choose brings you one step closer to a generic template. TAKE RISKS."
---
1. Constraint Analysis (ALWAYS FIRST)
Before any design work, ANSWER THESE or ASK USER:
| Constraint | Question | Why It Matters |
|---|---|---|
| Timeline | How much time? | Determines complexity |
| Content | Ready or placeholder? | Affects layout flexibility |
| Brand | Existing guidelines? | May dictate colors/fonts |
| Tech | What stack? | Affects capabilities |
| Audience | Who exactly? | Drives all visual decisions |
Audience → Design Approach
| Audience | Think About |
|---|---|
| Gen Z | Bold, fast, mobile-first, authentic |
| Millennials | Clean, minimal, value-driven |
| Gen X | Familiar, trustworthy, clear |
| Boomers | Readable, high contrast, simple |
| B2B | Professional, data-focused, trust |
| Luxury | Restrained elegance, whitespace |
---
2. UX Psychology Principles
Core Laws (Internalize These)
| Law | Principle | Application |
|---|---|---|
| Hick's Law | More choices = slower decisions | Limit options, use progressive disclosure |
| Fitts' Law | Bigger + closer = easier to click | Size CTAs appropriately |
| Miller's Law | ~7 items in working memory | Chunk content into groups |
| Von Restorff | Different = memorable | Make CTAs visually distinct |
| Serial Position | First/last remembered most | Key info at start/end |
Emotional Design Levels
VISCERAL (instant) → First impression: colors, imagery, overall feel
BEHAVIORAL (use) → Using it: speed, feedback, efficiency
REFLECTIVE (memory) → After: "I like what this says about me"Trust Building
- Security indicators on sensitive actions
- Social proof where relevant
- Clear contact/support access
- Consistent, professional design
- Transparent policies
---
3. Layout Principles
Golden Ratio (φ = 1.618)
Use for proportional harmony:
├── Content : Sidebar = roughly 62% : 38%
├── Each heading size = previous × 1.618 (for dramatic scale)
├── Spacing can follow: sm → md → lg (each × 1.618)8-Point Grid Concept
All spacing and sizing in multiples of 8:
├── Tight: 4px (half-step for micro)
├── Small: 8px
├── Medium: 16px
├── Large: 24px, 32px
├── XL: 48px, 64px, 80px
└── Adjust based on content densityKey Sizing Principles
| Element | Consideration |
|---|---|
| Touch targets | Minimum comfortable tap size |
| Buttons | Height based on importance hierarchy |
| Inputs | Match button height for alignment |
| Cards | Consistent padding, breathable |
| Reading width | 45-75 characters optimal |
---
4. Color Principles
60-30-10 Rule
60% → Primary/Background (calm, neutral base)
30% → Secondary (supporting areas)
10% → Accent (CTAs, highlights, attention)Color Psychology (For Decision Making)
| If You Need... | Consider Hues | Avoid |
|---|---|---|
| Trust, calm | Blue family | Aggressive reds |
| Growth, nature | Green family | Industrial grays |
| Energy, urgency | Orange, red | Passive blues |
| Luxury, creativity | Deep Teal, Gold, Emerald | Cheap-feeling brights |
| Clean, minimal | Neutrals | Overwhelming color |
Selection Process
1. What's the industry? (narrows options) 2. What's the emotion? (picks primary) 3. Light or dark mode? (sets foundation) 4. ASK USER if not specified
For detailed color theory: color-system.md
---
5. Typography Principles
Scale Selection
| Content Type | Scale Ratio | Feel |
|---|---|---|
| Dense UI | 1.125-1.2 | Compact, efficient |
| General web | 1.25 | Balanced (most common) |
| Editorial | 1.333 | Readable, spacious |
| Hero/display | 1.5-1.618 | Dramatic impact |
Pairing Concept
Contrast + Harmony:
├── DIFFERENT enough for hierarchy
├── SIMILAR enough for cohesion
└── Usually: display + neutral, or serif + sansReadability Rules
- Line length: 45-75 characters optimal
- Line height: 1.4-1.6 for body text
- Contrast: Check WCAG requirements
- Size: 16px+ for body on web
For detailed typography: typography-system.md
---
6. Visual Effects Principles
Glassmorphism (When Appropriate)
Key properties:
├── Semi-transparent background
├── Backdrop blur
├── Subtle border for definition
└── ⚠️ **WARNING:** Standard blue/white glassmorphism is a modern cliché. Use it radically or not at all.Shadow Hierarchy
Elevation concept:
├── Higher elements = larger shadows
├── Y-offset > X-offset (light from above)
├── Multiple layers = more realistic
└── Dark mode: may need glow insteadGradient Usage
Harmonious gradients:
├── Adjacent colors on wheel (analogous)
├── OR same hue, different lightness
├── Avoid harsh complementary pairs
├── 🚫 **NO Mesh/Aurora Gradients** (floating blobs)
└── VARY from project to project radicallyFor complete effects guide: visual-effects.md
---
7. Animation Principles
Timing Concept
Duration based on:
├── Distance (further = longer)
├── Size (larger = slower)
├── Importance (critical = clear)
└── Context (urgent = fast, luxury = slow)Easing Selection
| Action | Easing | Why |
|---|---|---|
| Entering | Ease-out | Decelerate, settle in |
| Leaving | Ease-in | Accelerate, exit |
| Emphasis | Ease-in-out | Smooth, deliberate |
| Playful | Bounce | Fun, energetic |
Performance
- Animate only transform and opacity
- Respect reduced-motion preference
- Test on low-end devices
For animation patterns: animation-guide.md, for advanced: motion-graphics.md
---
8. "Wow Factor" Checklist
Premium Indicators
- [ ] Generous whitespace (luxury = breathing room)
- [ ] Subtle depth and dimension
- [ ] Smooth, purposeful animations
- [ ] Attention to detail (alignment, consistency)
- [ ] Cohesive visual rhythm
- [ ] Custom elements (not all defaults)
Trust Builders
- [ ] Security cues where appropriate
- [ ] Social proof / testimonials
- [ ] Clear value proposition
- [ ] Professional imagery
- [ ] Consistent design language
Emotional Triggers
- [ ] Hero that evokes intended emotion
- [ ] Human elements (faces, stories)
- [ ] Progress/achievement indicators
- [ ] Moments of delight
---
9. Anti-Patterns (What NOT to Do)
❌ Lazy Design Indicators
- Default system fonts without consideration
- Stock imagery that doesn't match
- Inconsistent spacing
- Too many competing colors
- Walls of text without hierarchy
- Inaccessible contrast
❌ AI Tendency Patterns (AVOID!)
- Same colors every project
- Dark + neon as default
- Purple/violet as the default (use it only with intent)
- Bento grids for simple landing pages
- Mesh Gradients & Glow Effects
- Same layout structure / Vercel clone
- Not asking user preferences
❌ Dark Patterns (Unethical)
- Hidden costs
- Fake urgency
- Forced actions
- Deceptive UI
- Confirmshaming
---
10. Decision Process Summary
For EVERY design task:
1. CONSTRAINTS
└── What's the timeline, brand, tech, audience?
└── If unclear → ASK
2. CONTENT
└── What content exists?
└── What's the hierarchy?
3. STYLE DIRECTION
└── What's appropriate for context?
└── If unclear → ASK (don't default!)
4. EXECUTION
└── Apply principles above
└── Check against anti-patterns
5. REVIEW
└── "Does this serve the user?"
└── "Is this different from my defaults?"
└── "Would I be proud of this?"---
Reference Files
For deeper guidance on specific areas:
- color-system.md - Color theory and selection process
- typography-system.md - Font pairing and scale decisions
- visual-effects.md - Effects principles and techniques
- animation-guide.md - Motion design principles
- motion-graphics.md - Advanced: Lottie, GSAP, SVG, 3D, Particles
- decision-trees.md - Context-specific templates
- ux-psychology.md - User psychology deep dive
---
Related Skills
| Skill | When to Use |
|---|---|
| frontend-design (this) | Before coding - Learn design principles (color, typography, UX psychology) |
| [web-design-guidelines](../web-design-guidelines/SKILL.md) | After coding - Audit for accessibility, performance, and best practices |
Post-Design Workflow
After implementing your design, run the audit:
1. DESIGN → Read frontend-design principles ← YOU ARE HERE
2. CODE → Implement the design
3. AUDIT → Run web-design-guidelines review
4. FIX → Address findings from auditNext Step: After coding, use web-design-guidelines skill to audit your implementation for accessibility, focus states, animations, and performance issues.---
Remember: Design is THINKING, not copying. Every project deserves fresh consideration based on its unique context and users. Avoid the Modern SaaS Safe Harbor!
Animation Guidelines Reference
Animation principles and timing psychology - learn to decide, not copy.
No fixed durations to memorize - understand what affects timing.
---
1. Duration Principles
What Affects Timing
Factors that determine animation speed:
├── DISTANCE: Further travel = longer duration
├── SIZE: Larger elements = slower animations
├── COMPLEXITY: Complex = slower to process
├── IMPORTANCE: Critical actions = clear feedback
└── CONTEXT: Urgent = fast, luxurious = slowDuration Ranges by Purpose
| Purpose | Range | Why |
|---|---|---|
| Instant feedback | 50-100ms | Below perception threshold |
| Micro-interactions | 100-200ms | Quick but noticeable |
| Standard transitions | 200-300ms | Comfortable pace |
| Complex animations | 300-500ms | Time to follow |
| Page transitions | 400-600ms | Smooth handoff |
| Wow/Premium Effects | 800ms+ | Dramatic, organic spring-based, layered |
Choosing Duration
Ask yourself: 1. How far is the element moving? 2. How important is it to notice this change? 3. Is the user waiting, or is this background?
---
2. Easing Principles
What Easing Does
Easing = how speed changes over time
├── Linear: constant speed (mechanical, robotic)
├── Ease-out: fast start, slow end (natural entry)
├── Ease-in: slow start, fast end (natural exit)
└── Ease-in-out: slow both ends (smooth, deliberate)When to Use Each
| Easing | Best For | Feels Like |
|---|---|---|
| Ease-out | Elements entering | Arriving, settling |
| Ease-in | Elements leaving | Departing, exiting |
| Ease-in-out | Emphasis, loops | Deliberate, smooth |
| Linear | Continuous motion | Mechanical, constant |
| Bounce/Elastic | Playful UI | Fun, energetic |
The Pattern
/* Entering view = ease-out (decelerate) */
.enter {
animation-timing-function: ease-out;
}
/* Leaving view = ease-in (accelerate) */
.exit {
animation-timing-function: ease-in;
}
/* Continuous = ease-in-out */
.continuous {
animation-timing-function: ease-in-out;
}---
3. Micro-Interaction Principles
What Makes Good Micro-Interactions
Purpose of micro-interactions:
├── FEEDBACK: Confirm the action happened
├── GUIDANCE: Show what's possible
├── STATUS: Indicate current state
└── DELIGHT: Small moments of joyButton States
Hover → slight visual change (lift, color, scale)
Active → pressed feeling (scale down, shadow change)
Focus → clear indicator (outline, ring)
Loading → progress indicator (spinner, skeleton)
Success → confirmation (check, color)Principles
1. Respond immediately (under 100ms perception) 2. Match the action (press = scale(0.95), hover = translateY(-4px) + glow) 3. Be bold but smooth (make it feel crafted) 4. Be consistent (same actions = same feedback)
---
4. Loading States Principles
Types by Context
| Situation | Approach |
|---|---|
| Quick load (<1s) | No indicator needed |
| Medium (1-3s) | Spinner or simple animation |
| Long (3s+) | Progress bar or skeleton |
| Unknown duration | Indeterminate indicator |
Skeleton Screens
Purpose: Reduce perceived wait time
├── Show layout shape immediately
├── Animate subtly (shimmer, pulse)
├── Replace with content when ready
└── Feels faster than spinnerProgress Indicators
When to show progress:
├── User-initiated action
├── File uploads/downloads
├── Multi-step processes
└── Long operations
When NOT needed:
├── Very quick operations
├── Background tasks
└── Initial page loads (skeleton better)---
5. Page Transitions Principles
Transition Strategy
Simple rule: exit fast, enter slower
├── Outgoing content fades quickly
├── Incoming content animates in
└── Avoids "everything moving at once"Common Patterns
| Pattern | When to Use |
|---|---|
| Fade | Safe default, works everywhere |
| Slide | Sequential navigation (prev/next) |
| Scale | Opening/closing modals |
| Shared element | Maintaining visual continuity |
Direction Matching
Navigation direction = animation direction
├── Forward → slide from right
├── Backward → slide from left
├── Deeper → scale up from center
├── Back up → scale down---
6. Scroll Animation Principles
Progressive Reveal
Content appears as user scrolls:
├── Reduces initial cognitive load
├── Rewards exploration
├── Must not feel sluggish
└── Option to disable (accessibility)Trigger Points
| When to Trigger | Effect |
|---|---|
| Just entering viewport | Standard reveal |
| Centered in viewport | For emphasis |
| Partially visible | Earlier reveal |
| Fully visible | Late trigger |
Animation Properties
- Fade in (opacity)
- Slide up (transform)
- Scale (transform)
- Combination of above
Performance
- Use Intersection Observer
- Animate only transform/opacity
- Reduce on mobile if needed
---
7. Hover Effects Principles
Matching Effect to Action
| Element | Effect | Intent |
|---|---|---|
| Clickable card | Lift + shadow | "This is interactive" |
| Button | Color/brightness change | "Press me" |
| Image | Zoom/scale | "View closer" |
| Link | Underline/color | "Navigate here" |
Principles
1. Signal interactivity - hover shows it's clickable 2. Don't overdo it - subtle changes work 3. Match importance - bigger change = more important 4. Touch alternatives - hover doesn't work on mobile
---
8. Feedback Animation Principles
Success States
Celebrate appropriately:
├── Minor action → subtle check/color
├── Major action → more pronounced animation
├── Completion → satisfying animation
└── Match brand personalityError States
Draw attention without panic:
├── Color change (semantic red)
├── Shake animation (brief!)
├── Focus on error field
└── Clear messagingTiming
- Success: slightly longer (enjoy the moment)
- Error: quick (don't delay action)
- Loading: continuous until complete
---
9. Performance Principles
What's Cheap to Animate
GPU-accelerated (FAST):
├── transform: translate, scale, rotate
└── opacity: 0 to 1
CPU-intensive (SLOW):
├── width, height
├── top, left, right, bottom
├── margin, padding
├── border-radius changes
└── box-shadow changesOptimization Strategies
1. Animate transform/opacity whenever possible 2. Avoid layout triggers (size/position changes) 3. Use will-change sparingly (hints to browser) 4. Test on low-end devices (not just dev machine)
Respecting User Preferences
@media (prefers-reduced-motion: reduce) {
/* Honor this preference */
/* Essential animations only */
/* Reduce or remove decorative motion */
}---
10. Animation Decision Checklist
Before adding animation:
- [ ] Is there a purpose? (feedback/guidance/delight)
- [ ] Is timing appropriate? (not too fast/slow)
- [ ] Did you pick correct easing? (enter/exit/emphasis)
- [ ] Is it performant? (transform/opacity only)
- [ ] Tested reduced motion? (accessibility)
- [ ] Consistent with other animations? (same timing feel)
- [ ] Not your default settings? (variety check)
- [ ] Asked user about style if unclear?
Anti-Patterns
- ❌ Same timing values every project
- ❌ Animation for animation's sake
- ❌ Ignoring reduced-motion preference
- ❌ Animating expensive properties
- ❌ Too many things animating at once
- ❌ Delays that frustrate users
---
Remember: Animation is communication. Every motion should have meaning and serve the user experience.
Color System Reference
Color theory principles, selection process, and decision-making guidelines.
No memorized hex codes - learn to THINK about color.
---
1. Color Theory Fundamentals
The Color Wheel
YELLOW
│
Yellow- │ Yellow-
Green │ Orange
╲ │ ╱
╲ │ ╱
GREEN ─────────── ● ─────────── ORANGE
╱ │ ╲
╱ │ ╲
Blue- │ Red-
Green │ Orange
│
RED
│
PURPLE
╱ ╲
Blue- Red-
Purple Purple
╲ ╱
BLUEColor Relationships
| Scheme | How to Create | When to Use |
|---|---|---|
| Monochromatic | Pick ONE hue, vary only lightness/saturation | Minimal, professional, cohesive |
| Analogous | Pick 2-3 ADJACENT hues on wheel | Harmonious, calm, nature-inspired |
| Complementary | Pick OPPOSITE hues on wheel | High contrast, vibrant, attention |
| Split-Complementary | Base + 2 colors adjacent to complement | Dynamic but balanced |
| Triadic | 3 hues EQUIDISTANT on wheel | Vibrant, playful, creative |
How to Choose a Scheme:
1. What's the project mood? Calm → Analogous. Bold → Complementary. 2. How many colors needed? Minimal → Monochromatic. Complex → Triadic. 3. Who's the audience? Conservative → Monochromatic. Young → Triadic.
---
2. The 60-30-10 Rule
Distribution Principle
┌─────────────────────────────────────────────────┐
│ │
│ 60% PRIMARY (Background, large areas) │
│ → Should be neutral or calming │
│ → Carries the overall tone │
│ │
├────────────────────────────────────┬────────────┤
│ │ │
│ 30% SECONDARY │ 10% ACCENT │
│ (Cards, sections, headers) │ (CTAs, │
│ → Supports without dominating │ highlights)│
│ │ → Draws │
│ │ attention│
└────────────────────────────────────┴────────────┘Implementation Pattern
:root {
/* 60% - Pick based on light/dark mode and mood */
--color-bg: /* neutral: white, off-white, or dark gray */
--color-surface: /* slightly different from bg */
/* 30% - Pick based on brand or context */
--color-secondary: /* muted version of primary or neutral */
/* 10% - Pick based on desired action/emotion */
--color-accent: /* vibrant, attention-grabbing */
}---
3. Color Psychology - Meaning & Selection
How to Choose Based on Context
| If Project Is... | Consider These Hues | Why |
|---|---|---|
| Finance, Tech, Healthcare | Blues, Teals | Trust, stability, calm |
| Eco, Wellness, Nature | Greens, Earth tones | Growth, health, organic |
| Food, Energy, Youth | Orange, Yellow, Warm | Appetite, excitement, warmth |
| Luxury, Beauty, Creative | Deep Teal, Gold, Black | Sophistication, premium |
| Urgency, Sales, Alerts | Red, Orange | Action, attention, passion |
Emotional Associations (For Decision Making)
| Hue Family | Positive Associations | Cautions |
|---|---|---|
| Blue | Trust, calm, professional | Can feel cold, corporate |
| Green | Growth, nature, success | Can feel boring if overused |
| Red | Passion, urgency, energy | High arousal, use sparingly |
| Orange | Warmth, friendly, creative | Can feel cheap if saturated |
| Purple | Creative, luxury, imaginative | ⚠️ AI's default — earn it or try Deep Teal/Maroon/Emerald |
| Yellow | Optimism, attention, happy | Hard to read, use as accent |
| Black | Elegance, power, modern | Can feel heavy |
| White | Clean, minimal, open | Can feel sterile |
Selection Process:
1. What industry? → Narrow to 2-3 hue families 2. What emotion? → Pick primary hue 3. What contrast? → Decide light vs dark mode 4. ASK USER → Confirm before proceeding
---
4. Palette Generation Principles
From a Single Color (HSL Method)
Instead of memorizing hex codes, learn to manipulate HSL:
HSL = Hue, Saturation, Lightness
Hue (0-360): The color family
0/360 = Red
60 = Yellow
120 = Green
180 = Cyan
240 = Blue
300 = Purple
Saturation (0-100%): Color intensity
Low = Muted, sophisticated
High = Vibrant, energetic
Lightness (0-100%): Brightness
0% = Black
50% = Pure color
100% = WhiteGenerating a Full Palette
Given ANY base color, create a scale:
Lightness Scale:
50 (lightest) → L: 97%
100 → L: 94%
200 → L: 86%
300 → L: 74%
400 → L: 66%
500 (base) → L: 50-60%
600 → L: 48%
700 → L: 38%
800 → L: 30%
900 (darkest) → L: 20%Saturation Adjustments
| Context | Saturation Level |
|---|---|
| Professional/Corporate | Lower (40-60%) |
| Playful/Youth | Higher (70-90%) |
| Dark Mode | Reduce by 10-20% |
| Accessibility | Ensure contrast, may need adjustment |
---
5. Context-Based Selection Guide
Instead of Copying Palettes, Follow This Process:
Step 1: Identify the Context
What type of project?
├── E-commerce → Need trust + urgency balance
├── SaaS/Dashboard → Need low-fatigue, data focus
├── Health/Wellness → Need calming, natural feel
├── Luxury/Premium → Need understated elegance
├── Creative/Portfolio → Need personality, memorable
└── Other → ASK the userStep 2: Select Primary Hue Family
Based on context, pick ONE:
- Blue family (trust)
- Green family (growth)
- Warm family (energy)
- Neutral family (elegant)
- OR ask user preferenceStep 3: Decide Light/Dark Mode
Consider:
- User preference?
- Industry standard?
- Content type? (text-heavy = light preferred)
- Time of use? (evening app = dark option)Step 4: Generate Palette Using Principles
- Use HSL manipulation
- Follow 60-30-10 rule
- Check contrast (WCAG)
- Test with actual content
---
6. Dark Mode Principles
Key Rules (No Fixed Codes)
1. Never pure black → Use very dark gray with slight hue 2. Never pure white text → Use 87-92% lightness 3. Reduce saturation → Vibrant colors strain eyes in dark mode 4. Elevation = brightness → Higher elements slightly lighter
Contrast in Dark Mode
Background layers (darker → lighter as elevation increases):
Layer 0 (base) → Darkest
Layer 1 (cards) → Slightly lighter
Layer 2 (modals) → Even lighter
Layer 3 (popups) → Lightest darkAdapting Colors for Dark Mode
| Light Mode | Dark Mode Adjustment |
|---|---|
| High saturation accent | Reduce saturation 10-20% |
| Pure white background | Dark gray with brand hue tint |
| Black text | Light gray (not pure white) |
| Colorful backgrounds | Desaturated, darker versions |
---
7. Accessibility Guidelines
Contrast Requirements (WCAG)
| Level | Normal Text | Large Text |
|---|---|---|
| AA (minimum) | 4.5:1 | 3:1 |
| AAA (enhanced) | 7:1 | 4.5:1 |
How to Check Contrast
1. Convert colors to luminance 2. Calculate ratio: (lighter + 0.05) / (darker + 0.05) 3. Adjust until ratio meets requirement
Safe Patterns
| Use Case | Guideline |
|---|---|
| Text on light bg | Use lightness 35% or less |
| Text on dark bg | Use lightness 85% or more |
| Primary on white | Ensure dark enough variant |
| Buttons | High contrast between bg and text |
---
8. Color Selection Checklist
Before finalizing any color choice, verify:
- [ ] Asked user preference? (if not specified)
- [ ] Matches project context? (industry, audience)
- [ ] Follows 60-30-10? (proper distribution)
- [ ] WCAG compliant? (contrast checked)
- [ ] Works in both modes? (if dark mode needed)
- [ ] NOT your default/favorite? (variety check)
- [ ] Different from last project? (avoid repetition)
---
9. Anti-Patterns to Avoid
❌ DON'T:
- Copy the same hex codes every project
- Default to purple/violet (AI tendency)
- Default to dark mode + neon (AI tendency)
- Use pure black (#000000) backgrounds
- Use pure white (#FFFFFF) text on dark
- Ignore user's industry context
- Skip asking user preference
✅ DO:
- Generate fresh palette per project
- Ask user about color preferences
- Consider industry and audience
- Use HSL for flexible manipulation
- Test contrast and accessibility
- Offer light AND dark options
---
Remember: Colors are decisions, not defaults. Every project deserves thoughtful selection based on its unique context.
Decision Trees & Context Templates
Context-based design THINKING, not fixed solutions.
These are decision GUIDES, not copy-paste templates.
For UX psychology principles (Hick's, Fitts', etc.) see: ux-psychology.md
---
⚠️ How to Use This File
This file helps you DECIDE, not copy.
- Decision trees → Help you THINK through options
- Templates → Show STRUCTURE and PRINCIPLES, not exact values
- Always ask user preferences before applying
- Generate fresh palettes based on context, don't copy hex codes
- Apply UX laws from ux-psychology.md to validate decisions
---
1. Master Decision Tree
┌─────────────────────────────────────────────────────────────┐
│ WHAT ARE YOU BUILDING? │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
E-COMMERCE SaaS/APP CONTENT
- Product pages - Dashboard - Blog
- Checkout - Tools - Portfolio
- Catalog - Admin - Landing
│ │ │
▼ ▼ ▼
PRINCIPLES: PRINCIPLES: PRINCIPLES:
- Trust - Functionality - Storytelling
- Action - Clarity - Emotion
- Urgency - Efficiency - Creativity---
2. Audience Decision Tree
Who is your target user?
TARGET AUDIENCE
│
├── Gen Z (18-25)
│ ├── Colors: Bold, vibrant, unexpected combinations
│ ├── Type: Large, expressive, variable
│ ├── Layout: Mobile-first, vertical, snackable
│ ├── Effects: Motion, gamification, interactive
│ └── Approach: Authentic, fast, no corporate feel
│
├── Millennials (26-41)
│ ├── Colors: Muted, earthy, sophisticated
│ ├── Type: Clean, readable, functional
│ ├── Layout: Responsive, card-based, organized
│ ├── Effects: Subtle, purposeful only
│ └── Approach: Value-driven, transparent, sustainable
│
├── Gen X (42-57)
│ ├── Colors: Professional, trusted, conservative
│ ├── Type: Familiar, clear, no-nonsense
│ ├── Layout: Traditional hierarchy, predictable
│ ├── Effects: Minimal, functional feedback
│ └── Approach: Direct, efficient, reliable
│
├── Boomers (58+)
│ ├── Colors: High contrast, simple, clear
│ ├── Type: Large sizes, high readability
│ ├── Layout: Simple, linear, uncluttered
│ ├── Effects: None or very minimal
│ └── Approach: Clear, detailed, trustworthy
│
└── B2B / Enterprise
├── Colors: Professional palette, muted
├── Type: Clean, data-friendly, scannable
├── Layout: Grid-based, organized, efficient
├── Effects: Professional, subtle
└── Approach: Expert, solution-focused, ROI-driven---
3. Color Selection Decision Tree
Instead of fixed hex codes, use this process:
WHAT EMOTION/ACTION DO YOU WANT?
│
├── Trust & Security
│ └── Consider: Blue family, professional neutrals
│ → ASK user for specific shade preference
│
├── Growth & Health
│ └── Consider: Green family, natural tones
│ → ASK user if eco/nature/wellness focus
│
├── Urgency & Action
│ └── Consider: Warm colors (orange/red) as ACCENTS
│ → Use sparingly, ASK if appropriate
│
├── Luxury & Premium
│ └── Consider: Deep darks, metallics, restrained palette
│ → ASK about brand positioning
│
├── Creative & Playful
│ └── Consider: Multi-color, unexpected combinations
│ → ASK about brand personality
│
└── Calm & Minimal
└── Consider: Neutrals with single accent
→ ASK what accent color fits brandThe Process:
1. Identify the emotion needed 2. Narrow to color FAMILY 3. ASK user for preference within family 4. Generate fresh palette using HSL principles
---
4. Typography Decision Tree
WHAT'S THE CONTENT TYPE?
│
├── Data-Heavy (Dashboard, SaaS)
│ ├── Style: Sans-serif, clear, compact
│ ├── Scale: Tighter ratio (1.125-1.2)
│ └── Priority: Scannability, density
│
├── Editorial (Blog, Magazine)
│ ├── Style: Serif heading + Sans body works well
│ ├── Scale: More dramatic (1.333+)
│ └── Priority: Reading comfort, hierarchy
│
├── Modern Tech (Startup, SaaS Marketing)
│ ├── Style: Geometric or humanist sans
│ ├── Scale: Balanced (1.25)
│ └── Priority: Modern feel, clarity
│
├── Luxury (Fashion, Premium)
│ ├── Style: Elegant serif or thin sans
│ ├── Scale: Dramatic (1.5-1.618)
│ └── Priority: Sophistication, whitespace
│
└── Playful (Kids, Games, Casual)
├── Style: Rounded, friendly fonts
├── Scale: Varied, expressive
└── Priority: Fun, approachable, readableSelection Process:
1. Identify content type 2. Choose style DIRECTION 3. ASK user if they have brand fonts 4. Select fonts that match direction
---
5. E-commerce Guidelines {#e-commerce}
Key Principles (Not Fixed Rules)
- Trust first: How will you show security?
- Action-oriented: Where are the CTAs?
- Scannable: Can users compare quickly?
Color Thinking:
E-commerce typically needs:
├── Trust color (often blue family) → ASK preference
├── Clean background (white/neutral) → depends on brand
├── Action accent (for CTAs, sales) → depends on urgency level
├── Success/error semantics → standard conventions work
└── Brand integration → ASK about existing colorsLayout Principles:
┌────────────────────────────────────────────────────┐
│ HEADER: Brand + Search + Cart │
│ (Keep essential actions visible) │
├────────────────────────────────────────────────────┤
│ TRUST ZONE: Why trust this site? │
│ (Shipping, returns, security - if applicable) │
├────────────────────────────────────────────────────┤
│ HERO: Primary message or offer │
│ (Clear CTA, single focus) │
├────────────────────────────────────────────────────┤
│ CATEGORIES: Easy navigation │
│ (Visual, filterable, scannable) │
├────────────────────────────────────────────────────┤
│ PRODUCTS: Easy comparison │
│ (Price, rating, quick actions visible) │
├────────────────────────────────────────────────────┤
│ SOCIAL PROOF: Why others trust │
│ (Reviews, testimonials - if available) │
├────────────────────────────────────────────────────┤
│ FOOTER: All the details │
│ (Policies, contact, trust badges) │
└────────────────────────────────────────────────────┘Psychology to Apply:
- Hick's Law: Limit navigation choices
- Fitts' Law: Size CTAs appropriately
- Social proof: Show where relevant
- Scarcity: Use honestly if at all
---
6. SaaS Dashboard Guidelines {#saas}
Key Principles
- Functional first: Data clarity over decoration
- Calm UI: Reduce cognitive load
- Consistent: Predictable patterns
Color Thinking:
Dashboard typically needs:
├── Background: Light OR dark (ASK preference)
├── Surface: Slight contrast from background
├── Primary accent: For key actions
├── Data colors: Success/warning/danger semantics
└── Muted: For secondary informationLayout Principles:
Consider these patterns (not mandated):
OPTION A: Sidebar + Content
├── Fixed sidebar for navigation
└── Main area for content
OPTION B: Top nav + Content
├── Horizontal navigation
└── More horizontal content space
OPTION C: Collapsed + Expandable
├── Icon-only sidebar expands
└── Maximum content area
→ ASK user about their navigation preferencePsychology to Apply:
- Hick's Law: Group navigation items
- Miller's Law: Chunk information
- Cognitive Load: Whitespace, consistency
---
7. Landing Page Guidelines {#landing-page}
Key Principles
- Hero-centric: First impression matters most
- Single focus: One primary CTA
- Emotional: Connect before selling
Color Thinking:
Landing page typically needs:
├── Brand primary: Hero background or accent
├── Clean secondary: Most of page
├── CTA color: Stands out from everything
├── Supporting: For sections, testimonials
└── ASK about brand colors first!Structure Principles:
┌────────────────────────────────────────────────────┐
│ Navigation: Minimal, CTA visible │
├────────────────────────────────────────────────────┤
│ HERO: Hook + Value + CTA │
│ (Most important section, biggest impact) │
├────────────────────────────────────────────────────┤
│ PROBLEM: What pain do they have? │
├────────────────────────────────────────────────────┤
│ SOLUTION: How you solve it │
├────────────────────────────────────────────────────┤
│ PROOF: Why believe you? │
│ (Testimonials, logos, stats) │
├────────────────────────────────────────────────────┤
│ HOW: Simple explanation of process │
├────────────────────────────────────────────────────┤
│ PRICING: If applicable │
├────────────────────────────────────────────────────┤
│ FAQ: Address objections │
├────────────────────────────────────────────────────┤
│ FINAL CTA: Repeat main action │
└────────────────────────────────────────────────────┘Psychology to Apply:
- Visceral: Beautiful hero impression
- Serial Position: Key info top/bottom
- Social Proof: Testimonials work
---
8. Portfolio Guidelines {#portfolio}
Key Principles
- Personality: Show who you are
- Work-focused: Let projects speak
- Memorable: Stand out from templates
Color Thinking:
Portfolio is personal - many options:
├── Minimal: Neutrals + one signature accent
├── Bold: Unexpected color choices
├── Dark: Moody, artistic feel
├── Light: Clean, professional feel
└── ASK about personal brand identity!Structure Principles:
┌────────────────────────────────────────────────────┐
│ Navigation: Unique to your personality │
├────────────────────────────────────────────────────┤
│ INTRO: Who you are, what you do │
│ (Make it memorable, not generic) │
├────────────────────────────────────────────────────┤
│ WORK: Featured projects │
│ (Large, visual, interactive) │
├────────────────────────────────────────────────────┤
│ ABOUT: Personal story │
│ (Creates connection) │
├────────────────────────────────────────────────────┤
│ CONTACT: Easy to reach │
│ (Clear, direct) │
└────────────────────────────────────────────────────┘Psychology to Apply:
- Von Restorff: Be uniquely memorable
- Reflective: Personal story creates connection
- Emotional: Personality over professionalism
---
9. Pre-Design Checklists
Before Starting ANY Design
- [ ] Audience defined? (who exactly)
- [ ] Primary goal identified? (what action)
- [ ] Constraints known? (time, brand, tech)
- [ ] Content available? (or placeholders needed)
- [ ] User preferences asked? (colors, style, layout)
Before Choosing Colors
- [ ] Asked user preference?
- [ ] Considered context? (industry, emotion)
- [ ] Different from your default?
- [ ] Checked accessibility?
Before Finalizing Layout
- [ ] Hierarchy clear?
- [ ] Primary CTA obvious?
- [ ] Mobile considered?
- [ ] Content fits structure?
Before Delivery
- [ ] Looks premium, not generic?
- [ ] Would you be proud of this?
- [ ] Different from last project?
---
10. Complexity Estimation
Quick Projects (Hours)
Simple landing page
Small portfolio
Basic form
Single component→ Approach: Minimal decisions, focused execution
Medium Projects (Days)
Multi-page site
Dashboard with modules
E-commerce category
Complex forms→ Approach: Establish tokens, custom components
Large Projects (Weeks)
Full SaaS application
E-commerce platform
Custom design system
Complex workflows→ Approach: Full design system, documentation, testing
---
Remember: These templates show STRUCTURE and THINKING process. Every project needs fresh color, typography, and styling decisions based on its unique context. ASK when unclear.
Motion Graphics Reference
Advanced animation techniques for premium web experiences - Lottie, GSAP, SVG, 3D, Particles.
Learn the principles, create WOW effects.
---
1. Lottie Animations
What is Lottie?
JSON-based vector animations:
├── Exported from After Effects via Bodymovin
├── Lightweight (smaller than GIF/video)
├── Scalable (vector-based, no pixelation)
├── Interactive (control playback, segments)
└── Cross-platform (web, iOS, Android, React Native)When to Use Lottie
| Use Case | Why Lottie? |
|---|---|
| Loading animations | Branded, smooth, lightweight |
| Empty states | Engaging illustrations |
| Onboarding flows | Complex multi-step animations |
| Success/Error feedback | Delightful micro-interactions |
| Animated icons | Consistent cross-platform |
Principles
- Keep file size under 100KB for performance
- Use loop sparingly (avoid distraction)
- Provide static fallback for reduced-motion
- Lazy load animation files when possible
Sources
- LottieFiles.com (free library)
- After Effects + Bodymovin (custom)
- Figma plugins (export from design)
---
2. GSAP (GreenSock)
What Makes GSAP Different
Professional timeline-based animation:
├── Precise control over sequences
├── ScrollTrigger for scroll-driven animations
├── MorphSVG for shape transitions
├── Physics-based easing
└── Works with any DOM elementCore Concepts
| Concept | Purpose |
|---|---|
| Tween | Single A→B animation |
| Timeline | Sequenced/overlapping animations |
| ScrollTrigger | Scroll position controls playback |
| Stagger | Cascade effect across elements |
When to Use GSAP
- ✅ Complex sequenced animations
- ✅ Scroll-triggered reveals
- ✅ Precise timing control needed
- ✅ SVG morphing effects
- ❌ Simple hover/focus effects (use CSS)
- ❌ Performance-critical mobile (heavier)
Principles
- Use timeline for orchestration (not individual tweens)
- Stagger delay: 0.05-0.15s between items
- ScrollTrigger: start at 70-80% viewport entry
- Kill animations on unmount (prevent memory leaks)
---
3. SVG Animations
Types of SVG Animation
| Type | Technique | Use Case |
|---|---|---|
| Line Drawing | stroke-dashoffset | Logo reveals, signatures |
| Morph | Path interpolation | Icon transitions |
| Transform | rotate, scale, translate | Interactive icons |
| Color | fill/stroke transition | State changes |
Line Drawing Principles
How stroke-dashoffset drawing works:
├── Set dasharray to path length
├── Set dashoffset equal to dasharray (hidden)
├── Animate dashoffset to 0 (revealed)
└── Create "drawing" effectWhen to Use SVG Animations
- ✅ Logo reveals, brand moments
- ✅ Icon state transitions (hamburger ↔ X)
- ✅ Infographics, data visualization
- ✅ Interactive illustrations
- ❌ Photo-realistic content (use video)
- ❌ Very complex scenes (performance)
Principles
- Get path length dynamically for accuracy
- Duration: 1-3s for full drawings
- Easing: ease-out for natural feel
- Simple fills complement, don't compete
---
4. 3D CSS Transforms
Core Properties
CSS 3D Space:
├── perspective: depth of 3D field (500-1500px typical)
├── transform-style: preserve-3d (enable children 3D)
├── rotateX/Y/Z: rotation per axis
├── translateZ: move toward/away from viewer
└── backface-visibility: show/hide back sideCommon 3D Patterns
| Pattern | Use Case |
|---|---|
| Card flip | Reveals, flashcards, product views |
| Tilt on hover | Interactive cards, 3D depth |
| Parallax layers | Hero sections, immersive scrolling |
| 3D carousel | Image galleries, sliders |
Principles
- Perspective: 800-1200px for subtle, 400-600px for dramatic
- Keep transforms simple (rotate + translate)
- Ensure backface-visibility: hidden for flips
- Test on Safari (different rendering)
---
5. Particle Effects
Types of Particle Systems
| Type | Feel | Use Case |
|---|---|---|
| Geometric | Tech, network | SaaS, tech sites |
| Confetti | Celebration | Success moments |
| Snow/Rain | Atmospheric | Seasonal, mood |
| Dust/Bokeh | Dreamy | Photography, luxury |
| Fireflies | Magical | Games, fantasy |
Libraries
| Library | Best For |
|---|---|
| tsParticles | Configurable, lightweight |
| particles.js | Simple backgrounds |
| Canvas API | Custom, maximum control |
| Three.js | Complex 3D particles |
Principles
- Default: 30-50 particles (not overwhelming)
- Movement: slow, organic (speed 0.5-2)
- Opacity: 0.3-0.6 (don't compete with content)
- Connections: subtle lines for "network" feel
- ⚠️ Disable or reduce on mobile
When to Use
- ✅ Hero backgrounds (atmospheric)
- ✅ Success celebrations (confetti burst)
- ✅ Tech visualization (connected nodes)
- ❌ Content-heavy pages (distraction)
- ❌ Low-powered devices (battery drain)
---
6. Scroll-Driven Animations
Native CSS (Modern)
CSS Scroll Timelines:
├── animation-timeline: scroll() - document scroll
├── animation-timeline: view() - element in viewport
├── animation-range: entry/exit thresholds
└── No JavaScript requiredPrinciples
| Trigger Point | Use Case |
|---|---|
| Entry 0% | When element starts entering |
| Entry 50% | When half visible |
| Cover 50% | When centered in viewport |
| Exit 100% | When fully exited |
Best Practices
- Reveal animations: start at ~25% entry
- Parallax: continuous scroll progress
- Sticky elements: use cover range
- Always test scroll performance
---
7. Performance Principles
GPU vs CPU Animation
CHEAP (GPU-accelerated):
├── transform (translate, scale, rotate)
├── opacity
└── filter (use sparingly)
EXPENSIVE (triggers reflow):
├── width, height
├── top, left, right, bottom
├── padding, margin
└── complex box-shadowOptimization Checklist
- [ ] Animate only transform/opacity
- [ ] Use
will-changebefore heavy animations (remove after) - [ ] Test on low-end devices
- [ ] Implement
prefers-reduced-motion - [ ] Lazy load animation libraries
- [ ] Throttle scroll-based calculations
---
8. Motion Graphics Decision Tree
What animation do you need?
│
├── Complex branded animation?
│ └── Lottie (After Effects export)
│
├── Sequenced scroll-triggered?
│ └── GSAP + ScrollTrigger
│
├── Logo/icon animation?
│ └── SVG animation (stroke or morph)
│
├── Interactive 3D effect?
│ └── CSS 3D Transforms (simple) or Three.js (complex)
│
├── Atmospheric background?
│ └── tsParticles or Canvas
│
└── Simple entrance/hover?
└── CSS @keyframes or Framer Motion---
9. Anti-Patterns
| ❌ Don't | ✅ Do |
|---|---|
| Animate everything at once | Stagger and sequence |
| Use heavy libraries for simple effects | Start with CSS |
| Ignore reduced-motion | Always provide fallback |
| Block main thread | Optimize for 60fps |
| Same particles every project | Match brand/context |
| Complex effects on mobile | Feature detection |
---
10. Quick Reference
| Effect | Tool | Performance |
|---|---|---|
| Loading spinner | CSS/Lottie | Light |
| Staggered reveal | GSAP/Framer | Medium |
| SVG path draw | CSS stroke | Light |
| 3D card flip | CSS transforms | Light |
| Particle background | tsParticles | Heavy |
| Scroll parallax | GSAP ScrollTrigger | Medium |
| Shape morphing | GSAP MorphSVG | Medium |
---
Remember: Motion graphics should enhance, not distract. Every animation must serve a PURPOSE—feedback, guidance, delight, or storytelling.
#!/usr/bin/env python3
"""
Accessibility Checker - WCAG compliance audit
Checks HTML files for accessibility issues.
Usage:
python accessibility_checker.py <project_path>
Checks:
- Form labels
- ARIA attributes
- Color contrast hints
- Keyboard navigation
- Semantic HTML
"""
import sys
import json
import re
from pathlib import Path
from datetime import datetime
# Fix Windows console encoding
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
except:
pass
def find_html_files(project_path: Path) -> list:
"""Find all HTML/JSX/TSX files."""
patterns = ['**/*.html', '**/*.jsx', '**/*.tsx']
skip_dirs = {'node_modules', '.next', 'dist', 'build', '.git'}
files = []
for pattern in patterns:
for f in project_path.glob(pattern):
if not any(skip in f.parts for skip in skip_dirs):
files.append(f)
return files[:50]
def check_accessibility(file_path: Path) -> list:
"""Check a single file for accessibility issues."""
issues = []
try:
content = file_path.read_text(encoding='utf-8', errors='ignore')
# Check for form inputs without labels
inputs = re.findall(r'<input[^>]*>', content, re.IGNORECASE)
for inp in inputs:
if 'type="hidden"' not in inp.lower():
if 'aria-label' not in inp.lower() and 'id=' not in inp.lower():
issues.append("Input without label or aria-label")
break
# Check for buttons without accessible text
buttons = re.findall(r'<button[^>]*>[^<]*</button>', content, re.IGNORECASE)
for btn in buttons:
# Check if button has text content or aria-label
if 'aria-label' not in btn.lower():
text = re.sub(r'<[^>]+>', '', btn)
if not text.strip():
issues.append("Button without accessible text")
break
# Check for missing lang attribute
if '<html' in content.lower() and 'lang=' not in content.lower():
issues.append("Missing lang attribute on <html>")
# Check for missing skip link
if '<main' in content.lower() or '<body' in content.lower():
if 'skip' not in content.lower() and '#main' not in content.lower():
issues.append("Consider adding skip-to-main-content link")
# Check for click handlers without keyboard support
onclick_count = content.lower().count('onclick=')
onkeydown_count = content.lower().count('onkeydown=') + content.lower().count('onkeyup=')
if onclick_count > 0 and onkeydown_count == 0:
issues.append("onClick without keyboard handler (onKeyDown)")
# Check for tabIndex misuse
if 'tabindex=' in content.lower():
if 'tabindex="-1"' not in content.lower() and 'tabindex="0"' not in content.lower():
positive_tabindex = re.findall(r'tabindex="([1-9]\d*)"', content, re.IGNORECASE)
if positive_tabindex:
issues.append("Avoid positive tabIndex values")
# Check for autoplay media
if 'autoplay' in content.lower():
if 'muted' not in content.lower():
issues.append("Autoplay media should be muted")
# Check for role usage
if 'role="button"' in content.lower():
# Divs with role button should have tabindex
div_buttons = re.findall(r'<div[^>]*role="button"[^>]*>', content, re.IGNORECASE)
for div in div_buttons:
if 'tabindex' not in div.lower():
issues.append("role='button' without tabindex")
break
except Exception as e:
issues.append(f"Error reading file: {str(e)[:50]}")
return issues
def main():
project_path = Path(sys.argv[1] if len(sys.argv) > 1 else ".").resolve()
print(f"\n{'='*60}")
print(f"[ACCESSIBILITY CHECKER] WCAG Compliance Audit")
print(f"{'='*60}")
print(f"Project: {project_path}")
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("-"*60)
# Find HTML files
files = find_html_files(project_path)
print(f"Found {len(files)} HTML/JSX/TSX files")
if not files:
output = {
"script": "accessibility_checker",
"project": str(project_path),
"files_checked": 0,
"issues_found": 0,
"passed": True,
"message": "No HTML files found"
}
print(json.dumps(output, indent=2))
sys.exit(0)
# Check each file
all_issues = []
for f in files:
issues = check_accessibility(f)
if issues:
all_issues.append({
"file": str(f.name),
"issues": issues
})
# Summary
print("\n" + "="*60)
print("ACCESSIBILITY ISSUES")
print("="*60)
if all_issues:
for item in all_issues[:10]:
print(f"\n{item['file']}:")
for issue in item["issues"]:
print(f" - {issue}")
if len(all_issues) > 10:
print(f"\n... and {len(all_issues) - 10} more files with issues")
else:
print("No accessibility issues found!")
total_issues = sum(len(item["issues"]) for item in all_issues)
# Accessibility issues are important but not blocking
passed = total_issues < 5 # Allow minor issues
output = {
"script": "accessibility_checker",
"project": str(project_path),
"files_checked": len(files),
"files_with_issues": len(all_issues),
"issues_found": total_issues,
"passed": passed
}
print("\n" + json.dumps(output, indent=2))
sys.exit(0 if passed else 1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
UX Audit Script - Full Frontend Design Coverage
Analyzes code for compliance with:
1. CORE PSYCHOLOGY LAWS:
- Hick's Law (nav items, form complexity)
- Fitts' Law (target sizes, touch targets)
- Miller's Law (chunking, memory limits)
- Von Restorff Effect (primary CTA visibility)
- Serial Position Effect (important items at start/end)
2. EMOTIONAL DESIGN (Don Norman):
- Visceral (first impressions, gradients, animations)
- Behavioral (feedback, usability, performance)
- Reflective (brand story, values, identity)
3. TRUST BUILDING:
- Security signals (SSL, encryption on forms)
- Social proof (testimonials, reviews, logos)
- Authority indicators (certifications, awards, media)
4. COGNITIVE LOAD MANAGEMENT:
- Progressive disclosure (accordion, tabs, "Advanced")
- Visual noise (too many colors/borders)
- Familiar patterns (labels, standard conventions)
5. PERSUASIVE DESIGN (Ethical):
- Smart defaults (pre-selected options)
- Anchoring (original vs discount price)
- Social proof (live indicators, numbers)
- Progress indicators (progress bars, steps)
6. TYPOGRAPHY SYSTEM (9 sections):
- Font Pairing (max 3 families)
- Line Length (45-75ch)
- Line Height (proper ratios)
- Letter Spacing (uppercase, display text)
- Weight and Emphasis (contrast levels)
- Responsive Typography (clamp())
- Hierarchy (sequential headings)
- Modular Scale (consistent ratios)
- Readability (chunking, subheadings)
7. VISUAL EFFECTS (10 sections):
- Glassmorphism (blur + transparency)
- Neomorphism (dual shadows, inset)
- Shadow Hierarchy (elevation levels)
- Gradients (usage, overuse)
- Border Effects (complexity check)
- Glow Effects (text-shadow, box-shadow)
- Overlay Techniques (image text readability)
- GPU Acceleration (transform/opacity vs layout)
- Performance (will-change usage)
- Effect Selection (purpose over decoration)
8. COLOR SYSTEM (7 sections):
- PURPLE BAN (Critical Maestro rule - #8B5CF6, #A855F7, etc.)
- 60-30-10 Rule (dominant, secondary, accent)
- Color Scheme Patterns (monochromatic, analogous)
- Dark Mode Compliance (no pure black/white)
- WCAG Contrast (low-contrast detection)
- Color Psychology Context (food + blue = bad)
- HSL-Based Palettes (recommended approach)
9. ANIMATION GUIDE (6 sections):
- Duration Appropriateness (50ms minimum, 1s max transitions)
- Easing Functions (ease-out for entry, ease-in for exit)
- Micro-interactions (hover/focus feedback)
- Loading States (skeleton, spinner, progress)
- Page Transitions (fade/slide for routing)
- Scroll Animation Performance (no layout properties)
10. MOTION GRAPHICS (7 sections):
- Lottie Animations (reduced motion fallbacks)
- GSAP Memory Leaks (kill/revert on unmount)
- SVG Animation Performance (stroke-dashoffset sparingly)
- 3D Transforms (perspective parent, mobile warning)
- Particle Effects (mobile fallback)
- Scroll-Driven Animations (throttle with rAF)
- Motion Decision Tree (functional vs decorative)
11. ACCESSIBILITY:
- Alt text for images
- Reduced motion checks
- Form labels
Total: 80+ checks across all design principles
"""
import sys
import os
import re
import json
from pathlib import Path
class UXAuditor:
def __init__(self):
self.issues = []
self.warnings = []
self.passed_count = 0
self.files_checked = 0
def audit_file(self, filepath: str) -> None:
try:
with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
except: return
self.files_checked += 1
filename = os.path.basename(filepath)
# Pre-calculate common flags
has_long_text = bool(re.search(r'<p|<div.*class=.*text|article|<span.*text', content, re.IGNORECASE))
has_form = bool(re.search(r'<form|<input|password|credit|card|payment', content, re.IGNORECASE))
complex_elements = len(re.findall(r'<input|<select|<textarea|<option', content, re.IGNORECASE))
# --- 1. PSYCHOLOGY LAWS ---
# Hick's Law
nav_items = len(re.findall(r'<NavLink|<Link|<a\s+href|nav-item', content, re.IGNORECASE))
if nav_items > 7:
self.warnings.append(f"[Hick's Law] {filename}: {nav_items} nav items (Max 7). Consider grouping into categorized submenus.")
# Fitts' Law
if re.search(r'height:\s*([0-3]\d)px', content) or re.search(r'h-[1-9]\b|h-10\b', content):
self.warnings.append(f"[Fitts' Law] {filename}: Small targets (< 44px)")
# Miller's Law
form_fields = len(re.findall(r'<input|<select|<textarea', content, re.IGNORECASE))
if form_fields > 7 and not re.search(r'step|wizard|stage', content, re.IGNORECASE):
self.warnings.append(f"[Miller's Law] {filename}: Complex form ({form_fields} fields)")
# Von Restorff
if 'button' in content.lower() and not re.search(r'primary|bg-primary|Button.*primary|variant=["\']primary', content, re.IGNORECASE):
self.warnings.append(f"[Von Restorff] {filename}: No primary CTA")
# Serial Position Effect - Important items at beginning/end
if nav_items > 3:
# Check if last nav item is important (contact, login, etc.)
nav_content = re.findall(r'<NavLink|<Link|<a\s+href[^>]*>([^<]+)</a>', content, re.IGNORECASE)
if nav_content and len(nav_content) > 2:
last_item = nav_content[-1].lower() if nav_content else ''
if not any(x in last_item for x in ['contact', 'login', 'sign', 'get started', 'cta', 'button']):
self.warnings.append(f"[Serial Position] {filename}: Last nav item may not be important. Place key actions at start/end.")
# --- 1.5 EMOTIONAL DESIGN (Don Norman) ---
# Visceral: First impressions (aesthetics, gradients, animations)
has_hero = bool(re.search(r'hero|<h1|banner', content, re.IGNORECASE))
if has_hero:
# Check for visual appeal elements
has_gradient = bool(re.search(r'gradient|linear-gradient|radial-gradient', content))
has_animation = bool(re.search(r'@keyframes|transition:|animate-', content))
has_visual_interest = has_gradient or has_animation
if not has_visual_interest and not re.search(r'background:|bg-', content):
self.warnings.append(f"[Visceral] {filename}: Hero section lacks visual appeal. Consider gradients or subtle animations.")
# Behavioral: Instant feedback and usability
if 'onClick' in content or '@click' in content or 'onclick' in content:
has_feedback = re.search(r'transition|animate|hover:|focus:|disabled|loading|spinner', content, re.IGNORECASE)
has_state_change = re.search(r'setState|useState|disabled|loading', content)
if not has_feedback and not has_state_change:
self.warnings.append(f"[Behavioral] {filename}: Interactive elements lack immediate feedback. Add hover/focus/disabled states.")
# Reflective: Brand story, values, identity
has_reflective = bool(re.search(r'about|story|mission|values|why we|our journey|testimonials', content, re.IGNORECASE))
if has_long_text and not has_reflective:
self.warnings.append(f"[Reflective] {filename}: Long-form content without brand story/values. Add 'About' or 'Why We Exist' section.")
# --- 1.6 TRUST BUILDING (Enhanced) ---
# Security signals
if has_form:
security_signals = re.findall(r'ssl|secure|encrypt|lock|padlock|https', content, re.IGNORECASE)
if len(security_signals) == 0 and not re.search(r'checkout|payment', content, re.IGNORECASE):
self.warnings.append(f"[Trust] {filename}: Form without security indicators. Add 'SSL Secure' or lock icon.")
# Social proof elements
social_proof = re.findall(r'review|testimonial|rating|star|trust|trusted by|customer|logo', content, re.IGNORECASE)
if len(social_proof) > 0:
self.passed_count += 1
else:
if has_long_text:
self.warnings.append(f"[Trust] {filename}: No social proof detected. Consider adding testimonials, ratings, or 'Trusted by' logos.")
# Authority indicators
has_footer = bool(re.search(r'footer|<footer', content, re.IGNORECASE))
if has_footer:
authority = re.findall(r'certif|award|media|press|featured|as seen in', content, re.IGNORECASE)
if len(authority) == 0:
self.warnings.append(f"[Trust] {filename}: Footer lacks authority signals. Add certifications, awards, or media mentions.")
# --- 1.7 COGNITIVE LOAD MANAGEMENT ---
# Progressive disclosure
if complex_elements > 5:
has_progressive = re.search(r'step|wizard|stage|accordion|collapsible|tab|more\.\.\.|advanced|show more', content, re.IGNORECASE)
if not has_progressive:
self.warnings.append(f"[Cognitive Load] {filename}: Many form elements without progressive disclosure. Consider accordion, tabs, or 'Advanced' toggle.")
# Visual noise check
has_many_colors = len(re.findall(r'#[0-9a-fA-F]{3,6}|rgb|hsl', content)) > 15
has_many_borders = len(re.findall(r'border:|border-', content)) > 10
if has_many_colors and has_many_borders:
self.warnings.append(f"[Cognitive Load] {filename}: High visual noise detected. Many colors and borders increase cognitive load.")
# Familiar patterns
if re.search(r'<input|<select|<textarea', content, re.IGNORECASE):
has_standard_labels = bool(re.search(r'<label|placeholder|aria-label|htmlFor', content, re.IGNORECASE))
if not has_standard_labels:
self.issues.append(f"[Cognitive Load] {filename}: Form inputs without labels. Use <label> for accessibility and clarity.")
# --- 1.8 PERSUASIVE DESIGN (Ethical) ---
# Smart defaults
if has_form:
has_defaults = bool(re.search(r'checked|selected|default|value=["\'].*["\']', content))
radio_inputs = len(re.findall(r'type=["\']radio', content, re.IGNORECASE))
if radio_inputs > 0 and not has_defaults:
self.warnings.append(f"[Persuasion] {filename}: Radio buttons without default selection. Pre-select recommended option.")
# Anchoring (showing original price)
if re.search(r'price|pricing|cost|\$\d+', content, re.IGNORECASE):
has_anchor = bool(re.search(r'original|was|strike|del|save \d+%', content, re.IGNORECASE))
if not has_anchor:
self.warnings.append(f"[Persuasion] {filename}: Prices without anchoring. Show original price to frame discount value.")
# Social proof live indicators
has_social = bool(re.search(r'join|subscriber|member|user', content, re.IGNORECASE))
if has_social:
has_count = bool(re.findall(r'\d+[+kmb]|\d+,\d+', content))
if not has_count:
self.warnings.append(f"[Persuasion] {filename}: Social proof without specific numbers. Use 'Join 10,000+' format.")
# Progress indicators
if has_form:
has_progress = bool(re.search(r'progress|step \d+|complete|%|bar', content, re.IGNORECASE))
if complex_elements > 5 and not has_progress:
self.warnings.append(f"[Persuasion] {filename}: Long form without progress indicator. Add progress bar or 'Step X of Y'.")
# --- 2. TYPOGRAPHY SYSTEM (Complete Coverage) ---
# 2.1 Font Pairing - Too many font families
font_families = set()
# Check for @font-face, Google Fonts, font-family declarations
font_faces = re.findall(r'@font-face\s*\{[^}]*family:\s*["\']?([^;"\'\s}]+)', content, re.IGNORECASE)
google_fonts = re.findall(r'fonts\.googleapis\.com[^"\']*family=([^"&]+)', content, re.IGNORECASE)
font_family_css = re.findall(r'font-family:\s*([^;]+)', content, re.IGNORECASE)
for font in font_faces: font_families.add(font.strip().lower())
for font in google_fonts:
for f in font.replace('+', ' ').split('|'):
font_families.add(f.split(':')[0].strip().lower())
for family in font_family_css:
# Extract first font from stack
first_font = family.split(',')[0].strip().strip('"\'')
if first_font.lower() not in {'sans-serif', 'serif', 'monospace', 'cursive', 'fantasy', 'system-ui', 'inherit', 'arial', 'georgia', 'times new roman', 'courier new', 'verdana', 'helvetica', 'tahoma'}:
font_families.add(first_font.lower())
if len(font_families) > 3:
self.issues.append(f"[Typography] {filename}: {len(font_families)} font families detected. Limit to 2-3 for cohesion.")
# 2.2 Line Length - Character-based width
if has_long_text and not re.search(r'max-w-(?:prose|[\[\\]?\d+ch[\]\\]?)|max-width:\s*\d+ch', content):
self.warnings.append(f"[Typography] {filename}: No line length constraint (45-75ch). Use max-w-prose or max-w-[65ch].")
# 2.3 Line Height - Proper leading ratios
# Check for text without proper line-height
text_elements = len(re.findall(r'<p|<span|<div.*text|<h[1-6]', content, re.IGNORECASE))
if text_elements > 0 and not re.search(r'leading-|line-height:', content):
self.warnings.append(f"[Typography] {filename}: Text elements found without line-height. Body: 1.4-1.6, Headings: 1.1-1.3")
# Check for heading-specific line height issues
if re.search(r'<h[1-6]|text-(?:xl|2xl|3xl|4xl|5xl|6xl)', content, re.IGNORECASE):
# Extract line-height values
line_heights = re.findall(r'(?:leading-|line-height:\s*)([\d.]+)', content)
for lh in line_heights:
if float(lh) > 1.5:
self.warnings.append(f"[Typography] {filename}: Heading has line-height {lh} (>1.3). Headings should be tighter (1.1-1.3).")
# 2.4 Letter Spacing (Tracking)
# Uppercase without tracking
if re.search(r'uppercase|text-transform:\s*uppercase', content, re.IGNORECASE):
if not re.search(r'tracking-|letter-spacing:', content):
self.warnings.append(f"[Typography] {filename}: Uppercase text without tracking. ALL CAPS needs +5-10% spacing.")
# Large text (display/hero) should have negative tracking
if re.search(r'text-(?:4xl|5xl|6xl|7xl|8xl|9xl)|font-size:\s*[3-9]\dpx', content):
if not re.search(r'tracking-tight|letter-spacing:\s*-[0-9]', content):
self.warnings.append(f"[Typography] {filename}: Large display text without tracking-tight. Big text needs -1% to -4% spacing.")
# 2.5 Weight and Emphasis - Contrast levels
# Check for adjacent weight levels (poor contrast)
weights = re.findall(r'font-weight:\s*(\d+)|font-(?:thin|extralight|light|normal|medium|semibold|bold|extrabold|black)|fw-(\d+)', content, re.IGNORECASE)
weight_values = []
for w in weights:
val = w[0] or w[1]
if val:
# Map named weights to numbers
weight_map = {'thin': '100', 'extralight': '200', 'light': '300', 'normal': '400', 'medium': '500', 'semibold': '600', 'bold': '700', 'extrabold': '800', 'black': '900'}
val = weight_map.get(val.lower(), val)
try:
weight_values.append(int(val))
except: pass
# Check for adjacent weights (400/500, 500/600, etc.)
for i in range(len(weight_values) - 1):
diff = abs(weight_values[i] - weight_values[i+1])
if diff == 100:
self.warnings.append(f"[Typography] {filename}: Adjacent font weights ({weight_values[i]}/{weight_values[i+1]}). Skip at least 2 levels for contrast.")
# Too many weight levels
unique_weights = set(weight_values)
if len(unique_weights) > 4:
self.warnings.append(f"[Typography] {filename}: {len(unique_weights)} font weights. Limit to 3-4 per page.")
# 2.6 Responsive Typography - Fluid sizing with clamp()
has_font_sizes = bool(re.search(r'font-size:|text-(?:xs|sm|base|lg|xl|2xl)', content))
if has_font_sizes and not re.search(r'clamp\(|responsive:', content):
self.warnings.append(f"[Typography] {filename}: Fixed font sizes without clamp(). Consider fluid typography: clamp(MIN, PREFERRED, MAX)")
# 2.7 Hierarchy - Heading structure
headings = re.findall(r'<(h[1-6])', content, re.IGNORECASE)
if headings:
# Check for skipped levels (h1 -> h3)
for i in range(len(headings) - 1):
curr = int(headings[i][1])
next_h = int(headings[i+1][1])
if next_h > curr + 1:
self.warnings.append(f"[Typography] {filename}: Skipped heading level (h{curr} -> h{next_h}). Maintain sequential hierarchy.")
# Check if h1 exists for main content
if 'h1' not in [h.lower() for h in headings] and has_long_text:
self.warnings.append(f"[Typography] {filename}: No h1 found. Each page should have one primary heading.")
# 2.8 Modular Scale - Consistent sizing
# Extract font-size values
font_sizes = re.findall(r'font-size:\s*(\d+(?:\.\d+)?)(px|rem|em)', content)
size_values = []
for size, unit in font_sizes:
if unit == 'rem' or unit == 'em':
size_values.append(float(size))
elif unit == 'px':
size_values.append(float(size) / 16) # Normalize to rem
if len(size_values) > 2:
# Check if sizes follow a modular scale roughly
sorted_sizes = sorted(set(size_values))
ratios = []
for i in range(1, len(sorted_sizes)):
if sorted_sizes[i-1] > 0:
ratios.append(sorted_sizes[i] / sorted_sizes[i-1])
# Common scale ratios: 1.067, 1.125, 1.2, 1.25, 1.333, 1.5, 1.618
common_ratios = {1.067, 1.125, 1.2, 1.25, 1.333, 1.5, 1.618}
for ratio in ratios[:3]: # Check first 3 ratios
if not any(abs(ratio - cr) < 0.05 for cr in common_ratios):
self.warnings.append(f"[Typography] {filename}: Font sizes may not follow modular scale (ratio: {ratio:.2f}). Consider consistent ratio like 1.25 (Major Third).")
break
# 2.9 Readability - Content chunking
# Check for very long paragraphs (>5 lines estimated)
paragraphs = re.findall(r'<p[^>]*>([^<]+)</p>', content, re.IGNORECASE)
for p in paragraphs:
word_count = len(p.split())
if word_count > 100: # ~5-6 lines
self.warnings.append(f"[Typography] {filename}: Long paragraph detected ({word_count} words). Break into 3-4 line chunks for readability.")
# Check for missing subheadings in long content
if len(paragraphs) > 5:
subheadings = len(re.findall(r'<h[2-6]', content, re.IGNORECASE))
if subheadings == 0:
self.warnings.append(f"[Typography] {filename}: Long content without subheadings. Add h2/h3 to break up text.")
# --- 3. VISUAL EFFECTS (visual-effects.md) ---
# Glassmorphism Check
if 'backdrop-filter' in content or 'blur(' in content:
if not re.search(r'background:\s*rgba|bg-opacity|bg-[a-z0-9]+\/\d+', content):
self.warnings.append(f"[Visual] {filename}: Blur used without semi-transparent background (Glassmorphism fail)")
# GPU Acceleration / Performance
if re.search(r'@keyframes|transition:', content):
expensive_props = re.findall(r'width|height|top|left|right|bottom|margin|padding', content)
if expensive_props:
self.warnings.append(f"[Performance] {filename}: Animating expensive properties ({', '.join(set(expensive_props))}). Use transform/opacity where possible.")
# Reduced Motion
if not re.search(r'prefers-reduced-motion', content):
self.warnings.append(f"[Accessibility] {filename}: Animations found without prefers-reduced-motion check")
# Natural Shadows
shadows = re.findall(r'box-shadow:\s*([^;]+)', content)
for shadow in shadows:
# Check if natural (Y > X) or multiple layers
if ',' not in shadow and not re.search(r'\d+px\s+[1-9]\d*px', shadow): # Simple heuristic for Y-offset
self.warnings.append(f"[Visual] {filename}: Simple/Unnatural shadow detected. Consider multiple layers or Y > X offset for realism.")
# --- 3.1 NEOMORPHISM CHECK ---
# Check for neomorphism patterns (dual shadows with opposite directions)
neo_shadows = re.findall(r'box-shadow:\s*([^;]+)', content)
for shadow in neo_shadows:
# Neomorphism has two shadows: positive offset + negative offset
if ',' in shadow and '-' in shadow:
# Check for inset pattern (pressed state)
if 'inset' in shadow:
self.warnings.append(f"[Visual] {filename}: Neomorphism inset detected. Ensure adequate contrast for accessibility.")
# --- 3.2 SHADOW HIERARCHY ---
# Count shadow levels to check for elevation consistency
shadow_count = len(shadows)
if shadow_count > 0:
# Check for shadow opacity levels (should indicate hierarchy)
opacities = re.findall(r'rgba?\([^)]+,\s*([\d.]+)\)', content)
shadow_opacities = [float(o) for o in opacities if float(o) < 0.5]
if shadow_count >= 3 and len(shadow_opacities) > 0:
# Check if there's variety in shadow opacities for different elevations
unique_opacities = len(set(shadow_opacities))
if unique_opacities < 2:
self.warnings.append(f"[Visual] {filename}: All shadows at same opacity level. Vary shadow intensity for elevation hierarchy.")
# --- 3.3 GRADIENT CHECKS ---
# Check for gradient usage
has_gradient = bool(re.search(r'gradient|linear-gradient|radial-gradient|conic-gradient', content))
if has_gradient:
# Warn about mesh/aurora gradients (can be overused)
gradient_count = len(re.findall(r'gradient', content, re.IGNORECASE))
if gradient_count > 5:
self.warnings.append(f"[Visual] {filename}: Many gradients detected ({gradient_count}). Ensure this serves purpose, not decoration.")
else:
# Check if hero section exists without gradient
if has_hero and not re.search(r'background:|bg-', content):
self.warnings.append(f"[Visual] {filename}: Hero section without visual interest. Consider gradient for depth.")
# --- 3.4 BORDER EFFECTS ---
# Check for gradient borders or animated borders
has_border = bool(re.search(r'border:|border-', content))
if has_border:
# Check for overly complex borders
border_count = len(re.findall(r'border:', content))
if border_count > 8:
self.warnings.append(f"[Visual] {filename}: Many border declarations ({border_count}). Simplify for cleaner look.")
# --- 3.5 GLOW EFFECTS ---
# Check for text-shadow or multiple box-shadow layers (glow effects)
text_shadows = re.findall(r'text-shadow:', content)
for ts in text_shadows:
# Multiple text-shadow layers indicate glow
if ',' in ts:
self.warnings.append(f"[Visual] {filename}: Text glow effect detected. Ensure readability is maintained.")
# Check for box-shadow glow (multiple layers with 0 offset)
glow_shadows = re.findall(r'box-shadow:\s*[^;]*0\s+0\s+', content)
if len(glow_shadows) > 2:
self.warnings.append(f"[Visual] {filename}: Multiple glow effects detected. Use sparingly for emphasis only.")
# --- 3.6 OVERLAY TECHNIQUES ---
# Check for image overlays (for readability)
has_images = bool(re.search(r'<img|background-image:|bg-\[url', content))
if has_images and has_long_text:
has_overlay = bool(re.search(r'overlay|rgba\(0|gradient.*transparent|::after|::before', content))
if not has_overlay:
self.warnings.append(f"[Visual] {filename}: Text over image without overlay. Add gradient overlay for readability.")
# --- 3.7 PERFORMANCE: will-change ---
# Check for will-change usage
if re.search(r'will-change:', content):
will_change_props = re.findall(r'will-change:\s*([^;]+)', content)
for prop in will_change_props:
prop = prop.strip().lower()
if prop in ['width', 'height', 'top', 'left', 'right', 'bottom', 'margin', 'padding']:
self.issues.append(f"[Performance] {filename}: will-change on '{prop}' (layout property). Use only for transform/opacity.")
# Check for excessive will-change usage
will_change_count = len(re.findall(r'will-change:', content))
if will_change_count > 3:
self.warnings.append(f"[Performance] {filename}: Many will-change declarations ({will_change_count}). Use sparingly, only for heavy animations.")
# --- 3.8 EFFECT SELECTION ---
# Check for effect overuse (too many visual effects)
effect_count = (
(1 if has_gradient else 0) +
shadow_count +
len(re.findall(r'backdrop-filter|blur\(', content)) +
len(re.findall(r'text-shadow:', content))
)
if effect_count > 10:
self.warnings.append(f"[Visual] {filename}: Many visual effects ({effect_count}). Ensure effects serve purpose, not decoration.")
# Check for static/flat design (no depth)
if has_long_text and effect_count == 0:
self.warnings.append(f"[Visual] {filename}: Flat design with no depth. Consider shadows or subtle gradients for hierarchy.")
# --- 4. COLOR SYSTEM (color-system.md) ---
# 4.1 PURPLE BAN - Critical check from color-system.md
purple_hexes = ['#8B5CF6', '#A855F7', '#9333EA', '#7C3AED', '#6D28D9',
'#8B5CF6', '#A78BFA', '#C4B5FD', '#DDD6FE', '#EDE9FE',
'#8b5cf6', '#a855f7', '#9333ea', '#7c3aed', '#6d28d9',
'purple', 'violet', 'fuchsia', 'magenta', 'lavender']
for purple in purple_hexes:
if purple.lower() in content.lower():
self.issues.append(f"[Color] {filename}: PURPLE DETECTED ('{purple}'). Banned by Maestro rules. Use Teal/Cyan/Emerald instead.")
break
# 4.2 60-30-10 Rule check
# Count color usage to estimate ratio
color_hex_count = len(re.findall(r'#[0-9a-fA-F]{3,6}', content))
hsl_count = len(re.findall(r'hsl\(', content))
total_colors = color_hex_count + hsl_count
if total_colors > 3:
# Check for dominant colors (should be ~60%)
bg_declarations = re.findall(r'(?:background|bg-|bg\[)([^;}\s]+)', content)
text_declarations = re.findall(r'(?:color|text-)([^;}\s]+)', content)
if len(bg_declarations) > 0 and len(text_declarations) > 0:
# Just warn if too many distinct colors
unique_hexes = set(re.findall(r'#[0-9a-fA-F]{6}', content))
if len(unique_hexes) > 5:
self.warnings.append(f"[Color] {filename}: {len(unique_hexes)} distinct colors. Consider 60-30-10 rule: dominant (60%), secondary (30%), accent (10%).")
# 4.3 Color Scheme Pattern Detection
# Detect monochromatic (same hue, different lightness)
hsl_matches = re.findall(r'hsl\((\d+),\s*\d+%,\s*\d+%\)', content)
if len(hsl_matches) >= 3:
hues = [int(h) for h in hsl_matches]
hue_range = max(hues) - min(hues)
if hue_range < 10:
self.warnings.append(f"[Color] {filename}: Monochromatic palette detected (hue variance: {hue_range}deg). Ensure adequate contrast.")
# 4.4 Dark Mode Compliance
# Check for pure black (#000000) or pure white (#FFFFFF) text (forbidden)
if re.search(r'color:\s*#000000|#000\b', content):
self.warnings.append(f"[Color] {filename}: Pure black (#000000) detected. Use #1a1a1a or darker grays for better dark mode.")
if re.search(r'background:\s*#ffffff|#fff\b', content) and re.search(r'dark:\s*|dark:', content):
self.warnings.append(f"[Color] {filename}: Pure white background in dark mode context. Use slight off-white (#f9fafb) for reduced eye strain.")
# 4.5 WCAG Contrast Pattern Check
# Look for potential low-contrast combinations
light_bg_light_text = bool(re.search(r'bg-(?:gray|slate|zinc)-50|bg-white.*text-(?:gray|slate)-[12]', content))
dark_bg_dark_text = bool(re.search(r'bg-(?:gray|slate|zinct)-9|bg-black.*text-(?:gray|slate)-[89]', content))
if light_bg_light_text or dark_bg_dark_text:
self.warnings.append(f"[Color] {filename}: Possible low-contrast combination detected. Verify WCAG AA (4.5:1 for text).")
# 4.6 Color Psychology Context Check
# Warn if blue used for food/restaurant context
has_blue = bool(re.search(r'bg-blue|text-blue|from-blue|#[0-9a-fA-F]*00[0-9A-Fa-f]{2}|#[0-9a-fA-F]*1[0-9A-Fa-f]{2}', content))
has_food_context = bool(re.search(r'restaurant|food|cooking|recipe|menu|dish|meal', content, re.IGNORECASE))
if has_blue and has_food_context:
self.warnings.append(f"[Color] {filename}: Blue color in food context. Blue suppresses appetite; consider warm colors (red, orange, yellow).")
# 4.7 HSL-Based Palette Detection
# Check if using HSL for palette (recommended in color-system.md)
has_color_vars = bool(re.search(r'--color-|color-|primary-|secondary-', content))
if has_color_vars and not re.search(r'hsl\(', content):
self.warnings.append(f"[Color] {filename}: Color variables without HSL. Consider HSL for easier palette adjustment (Hue, Saturation, Lightness).")
# --- 5. ANIMATION GUIDE (animation-guide.md) ---
# 5.1 Duration Appropriateness
# Check for excessively long or short animations
durations = re.findall(r'(?:duration|animation-duration|transition-duration):\s*([\d.]+)(s|ms)', content)
for duration, unit in durations:
duration_ms = float(duration) * (1000 if unit == 's' else 1)
if duration_ms < 50:
self.warnings.append(f"[Animation] {filename}: Very fast animation ({duration}{unit}). Minimum 50ms for visibility.")
elif duration_ms > 1000 and 'transition' in content.lower():
self.warnings.append(f"[Animation] {filename}: Long transition ({duration}{unit}). Transitions should be 100-300ms for responsiveness.")
# 5.2 Easing Function Correctness
# Check for incorrect easing patterns
if re.search(r'ease-in\s+.*entry|fade-in.*ease-in', content):
self.warnings.append(f"[Animation] {filename}: Entry animation with ease-in. Entry should use ease-out for snappy feel.")
if re.search(r'ease-out\s+.*exit|fade-out.*ease-out', content):
self.warnings.append(f"[Animation] {filename}: Exit animation with ease-out. Exit should use ease-in for natural feel.")
# 5.3 Micro-interaction Feedback Patterns
# Check for interactive elements without hover/focus states
interactive_elements = len(re.findall(r'<button|<a\s+href|onClick|@click', content))
has_hover_focus = bool(re.search(r'hover:|focus:|:hover|:focus', content))
if interactive_elements > 2 and not has_hover_focus:
self.warnings.append(f"[Animation] {filename}: Interactive elements without hover/focus states. Add micro-interactions for feedback.")
# 5.4 Loading State Indicators
# Check for loading patterns
has_async = bool(re.search(r'async|await|fetch|axios|loading|isLoading', content))
has_loading_indicator = bool(re.search(r'skeleton|spinner|progress|loading|<circle.*animate', content))
if has_async and not has_loading_indicator:
self.warnings.append(f"[Animation] {filename}: Async operations without loading indicator. Add skeleton or spinner for perceived performance.")
# 5.5 Page Transition Patterns
# Check for page/view transitions
has_routing = bool(re.search(r'router|navigate|Link.*to|useHistory', content))
has_page_transition = bool(re.search(r'AnimatePresence|motion\.|transition.*page|fade.*route', content))
if has_routing and not has_page_transition:
self.warnings.append(f"[Animation] {filename}: Routing detected without page transitions. Consider fade/slide for context continuity.")
# 5.6 Scroll Animation Performance
# Check for scroll-driven animations
has_scroll_anim = bool(re.search(r'onScroll|scroll.*trigger|IntersectionObserver', content))
if has_scroll_anim:
# Check if using expensive properties in scroll handlers
if re.search(r'onScroll.*[^\w](width|height|top|left)', content):
self.issues.append(f"[Animation] {filename}: Scroll handler animating layout properties. Use transform/opacity for 60fps.")
# --- 6. MOTION GRAPHICS (motion-graphics.md) ---
# 6.1 Lottie Animation Checks
has_lottie = bool(re.search(r'lottie|Lottie|@lottie-react', content))
if has_lottie:
# Check for reduced motion fallback
has_lottie_fallback = bool(re.search(r'prefers-reduced-motion.*lottie|lottie.*isPaused|lottie.*stop', content))
if not has_lottie_fallback:
self.warnings.append(f"[Motion] {filename}: Lottie animation without reduced-motion fallback. Add pause/stop for accessibility.")
# 6.2 GSAP Memory Leak Risks
has_gsap = bool(re.search(r'gsap|ScrollTrigger|from\(.*gsap', content))
if has_gsap:
# Check for cleanup patterns
has_gsap_cleanup = bool(re.search(r'kill\(|revert\(|useEffect.*return.*gsap', content))
if not has_gsap_cleanup:
self.issues.append(f"[Motion] {filename}: GSAP animation without cleanup (kill/revert). Memory leak risk on unmount.")
# 6.3 SVG Animation Performance
svg_animations = re.findall(r'<animate|<animateTransform|stroke-dasharray|stroke-dashoffset', content)
if len(svg_animations) > 3:
self.warnings.append(f"[Motion] {filename}: Multiple SVG animations detected. Ensure stroke-dashoffset is used sparingly for mobile performance.")
# 6.4 3D Transform Performance
has_3d_transform = bool(re.search(r'transform3d|perspective\(|rotate3d|translate3d', content))
if has_3d_transform:
# Check for perspective on parent
has_perspective_parent = bool(re.search(r'perspective:\s*\d+px|perspective\s*\(', content))
if not has_perspective_parent:
self.warnings.append(f"[Motion] {filename}: 3D transform without perspective parent. Add perspective: 1000px for realistic depth.")
# Warn about mobile performance
self.warnings.append(f"[Motion] {filename}: 3D transforms detected. Test on mobile; can impact performance on low-end devices.")
# 6.5 Particle Effect Warnings
# Check for canvas/WebGL particle systems
has_particles = bool(re.search(r'particle|canvas.*loop|requestAnimationFrame.*draw|Three\.js', content))
if has_particles:
self.warnings.append(f"[Motion] {filename}: Particle effects detected. Ensure fallback or reduced-quality option for mobile devices.")
# 6.6 Scroll-Driven Animation Performance
has_scroll_driven = bool(re.search(r'IntersectionObserver.*animate|scroll.*progress|view-timeline', content))
if has_scroll_driven:
# Check for throttling/debouncing
has_throttle = bool(re.search(r'throttle|debounce|requestAnimationFrame', content))
if not has_throttle:
self.issues.append(f"[Motion] {filename}: Scroll-driven animation without throttling. Add requestAnimationFrame for 60fps.")
# 6.7 Motion Decision Tree - Context Check
# Check if animation serves purpose (not just decoration)
total_animations = (
len(re.findall(r'@keyframes|transition:|animate-', content)) +
(1 if has_lottie else 0) +
(1 if has_gsap else 0)
)
if total_animations > 5:
# Check if animations are functional
functional_animations = len(re.findall(r'hover:|focus:|disabled|loading|error|success', content))
if functional_animations < total_animations / 2:
self.warnings.append(f"[Motion] {filename}: Many animations ({total_animations}). Ensure majority serve functional purpose (feedback, guidance), not decoration.")
# --- 7. ACCESSIBILITY ---
if re.search(r'<img(?![^>]*alt=)[^>]*>', content):
self.issues.append(f"[Accessibility] {filename}: Missing img alt text")
def audit_directory(self, directory: str) -> None:
extensions = {'.tsx', '.jsx', '.html', '.vue', '.svelte', '.css'}
for root, dirs, files in os.walk(directory):
dirs[:] = [d for d in dirs if d not in {'node_modules', '.git', 'dist', 'build', '.next', 'ui'}]
for file in files:
if Path(file).suffix in extensions:
self.audit_file(os.path.join(root, file))
def get_report(self):
return {
"files_checked": self.files_checked,
"issues": self.issues,
"warnings": self.warnings,
"passed_checks": self.passed_count,
"compliant": len(self.issues) == 0
}
def main():
if len(sys.argv) < 2: sys.exit(1)
path = sys.argv[1]
is_json = "--json" in sys.argv
auditor = UXAuditor()
if os.path.isfile(path): auditor.audit_file(path)
else: auditor.audit_directory(path)
report = auditor.get_report()
if is_json:
print(json.dumps(report))
else:
# Use ASCII-safe output for Windows console compatibility
print(f"\n[UX AUDIT] {report['files_checked']} files checked")
print("-" * 50)
if report['issues']:
print(f"[!] ISSUES ({len(report['issues'])}):")
for i in report['issues'][:10]: print(f" - {i}")
if report['warnings']:
print(f"[*] WARNINGS ({len(report['warnings'])}):")
for w in report['warnings'][:15]: print(f" - {w}")
print(f"[+] PASSED CHECKS: {report['passed_checks']}")
status = "PASS" if report['compliant'] else "FAIL"
print(f"STATUS: {status}")
sys.exit(0 if report['compliant'] else 1)
if __name__ == "__main__":
main()
Typography System Reference
Typography principles and decision-making - learn to think, not memorize.
No fixed font names or sizes - understand the system.
---
1. Modular Scale Principles
What is a Modular Scale?
A mathematical relationship between font sizes:
├── Pick a BASE size (usually body text)
├── Pick a RATIO (multiplier)
└── Generate all sizes using: base × ratio^nCommon Ratios and When to Use
| Ratio | Value | Feeling | Best For |
|---|---|---|---|
| Minor Second | 1.067 | Very subtle | Dense UI, small screens |
| Major Second | 1.125 | Subtle | Compact interfaces |
| Minor Third | 1.2 | Comfortable | Mobile apps, cards |
| Major Third | 1.25 | Balanced | General web (most common) |
| Perfect Fourth | 1.333 | Noticeable | Editorial, blogs |
| Perfect Fifth | 1.5 | Dramatic | Headlines, marketing |
| Golden Ratio | 1.618 | Maximum impact | Hero sections, display |
Generate Your Scale
Given: base = YOUR_BASE_SIZE, ratio = YOUR_RATIO
Scale:
├── xs: base ÷ ratio²
├── sm: base ÷ ratio
├── base: YOUR_BASE_SIZE
├── lg: base × ratio
├── xl: base × ratio²
├── 2xl: base × ratio³
├── 3xl: base × ratio⁴
└── ... continue as neededChoosing Base Size
| Context | Base Size Range | Why |
|---|---|---|
| Mobile-first | 16-18px | Readability on small screens |
| Desktop app | 14-16px | Information density |
| Editorial | 18-21px | Long-form reading comfort |
| Accessibility focus | 18px+ | Easier to read |
---
2. Font Pairing Principles
What Makes Fonts Work Together
Contrast + Harmony:
├── Different ENOUGH to create hierarchy
├── Similar ENOUGH to feel cohesive
└── Usually: serif + sans, or display + neutralPairing Strategies
| Strategy | How | Result |
|---|---|---|
| Contrast | Serif heading + Sans body | Classic, editorial feel |
| Same Family | One variable font, different weights | Cohesive, modern |
| Same Designer | Fonts by same foundry | Often harmonious proportions |
| Era Match | Fonts from same time period | Historical consistency |
What to Look For
When pairing, compare:
├── x-height (height of lowercase letters)
├── Letter width (narrow vs wide)
├── Stroke contrast (thin/thick variation)
└── Overall mood (formal vs casual)Safe Pairing Patterns
| Heading Style | Body Style | Mood |
|---|---|---|
| Geometric sans | Humanist sans | Modern, friendly |
| Display serif | Clean sans | Editorial, sophisticated |
| Neutral sans | Same sans | Minimal, tech |
| Bold geometric | Light geometric | Contemporary |
Avoid
- ❌ Two decorative fonts together
- ❌ Similar fonts that conflict
- ❌ More than 2-3 font families
- ❌ Fonts with very different x-heights
---
3. Line Height Principles
The Relationship
Line height depends on:
├── Font size (larger text = less line height needed)
├── Line length (longer lines = more line height)
├── Font design (some fonts need more space)
└── Content type (headings vs body)Guidelines by Context
| Content Type | Line Height Range | Why |
|---|---|---|
| Headings | 1.1 - 1.3 | Short lines, want compact |
| Body text | 1.4 - 1.6 | Comfortable reading |
| Long-form | 1.6 - 1.8 | Maximum readability |
| UI elements | 1.2 - 1.4 | Space efficiency |
Adjustment Factors
- Longer line length → Increase line height
- Larger font size → Decrease line height ratio
- All caps → May need more line height
- Tight tracking → May need more line height
---
4. Line Length Principles
Optimal Reading Width
The sweet spot: 45-75 characters per line
├── < 45: Too choppy, breaks flow
├── 45-75: Comfortable reading
├── > 75: Eye tracking strainHow to Measure
/* Character-based (recommended) */
max-width: 65ch; /* ch = width of "0" character */
/* This adapts to font size automatically */Context Adjustments
| Context | Character Range |
|---|---|
| Desktop article | 60-75 characters |
| Mobile | 35-50 characters |
| Sidebar text | 30-45 characters |
| Wide monitors | Still cap at ~75ch |
---
5. Responsive Typography Principles
The Problem
Fixed sizes don't scale well:
├── Desktop size too big on mobile
├── Mobile size too small on desktop
└── Breakpoint jumps feel jarringFluid Typography (clamp)
/* Syntax: clamp(MIN, PREFERRED, MAX) */
font-size: clamp(
MINIMUM_SIZE,
FLUID_CALCULATION,
MAXIMUM_SIZE
);
/* FLUID_CALCULATION typically:
base + viewport-relative-unit */Scaling Strategy
| Element | Scaling Behavior |
|---|---|
| Body text | Slight scaling (1rem → 1.125rem) |
| Subheadings | Moderate scaling |
| Headings | More dramatic scaling |
| Display text | Most dramatic scaling |
---
6. Weight and Emphasis Principles
Semantic Weight Usage
| Weight Range | Name | Use For |
|---|---|---|
| 300-400 | Light/Normal | Body text, paragraphs |
| 500 | Medium | Subtle emphasis |
| 600 | Semibold | Subheadings, labels |
| 700 | Bold | Headings, strong emphasis |
| 800-900 | Heavy/Black | Display, hero text |
Creating Contrast
Good contrast = skip at least 2 weight levels
├── 400 body + 700 heading = good
├── 400 body + 500 emphasis = subtle
├── 600 heading + 700 subheading = too similarAvoid
- ❌ Too many weights (max 3-4 per page)
- ❌ Adjacent weights for hierarchy (400/500)
- ❌ Heavy weights for long text
---
7. Letter Spacing (Tracking)
Principles
Large text (headings): tighter tracking
├── Letters are big, gaps feel larger
└── Slight negative tracking looks better
Small text (body): normal or slightly wider
├── Improves readability at small sizes
└── Never negative for body text
ALL CAPS: always wider tracking
├── Uppercase lacks ascenders/descenders
└── Needs more space to feel rightAdjustment Guidelines
| Context | Tracking Adjustment |
|---|---|
| Display/Hero | -2% to -4% |
| Headings | -1% to -2% |
| Body text | 0% (normal) |
| Small text | +1% to +2% |
| ALL CAPS | +5% to +10% |
---
8. Hierarchy Principles
Visual Hierarchy Through Type
Ways to create hierarchy:
├── SIZE (most obvious)
├── WEIGHT (bold stands out)
├── COLOR (contrast levels)
├── SPACING (margins separate sections)
└── POSITION (top = important)Typical Hierarchy
| Level | Characteristics |
|---|---|
| Primary (H1) | Largest, boldest, most distinct |
| Secondary (H2) | Noticeably smaller but still bold |
| Tertiary (H3) | Medium size, may use weight only |
| Body | Standard size and weight |
| Caption/Meta | Smaller, often lighter color |
Testing Hierarchy
Ask: "Can I tell what's most important at a glance?"
If squinting at the page, the hierarchy should still be clear.
---
9. Readability Psychology
F-Pattern Reading
Users scan in F-pattern:
├── Across the top (first line)
├── Down the left side
├── Across again (subheading)
└── Continue down leftImplication: Key info on left and in headings
Chunking for Comprehension
- Short paragraphs (3-4 lines max)
- Clear subheadings
- Bullet points for lists
- White space between sections
Cognitive Ease
- Familiar fonts = easier reading
- High contrast = less strain
- Consistent patterns = predictable
---
10. Typography Selection Checklist
Before finalizing typography:
- [ ] Asked user for font preferences?
- [ ] Considered brand/context?
- [ ] Selected appropriate scale ratio?
- [ ] Limited to 2-3 font families?
- [ ] Tested readability at all sizes?
- [ ] Checked line length (45-75ch)?
- [ ] Verified contrast for accessibility?
- [ ] Different from your last project?
Anti-Patterns
- ❌ Same fonts every project
- ❌ Too many font families
- ❌ Ignoring readability for style
- ❌ Fixed sizes without responsiveness
- ❌ Decorative fonts for body text
---
Remember: Typography is about communication clarity. Choose based on content needs and audience, not personal preference.
Visual Effects Reference
Modern CSS effect principles and techniques - learn the concepts, create variations.
No fixed values to copy - understand the patterns.
---
1. Glassmorphism Principles
What Makes Glassmorphism Work
Key Properties:
├── Semi-transparent background (not solid)
├── Backdrop blur (frosted glass effect)
├── Subtle border (for definition)
└── Often: light shadow for depthThe Pattern (Customize Values)
.glass {
/* Transparency: adjust opacity based on content readability */
background: rgba(R, G, B, OPACITY);
/* OPACITY: 0.1-0.3 for dark bg, 0.5-0.8 for light bg */
/* Blur: higher = more frosted */
backdrop-filter: blur(AMOUNT);
/* AMOUNT: 8-12px subtle, 16-24px strong */
/* Border: defines edges */
border: 1px solid rgba(255, 255, 255, OPACITY);
/* OPACITY: 0.1-0.3 typically */
/* Radius: match your design system */
border-radius: YOUR_RADIUS;
}When to Use Glassmorphism
- ✅ Over colorful/image backgrounds
- ✅ Modals, overlays, cards
- ✅ Navigation bars with scrolling content behind
- ❌ Text-heavy content (readability issues)
- ❌ Simple solid backgrounds (pointless)
When NOT to Use
- Low contrast situations
- Accessibility-critical content
- Performance-constrained devices
---
2. Neomorphism Principles
What Makes Neomorphism Work
Key Concept: Soft, extruded elements using DUAL shadows
├── Light shadow (from light source direction)
├── Dark shadow (opposite direction)
└── Background matches surrounding (same color)The Pattern
.neo-raised {
/* Background MUST match parent */
background: SAME_AS_PARENT;
/* Two shadows: light direction + dark direction */
box-shadow:
OFFSET OFFSET BLUR rgba(light-color),
-OFFSET -OFFSET BLUR rgba(dark-color);
/* OFFSET: typically 6-12px */
/* BLUR: typically 12-20px */
}
.neo-pressed {
/* Inset creates "pushed in" effect */
box-shadow:
inset OFFSET OFFSET BLUR rgba(dark-color),
inset -OFFSET -OFFSET BLUR rgba(light-color);
}Accessibility Warning
⚠️ Low contrast - use sparingly, ensure clear boundaries
When to Use
- Decorative elements
- Subtle interactive states
- Minimalist UI with flat colors
---
3. Shadow Hierarchy Principles
Concept: Shadows Indicate Elevation
Higher elevation = larger shadow
├── Level 0: No shadow (flat on surface)
├── Level 1: Subtle shadow (slightly raised)
├── Level 2: Medium shadow (cards, buttons)
├── Level 3: Large shadow (modals, dropdowns)
└── Level 4: Deep shadow (floating elements)Shadow Properties to Adjust
box-shadow: OFFSET-X OFFSET-Y BLUR SPREAD COLOR;
/* Offset: direction of shadow */
/* Blur: softness (larger = softer) */
/* Spread: size expansion */
/* Color: typically black with low opacity */Principles for Natural Shadows
1. Y-offset larger than X (light comes from above) 2. Low opacity (5-15% for subtle, 15-25% for pronounced) 3. Multiple layers for realism (ambient + direct) 4. Blur scales with offset (larger offset = larger blur)
Dark Mode Shadows
- Shadows less visible on dark backgrounds
- May need to increase opacity
- Or use glow/highlight instead
---
4. Gradient Principles
Types and When to Use
| Type | Pattern | Use Case |
|---|---|---|
| Linear | Color A → Color B along line | Backgrounds, buttons, headers |
| Radial | Center → outward | Spotlights, focal points |
| Conic | Around center | Pie charts, creative effects |
Creating Harmonious Gradients
Good Gradient Rules:
├── Use ADJACENT colors on wheel (analogous)
├── Or same hue with different lightness
├── Avoid complementary (can look harsh)
└── Add middle stops for smoother transitionsGradient Syntax Pattern
.gradient {
background: linear-gradient(
DIRECTION, /* angle or to-keyword */
COLOR-STOP-1, /* color + optional position */
COLOR-STOP-2,
/* ... more stops */
);
}
/* DIRECTION examples: */
/* 90deg, 135deg, to right, to bottom right */Mesh Gradients
Multiple radial gradients overlapped:
├── Each at different position
├── Each with transparent falloff
├── Use with INTENT — overused as a lazy "wow" default
└── Creates organic, colorful effect; pair with a deliberate palette---
5. Border Effects Principles
Gradient Borders
Technique: Pseudo-element with gradient background
├── Element has padding = border width
├── Pseudo-element fills with gradient
└── Mask or clip creates border effectAnimated Borders
Technique: Rotating gradient or conic sweep
├── Pseudo-element larger than content
├── Animation rotates the gradient
└── Overflow hidden clips to shapeGlow Borders
/* Multiple box-shadows create glow */
box-shadow:
0 0 SMALL-BLUR COLOR,
0 0 MEDIUM-BLUR COLOR,
0 0 LARGE-BLUR COLOR;
/* Each layer adds to the glow */---
6. Glow Effects Principles
Text Glow
text-shadow:
0 0 BLUR-1 COLOR,
0 0 BLUR-2 COLOR,
0 0 BLUR-3 COLOR;
/* Multiple layers = stronger glow */
/* Larger blur = softer spread */Element Glow
box-shadow:
0 0 BLUR-1 COLOR,
0 0 BLUR-2 COLOR;
/* Use color matching element for realistic glow */
/* Lower opacity for subtle, higher for neon */Pulsing Glow Animation
@keyframes glow-pulse {
0%, 100% { box-shadow: 0 0 SMALL-BLUR COLOR; }
50% { box-shadow: 0 0 LARGE-BLUR COLOR; }
}
/* Easing and duration affect feel */---
7. Overlay Techniques
Gradient Overlay on Images
Purpose: Improve text readability over images
Pattern: Gradient from transparent to opaque
Position: Where text will appear.overlay::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(
DIRECTION,
transparent PERCENTAGE,
rgba(0,0,0,OPACITY) 100%
);
}Colored Overlay
/* Blend mode or layered gradient */
background:
linear-gradient(YOUR-COLOR-WITH-OPACITY),
url('image.jpg');---
8. Modern CSS Techniques
Container Queries (Concept)
Instead of viewport breakpoints:
├── Component responds to ITS container
├── Truly modular, reusable components
└── Syntax: @container (condition) { }:has() Selector (Concept)
Parent styling based on children:
├── "Parent that has X child"
├── Enables previously impossible patterns
└── Progressive enhancement approachScroll-Driven Animations (Concept)
Animation progress tied to scroll:
├── Entry/exit animations on scroll
├── Parallax effects
├── Progress indicators
└── View-based or scroll-based timeline---
9. Performance Principles
GPU-Accelerated Properties
CHEAP to animate (GPU):
├── transform (translate, scale, rotate)
└── opacity
EXPENSIVE to animate (CPU):
├── width, height
├── top, left, right, bottom
├── margin, padding
└── box-shadow (recalculates)will-change Usage
/* Use sparingly, only for heavy animations */
.heavy-animation {
will-change: transform;
}
/* Remove after animation if possible */Reduced Motion
@media (prefers-reduced-motion: reduce) {
/* Disable or minimize animations */
/* Respect user preference */
}---
10. Effect Selection Checklist
Before applying any effect:
- [ ] Does it serve a purpose? (not just decoration)
- [ ] Is it appropriate for the context? (brand, audience)
- [ ] Have you varied from previous projects? (avoid repetition)
- [ ] Is it accessible? (contrast, motion sensitivity)
- [ ] Is it performant? (especially on mobile)
- [ ] Did you ask user preference? (if style open-ended)
Anti-Patterns
- ❌ Glassmorphism on every element (kitsch)
- ❌ Dark + neon as default (lazy AI look)
- ❌ Flat with no intent (depth absent by accident, not by choice)
- ❌ Effects that hurt readability
- ❌ Animations without purpose
---
Remember: Effects enhance meaning. Choose based on purpose and context, not because it "looks cool."
Related skills
Forks & variants (1)
Frontend Design has 1 known copy in the catalog totaling 20 installs. They canonicalize to this original listing.
- vudovn - 20 installs
How it compares
Use frontend-design before coding to set aesthetic direction and anti-slop rules; pair with a post-build accessibility audit skill when the goal is compliance checking rather than design generation.
FAQ
What does the frontend-design skill do?
frontend-design is an ag-kit agent skill that reads a web UI brief, outputs a one-line Design Read, tunes three design dials, and guides React or Next.js implementation. It targets landing pages, portfolios, and redesigns while blocking common AI template patterns like purple gra
How do you install frontend-design from antigravity-kit?
Install frontend-design with npx skills add https://github.com/vudovn/antigravity-kit --skill frontend-design. The skill lives under .agents/skills/frontend-design/ in the ag-kit repo alongside 44 other domain skills and 20 specialist agent personas.
Does frontend-design work for mobile app UI?
frontend-design explicitly excludes mobile apps and dashboards. Its when_to_use frontmatter directs agents to the separate mobile-design skill for native mobile UI, while frontend-design covers browser landing pages, portfolios, marketing sites, and web redesigns.