Interface: App UI
Rule
Quality bar: Build app interfaces worthy of Linear, Vercel, or Notion. Functional, clear, refined — and distinctly this product, not a template.
Intent First
Before any visual decisions, answer explicitly:
- Who is this human? Specific role and context, not "users"
- What must they accomplish? Specific verb — create, monitor, configure, analyze
- What should this feel like? Concrete descriptors, not clichés
If your answer is "it's common" or "it's clean" — you haven't chosen. You've defaulted.
Product Domain Exploration
Every product exists in a world. Discover it before designing:
- Domain vocabulary: 5+ concepts, metaphors, or terms from the product's actual world (not its features)
- Color world: Colors that naturally exist in the physical version of this product space
- Signature element: One visual, structural, or interaction element unique to THIS product
- Defaults to avoid: Name 3 obvious choices for this interface type — to consciously avoid them
Test: Remove the product name from the design. Can someone identify what it's for?
The Swap Test
For every visual choice, ask: if I substituted the alternative, would the design's meaning change?
- Same font as every other SaaS dashboard → defaulted
- Same sidebar layout as the last 5 projects → defaulted
- Same gray palette with blue accent → defaulted
If the swap wouldn't matter, the choice isn't a choice.
Depth Strategy
Pick ONE approach and commit across the entire app:
| Strategy | Feel | When to use |
|---|---|---|
| Borders only | Technical, precise | Developer tools, data-heavy apps |
| Subtle shadows | Approachable, soft | General SaaS, collaborative tools |
| Layered shadows | Premium, dimensional | Design tools, luxury products |
- NEVERMix strategies in the same interface
- NEVERDramatic elevation jumps between adjacent surfaces
Subtle Layering
Surfaces should be barely different but still distinguishable. Study Vercel, Supabase, Linear for whisper-quiet hierarchy.
- SHOULDSquint test — blur your eyes and still perceive hierarchy without harshness
- SHOULDBackground differences of 2-4% lightness between layers
- NEVERPure white cards on colored backgrounds (dead contrast)
- NEVERHarsh borders as the only separator
Navigation
Navigation teaches users how to think about the product space. It IS the product, not around it.
- MUSTCurrent location always visible
- MUSTConsistent placement across all screens
- SHOULDBreadcrumbs for 3+ level depth
- SHOULDNavigation structure mirrors the mental model of the domain, not the database schema
- NEVERNavigation that requires scrolling to find
Information Density
- MUSTMatch density to context (sparse for onboarding, dense for dashboards)
- SHOULDConsistent density within a screen
- NEVERMix sparse and dense patterns in the same view without clear hierarchy
States
- MUSTDesign empty states with helpful CTAs — these are onboarding moments
- MUSTLoading states — skeleton preferred over spinners for layouts
- MUSTError states with recovery actions (not just "something went wrong")
- SHOULDPartial/permission states if applicable
- SHOULDEmpty states that teach the product, not just fill space
Data Display
- MUSTTables sortable by at least one column
- SHOULDPagination or virtualization for 50+ items
- SHOULDFilters visible, not buried in menus
- SHOULDNumbers with context — what's good, what's bad, what changed
- NEVERTruncate data without tooltip or expansion
- NEVERDisplay raw data without considering what action the user takes with it
Interactive Patterns
- MUSTHover states on all clickable elements
- MUSTLoading indicator for async actions
- SHOULDOptimistic updates where safe
- SHOULDUndo for destructive actions instead of confirmation dialogs
- SHOULDKeyboard shortcuts for frequent actions
Typography
- SHOULDBody text 14-16px (not smaller for prolonged use)
- SHOULDLabels 12-13px, medium weight or caps for differentiation
- SHOULDMonospace for data that needs alignment (IDs, timestamps, code)
- SHOULDTabular numerals for columns of numbers
- NEVERDisplay-size fonts in app chrome (save for marketing)
Color
- MUSTSemantic colors for status (success, warning, error, info)
- SHOULDMuted palette — color draws attention, so use it sparingly
- SHOULDAccent color for primary actions only
- SHOULDSaturated greys (warm or cool) rather than dead neutral
- NEVERDecorative color that doesn't convey meaning
- NEVERColor as the only indicator of status (accessibility)
Token Naming
CSS variable names are design decisions. They carry meaning:
/* Evokes a world */
--ink: #1a1a1a;
--surface: #fafafa;
--accent: #e11d48;
/* Evokes a template */
--gray-700: #374151;
--white: #ffffff;
--blue-500: #3b82f6;
- SHOULDName tokens by role, not by value
- SHOULDNames that a designer would understand without a color picker
The 8-Hour Test
Could someone use this interface for 8 hours without visual fatigue? If not:
- Reduce contrast between background layers
- Soften borders
- Check for competing visual weight
- Ensure the eye has clear resting places