.claude/skills/frontend-visual-design/SKILL.md
Use when a Blazor or web application needs intentional visual design beyond default Bootstrap styling, when scaffolding a greenfield app that should look polished rather than generic, or when the design brief requires aesthetic direction (typography, color, motion, spatial composition). Covers the design thinking process, aesthetic vocabulary, font pairing, color palette composition, animation patterns for Blazor, and anti-generic design principles. Domain: UI, Visual Design, Blazor. Level: Intermediate. Tags: design, typography, color, animation, aesthetics, layout, blazor, visual-quality.
npx skillsauth add klod68/littlerae frontend-visual-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Technical CSS framework setup (Bootstrap wired, variables defined, isolation configured) is necessary but not sufficient for a polished product. Without intentional visual design, every Blazor app converges on the same generic appearance: system fonts, default Bootstrap gray, uniform card grids, and zero personality. Users perceive these as "AI-generated" or "developer-designed" — functional but forgettable.
The gap is not technical — it is intentional. No one in the pipeline asks "what should this look like?" before scaffolding begins. The Solution Designer defines component hierarchy and data flow; the Scaffolder creates files; the Implementer fills logic. Visual design falls through the cracks because no artifact captures aesthetic intent.
Do NOT use for:
web-ui-styling — that skill decides Bootstrap vs MudBlazor vs Tailwind)blazor.md rules)Before any markup is written, the design brief must answer four questions. This process applies at Stage 1 (Solution Designer) of the frontend pipeline.
What problem does this interface solve? Who uses it? Context drives every visual decision.
| Application Type | Visual Priority | Tone | |---|---|---| | Internal admin dashboard | Clarity, density, scanability | Professional, utilitarian | | Public documentation site | Readability, navigation, trust | Clean, authoritative | | Customer-facing portal | Brand alignment, delight, trust | Polished, branded | | Demo / showcase site | Impact, memorability, exploration | Bold, distinctive | | Data analytics dashboard | Information density, comparison | Precise, technical |
Commit to a visual direction. Declare it in the design brief as a one-phrase descriptor. These are reference points — combine or adapt, but never ship "no direction."
| Direction | Character | When It Works | |---|---|---| | Clean professional | Generous whitespace, muted palette, clear hierarchy | Business apps, SaaS dashboards, enterprise tools | | Bold editorial | Strong typography, asymmetric layout, dramatic contrast | Marketing sites, portfolios, documentation with personality | | Soft modern | Rounded corners, pastel accents, light shadows, warm tones | Consumer apps, onboarding flows, friendly tools | | Dark technical | Dark surfaces, monospace accents, subtle glow effects, high contrast text | Developer tools, CLI companions, monitoring dashboards | | Minimal refined | Maximum whitespace, restrained palette, precise alignment, no decoration | Luxury, premium, or design-conscious brands | | Data-dense utilitarian | Compact spacing, small type, borders over shadows, maximum information | Trading platforms, operations dashboards, admin panels |
Technical and brand constraints that bound the visual design:
web-ui-styling decision)What is the one visual detail someone will remember? Every polished app has one:
If the brief cannot name a signature element, the design is generic.
Typography is the highest-leverage visual improvement. Upgrading from Bootstrap's default system font stack to a considered font pairing transforms the entire feel of an application.
Pair a display font (headings, hero text) with a body font (paragraphs, UI labels). Contrast in style, harmonize in proportion.
| Pairing Strategy | Display Font | Body Font | Character | |---|---|---|---| | Geometric + Humanist | Poppins, Outfit, Plus Jakarta Sans | Source Sans 3, Nunito Sans | Modern, friendly | | Serif + Sans | Playfair Display, Lora, Merriweather | Inter, Open Sans | Editorial, authoritative | | Mono + Sans | JetBrains Mono, Fira Code | IBM Plex Sans, Rubik | Technical, developer-oriented | | Rounded + Clean | Nunito, Quicksand | Lato, Noto Sans | Approachable, soft | | Sharp + Neutral | Manrope, Sora, General Sans | DM Sans, Work Sans | Contemporary, clean |
Add to App.razor <head>, before Bootstrap CSS:
<!-- Google Fonts — load before Bootstrap so font-family overrides apply -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=Source+Sans+3:wght@400;600&display=swap"
rel="stylesheet" />
Apply in wwwroot/css/app.css:
:root {
--app-font-display: 'Plus Jakarta Sans', sans-serif;
--app-font-body: 'Source Sans 3', sans-serif;
--app-font-mono: 'JetBrains Mono', monospace;
}
body {
font-family: var(--app-font-body);
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--app-font-display);
font-weight: 600;
}
code, pre, .font-mono {
font-family: var(--app-font-mono);
}
--app-font-*) — never hardcode font-family per componentdisplay=swap on Google Fonts to prevent invisible text during loadA cohesive palette is more than Bootstrap's $primary blue. Design the full color system
in the design brief.
| Role | Purpose | Example |
|---|---|---|
| Primary | Brand action color — buttons, links, active states | #2563eb (blue) |
| Accent | Secondary emphasis — badges, highlights, decorative elements | #f59e0b (amber) |
| Surface | Background layers — cards, modals, sidebar | #ffffff, #f8f9fa, #1e1e2e |
| Text | Content hierarchy — headings, body, muted | #111827, #6b7280, #9ca3af |
| Semantic | Status signals — success, warning, error, info | Standard green/yellow/red/blue |
:root {
--app-primary: #2563eb;
--app-primary-hover: #1d4ed8;
--app-accent: #f59e0b;
--app-surface-0: #ffffff;
--app-surface-1: #f8f9fa;
--app-surface-2: #e9ecef;
--app-text-primary: #111827;
--app-text-secondary: #6b7280;
--app-text-muted: #9ca3af;
}
[data-bs-theme="dark"] {
--app-surface-0: #0f172a;
--app-surface-1: #1e293b;
--app-surface-2: #334155;
--app-text-primary: #f1f5f9;
--app-text-secondary: #94a3b8;
--app-text-muted: #64748b;
}
Animation adds perceived quality. In Blazor, CSS-only animations are preferred over JS because they avoid SignalR round-trips and work in both SSR and interactive modes.
| Pattern | Where | CSS Technique |
|---|---|---|
| Page load reveal | Page content on first render | @keyframes fadeInUp with staggered animation-delay |
| Card hover lift | Interactive cards | transform: translateY(-4px) + box-shadow transition |
| Sidebar collapse | Navigation | transition: width 0.3s ease with overflow: hidden |
| Loading skeleton | Data-loading states | @keyframes shimmer with gradient background-position animation |
| Button press | Action buttons | transform: scale(0.97) on :active |
| Toast slide-in | Notifications | @keyframes slideInRight with transform: translateX() |
/* In app.css or component .razor.css */
.stagger-in {
opacity: 0;
transform: translateY(12px);
animation: fadeInUp 0.4s ease forwards;
}
.stagger-in:nth-child(1) { animation-delay: 0.05s; }
.stagger-in:nth-child(2) { animation-delay: 0.10s; }
.stagger-in:nth-child(3) { animation-delay: 0.15s; }
.stagger-in:nth-child(4) { animation-delay: 0.20s; }
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
.skeleton {
background: linear-gradient(90deg,
var(--app-surface-1) 25%,
var(--app-surface-2) 50%,
var(--app-surface-1) 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
ease or ease-out timing — never linear for UI motion (feels mechanical)prefers-reduced-motion: reduce is set (accessibility)@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important; /* effectively instant */
transition-duration: 0.01ms !important;
}
}
Layout is not "put things in a grid." Intentional spatial composition creates visual hierarchy and guides the eye.
mb-3, p-3) is too tight for page-level sections — use mb-5 or
custom --app-section-gap valuesFollow Bootstrap's breakpoints but design for the actual use case:
| Application Type | Primary Target | Design Priority | |---|---|---| | Admin dashboard | Desktop (1200px+) | Dense layout, sidebar nav | | Documentation site | Tablet+ (768px+) | Readable width (max 75ch), collapsible nav | | Public portal | Mobile-first (375px+) | Touch targets, stacked layout |
| Anti-Pattern | Fix |
|---|---|
| Default Bootstrap with no customization | Define custom palette, typography, and at least one signature element |
| System font stack with no font declaration | Choose a font pairing and declare it in CSS custom properties |
| Every section is a uniform card grid | Vary layout: hero sections, split layouts, full-width banners, list views |
| No loading state — blank page then sudden content | Add loading skeletons or staggered fade-in reveals |
| All colors from Bootstrap defaults (btn-primary, bg-light) | Define --app-* custom properties for project-specific palette |
| Animations disabled for prefers-reduced-motion not handled | Always include the reduced-motion media query |
| More than 3 font families loaded | Reduce to 2 (display + body) plus optional monospace |
| linear timing on UI transitions | Use ease or ease-out for natural-feeling motion |
| Everything center-aligned on the page | Choose a dominant alignment; use asymmetry intentionally |
| No visual hierarchy — all text same size/weight | Use font size + weight + color to create 3+ hierarchy levels |
When the frontend-orchestrator requires a design brief (feature, module, or greenfield scope), populate this template in the design artifact:
## Visual Design Brief
**Aesthetic direction:** {one-phrase descriptor from the vocabulary table}
**Signature element:** {the one visual detail that makes this memorable}
### Typography
- Display font: {name} — {weights to load}
- Body font: {name} — {weights to load}
- Source: Google Fonts | system | self-hosted
### Color Palette
- Primary: {hex} — {where it appears}
- Accent: {hex} — {where it appears}
- Surface: {light hex} / {dark hex}
- Text: {primary hex} / {secondary hex} / {muted hex}
### Motion
- Page transitions: {yes/no — approach if yes}
- Loading states: {skeleton / spinner / fade-in}
- Hover effects: {lift / glow / underline / none}
### Layout
- Primary target viewport: {mobile / tablet / desktop}
- Navigation: {sidebar / topbar / combined}
- Content max-width: {e.g., 1200px / 75ch / full-width}
Before: Default Bootstrap, system fonts, btn-primary blue, uniform card grid,
no loading states. Looks like every other Bootstrap admin template.
After: Plus Jakarta Sans headings + Source Sans 3 body, custom indigo primary
(#4f46e5) with amber accent (#f59e0b), staggered card load animation, loading
skeletons on data fetches, sidebar with subtle gradient background, one asymmetric
hero stat bar at the top breaking the card grid pattern.
Design brief declared: "Clean professional with warm accent." Signature element: "Amber-highlighted stat bar with staggered number count-up."
Before: Default Bootstrap docs template, gray sidebar, Inter font, no visual identity.
After: Aesthetic direction "Bold editorial." Playfair Display headings, DM Sans body.
Dark sidebar (#0f172a) contrasting with warm white content (#fffbf5). Code blocks
with a subtle gradient border. Page sections fade in on scroll. Signature element:
"Serif headings with a thin amber underline on hover."
Scenario: Internal operations dashboard used by 5 people in a warehouse. They need density, speed, and clarity — not personality.
Direction: "Data-dense utilitarian." System font stack (intentional choice, not default), compact spacing, borders instead of shadows, minimal color (monochrome with red for alerts), zero animation. This IS the design — restraint is intentional.
Design brief declared: "Utilitarian — maximum data density, zero decoration." Signature element: "None — density is the design."
web-ui-styling — Technical framework selection (Bootstrap vs alternatives), CSS architecture, isolation, and variable conventions. Use that skill for which framework; use this skill for how it should lookgen-blazor-demo-site — Scaffolds a complete Blazor demo site; this skill's design brief feeds the demo site's visual approachstreaming-ai-responses — ChatGPT-style progressive display; complements motion guidance for AI-integrated UIstools
Use when cross-cutting concerns (logging, metrics, validation, authorization) are tangled into command handlers or service methods, when building database command pipelines with reorderable concerns, or when HTTP client pipelines or message handlers need composable, independently-replaceable processing stages. Covers ICommandInterceptor interface, InterceptorPipeline with reverse-chain construction, zero-cost Empty sentinel to skip overhead when no interceptors are registered, and ConfigureAwait(false) discipline for library code. Domain: Architecture, Cross-Cutting Concerns. Level: Intermediate. Tags: interceptor, pipeline, middleware, decorator, cross-cutting-concerns.
development
Use when writing integration tests for Razor Pages, MVC, or Minimal API applications to validate routing, middleware, page rendering, and HTTP behavior without a browser or live server, or when adding fast smoke tests to a CI pipeline. Covers WebApplicationFactory<Program> setup with public partial class Program, in-memory test server, AngleSharp HTML parsing, CSS selector assertions, redirect and status code testing, and a shared static fixture pattern for minimal per-test startup overhead. Domain: Testing, ASP.NET Core. Level: Intermediate. Tags: integration-testing, webapplicationfactory, razor-pages, anglesharp, http-testing.
development
Use when designing indexes for new tables, diagnosing slow queries that are not using indexes efficiently, reviewing index fragmentation and maintenance, or when the current indexing strategy results in key lookups, table scans, or missing index warnings. Covers clustered index key selection (narrow, unique, ever-increasing), non-clustered index design for query patterns, covering indexes with INCLUDE columns, filtered indexes for subset queries, composite index column ordering, DMV-based monitoring for missing and unused indexes, and rebuild vs reorganize maintenance thresholds. Domain: Database, Performance. Level: Intermediate. Tags: index, sql-server, covering-index, filtered-index, performance, dmv, maintenance.
development
Use when building a searchable in-memory catalog or registry for documentation sites, admin panels, or type/API browsers where you need keyword matching, fuzzy search, and ranked results without an external search engine or database. Covers RegistryService with weighted scoring across name, description, keywords, and method names; Levenshtein fuzzy matching; synonym expansion; category and subcategory filtering; and singleton DI registration for datasets of hundreds to low thousands of items. Domain: Search, Data Access Patterns. Level: Intermediate. Tags: search, registry, fuzzy-matching, in-memory, catalog, filtering.