srbhr

design-principles

@srbhr/design-principles
srbhr
25,501
4606 forks
Updated 1/7/2026
View on GitHub

Swiss International Style design system for Resume Matcher. Use this skill when building UI components, modifying styles, or creating new pages. Every frontend change MUST follow these rules.

Installation

$skills install @srbhr/design-principles
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Path.claude/skills/design-principles/skill.md
Branchmain
Scoped Name@srbhr/design-principles

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: design-principles description: Swiss International Style design system for Resume Matcher. Use this skill when building UI components, modifying styles, or creating new pages. Every frontend change MUST follow these rules.

Resume Matcher Design System: Swiss International Style

This project follows a strict Swiss International Style (International Typographic Style) aesthetic. It emphasizes cleanliness, readability, objectivity, and strong grid structures. The design is "Brutalist-Lite" — raw, functional, but polished.


Core Philosophy

  • Form follows function: content is primary
  • Grid Systems: mathematically consistent layouts
  • High Contrast: Sharp borders, distinct colors
  • Typography: Hierarchy through size, weight, and font family mixing (Serif + Mono)

Color Palette

The palette is minimal, relying on high contrast between ink and paper.

Color NameHex / TailwindUsage
Canvas Cream#F0F0E8Main application background. Simulates paper.
Panel Grey#E5E5E0Secondary backgrounds, workspaces, unselected areas.
Ink Black#000000Borders, primary text, grid lines, hard shadows.
Hyper Blue#1D4ED8 (blue-700)Primary actions, links, active states, accents.
Paper White#FFFFFFInput fields, active cards, resume pages.
Signal Green#15803D (green-700)Download actions, live status indicators.
Alert Orange#F97316 (orange-500)Reset actions, highlights.
Alert Red#DC2626 (red-600)Destructive actions, delete confirmations.
Steel Grey#4B5563 (gray-600)Secondary labels like Live Preview text.
Muted Texttext-gray-500Metadata, placeholders, descriptions.

Typography

We mix three typefaces to create a distinctive technical document feel.

Headings: Serif

Used for major page titles and section headers. Represents authority and tradition.

  • Class: font-serif
  • Style: Bold, often Uppercase
  • Tracking: Tight (tracking-tight) for large headers

Body: Sans-Serif

Used for long-form text, descriptions, and general readability.

  • Class: font-sans
  • Style: Regular weight, clean

Metadata / Technical: Monospace

Used for labels, dates, locations, small details, and "system" text.

  • Class: font-mono
  • Style: Uppercase, tracking wide (tracking-wider), small size (text-xs or text-sm)
  • Prefixes: Often stylized with // (e.g., // SELECT MODULE)

Components & Shapes

Borders & Radius

  • Borders: Always solid, 1px Black (border border-black)
  • Radius: Zero. rounded-none. No soft curves.

Shadows (Hard Drops)

Shadows are solid blocks of color/alpha, not diffuse blurs. They mimic paper cutout layers.

Primary Swiss-Style Shadows (solid black):

  • Resume/Large Content: shadow-[8px_8px_0px_0px_#000000]
  • Builder Preview: shadow-[6px_6px_0px_0px_#000000]
  • Buttons (Hover): shadow-[2px_2px_0px_0px_#000000]

Secondary Shadows (semi-transparent):

  • Page Containers: shadow-[8px_8px_0px_0px_rgba(0,0,0,0.1)]
  • Cards / Forms: shadow-[4px_4px_0px_0px_rgba(0,0,0,0.1)]

Important: Resume components should NOT have internal shadows. The parent container provides the Swiss-style shadow.


Buttons

Swiss-style buttons use hard shadows, square corners, and clear semantic colors.

Base Styling (All Buttons)

rounded-none                           /* Square corners - Brutalist */
border border-black                    /* High contrast border */
shadow-[2px_2px_0px_0px_#000000]       /* Hard shadow (no blur) */
font-mono uppercase tracking-wide      /* Technical typography */
transition-all duration-150 ease-out   /* Smooth interactions */

Hover/Active Behavior

hover:translate-y-[1px] hover:translate-x-[1px] hover:shadow-none  /* Press effect */
active:translate-y-[2px] active:translate-x-[2px]                   /* Deep press */

Button Variants

VariantColorHexUse Case
defaultHyper Blue#1D4ED8Primary actions (Save, Submit)
destructiveAlert Red#DC2626Dangerous actions (Delete)
successSignal Green#15803DPositive actions (Download)
warningAlert Orange#F97316Caution actions (Reset, Undo)
outlineTransparentBlack borderSecondary actions (Cancel)
secondaryPanel Grey#E5E5E0Tertiary actions
ghostTransparentNo border/shadowIcon buttons
linkHyper Blue text#1D4ED8Inline links

Button Sizes

SizeHeightPaddingUse Case
smh-8px-4 py-1Compact UI, toolbars
defaulth-10px-6 py-2Standard buttons
lgh-12px-8 py-3Hero CTAs
iconh-10 w-10p-0Icon-only buttons

Usage Examples

<Button variant="default">Save Changes</Button>
<Button variant="destructive">Delete Resume</Button>
<Button variant="success">Download PDF</Button>
<Button variant="warning">Reset Form</Button>
<Button variant="outline">Cancel</Button>
<Button variant="ghost" size="icon"><Settings /></Button>

DO's and DON'Ts

DO:

  • Use semantic variants (destructive for delete, success for download)
  • Use outline for cancel/back actions paired with primary buttons
  • Use ghost for icon-only buttons in toolbars

DON'T:

  • Add rounded-* classes (always square)
  • Use custom colors inline (use variants)
  • Use soft/blurred shadows

Status Indicators

Small colored squares for at-a-glance system state information.

Base Styling

w-3 h-3                          /* 12x12px square */
/* No rounded corners - sharp edges */

Indicator Variants

ColorTailwind ClassUse Case
Hyper Bluebg-blue-700Active sections, editor mode
Signal Greenbg-green-700Ready state, success
Alert Amberbg-amber-500Warning, setup required
Alert Redbg-red-600Error, offline
Steel Greybg-gray-500Inactive, disabled

Usage Pattern

<div className="flex items-center gap-2 border-b-2 border-black pb-2">
  <div className="w-3 h-3 bg-blue-700"></div>
  <h2 className="font-mono text-lg font-bold uppercase tracking-wider">
    Editor Panel
  </h2>
</div>

Inputs & Forms

  • Background: White or Transparent
  • Borders: Black, square (rounded-none)
  • Focus: Sharp blue ring or border color change. No soft glow.
  • Labels: Uppercase Monospace (text-xs font-mono uppercase tracking-wider)

Collapsible Panels

<div className="border border-black bg-white">
  {/* Header - Always Visible */}
  <button className="w-full flex items-center justify-between p-3 hover:bg-gray-50">
    <div className="flex items-center gap-2">
      <div className="w-2 h-2 bg-blue-700"></div>
      <span className="font-mono text-xs font-bold uppercase tracking-wider">
        Panel Title
      </span>
    </div>
    <ChevronUp />
  </button>

  {/* Expandable Content */}
  <div className="border-t border-black p-4 space-y-6">
    {/* Controls */}
  </div>
</div>

Template Thumbnails

<button className={`flex flex-col items-center p-2 border-2 transition-all ${
  isActive
    ? 'border-blue-700 bg-blue-50 shadow-[2px_2px_0px_0px_#1D4ED8]'
    : 'border-black bg-white hover:bg-gray-50 hover:shadow-[1px_1px_0px_0px_#000]'
}`}>
  <div className="w-12 h-16 mb-1.5">{/* Thumbnail */}</div>
  <span className={`font-mono text-[9px] uppercase tracking-wider font-bold ${
    isActive ? 'text-blue-700' : 'text-gray-700'
  }`}>
    Template Name
  </span>
</button>

Toggle Selectors

Binary choices (A4 / US Letter):

<button className={`flex-1 px-3 py-2 border-2 font-mono text-xs transition-all ${
  isSelected
    ? 'border-blue-700 bg-blue-50 text-blue-700 shadow-[2px_2px_0px_0px_#1D4ED8]'
    : 'border-black bg-white text-gray-700 hover:bg-gray-50'
}`}>
  <div className="font-bold">A4</div>
  <div className="text-[9px] opacity-70">210 × 297 mm</div>
</button>

Spacing Level Selectors

Button groups for levels 1-5:

<div className="flex gap-1">
  {[1, 2, 3, 4, 5].map((level) => (
    <button className={`w-6 h-6 font-mono text-xs border transition-all ${
      isSelected
        ? 'bg-blue-700 text-white border-blue-700 shadow-[1px_1px_0px_0px_#000]'
        : 'bg-white text-gray-700 border-gray-300 hover:border-black'
    }`}>
      {level}
    </button>
  ))}
</div>

Layout Patterns

The "Canvas" Container

<div className="w-full max-w-7xl border border-black bg-[#F0F0E8] shadow-[8px_8px_0px_0px_rgba(0,0,0,0.1)]">
  {/* Content */}
</div>

Full-Height Editor Layout

<div className="h-screen w-full bg-[#F0F0E8] flex justify-center items-center p-4 md:p-8">
  <div className="w-full h-full max-w-[95%] xl:max-w-[1800px] border border-black flex flex-col">
    {/* Header */}
    <div className="border-b border-black p-6 md:p-8">...</div>

    {/* Content grid */}
    <div className="grid grid-cols-1 lg:grid-cols-2 bg-black gap-[1px] flex-1 min-h-0">
      <div className="bg-[#F0F0E8] p-6 md:p-8 overflow-y-auto">...</div>
      <div className="bg-[#E5E5E0] p-6 md:p-8 overflow-y-auto">...</div>
    </div>

    {/* Footer */}
    <div className="p-4 border-t border-black">...</div>
  </div>
</div>

Grid Lines Background

style={{
  backgroundImage: 'linear-gradient(rgba(29, 78, 216, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(29, 78, 216, 0.1) 1px, transparent 1px)',
  backgroundSize: '40px 40px',
}}

Paginated Preview System

Page Dimensions

Page SizeWidthHeight
A4210mm297mm
US Letter215.9mm279.4mm

PageContainer Component

<PageContainer
  pageSize="A4"
  margins={{ top: 10, bottom: 10, left: 10, right: 10 }}
  pageNumber={1}
  totalPages={2}
  scale={0.6}
  showMarginGuides={false}
>
  <Resume ... />
</PageContainer>

Page Break Rules

  1. Sections CAN span pages - Experience, Projects flow naturally
  2. Individual items stay together - Job entries don't split
  3. 50% minimum fill - Pages at least half full before moving items
  4. Section titles protected - No orphans at page bottom

CSS for Page Breaks

.resume-body .resume-item {
  break-inside: avoid;
  page-break-inside: avoid;
}

.resume-body .resume-section-title {
  break-after: avoid;
  page-break-after: avoid;
}

Quick Reference

Required Classes

ElementClasses
Headersfont-serif font-bold tracking-tight
Body textfont-sans
Labels/Metafont-mono text-xs uppercase tracking-wider
Bordersborder border-black rounded-none
Primary BGbg-[#F0F0E8]
Panel BGbg-[#E5E5E0]
Hard shadowshadow-[Xpx_Xpx_0px_0px_#000000]

Semantic Colors

PurposeColorClass
Primary actionHyper Bluebg-blue-700 text-white
SuccessSignal Greenbg-green-700 text-white
WarningAlert Orangebg-orange-500 text-white
DestructiveAlert Redbg-red-600 text-white
SecondaryPanel Greybg-[#E5E5E0] text-black

Retro Terminal Elements (UI Chrome Only)

These elements add personality to the app interface. DO NOT use these on resume builder, resume viewer, or any resume-related components.

Where to Use

  • Dashboard
  • Settings page
  • Navigation/sidebar
  • Empty states
  • Loading states
  • Error pages
  • Modals (non-resume)

Where NOT to Use

  • Resume Builder form
  • Resume Preview/Viewer
  • PDF output
  • Print layouts
  • Any component that displays resume content

Bracket Syntax for Labels

Use brackets for status indicators and system labels in UI chrome:

// Status indicators
<span className="font-mono text-xs uppercase tracking-wider">
  [ STATUS: READY ]
</span>

<span className="font-mono text-xs uppercase tracking-wider">
  [ LOADING... ]
</span>

// Section labels
<span className="font-mono text-xs uppercase tracking-wider text-gray-500">
  [ SETTINGS ]
</span>

// Navigation items (optional)
<span className="font-mono text-sm">
  [ 01. DASHBOARD ]
</span>

Bracket Variants:

ContextFormatExample
Status ready[ STATUS: X ][ STATUS: READY ]
Status warning[ STATUS: X ][ STATUS: SETUP REQUIRED ]
Section label[ LABEL ][ SETTINGS ]
Action hint[ ACTION ][ DRAG TO REORDER ]
System message> MESSAGE> NO ITEMS FOUND

ASCII Empty States

Use ASCII art for empty states to add character:

// Empty resume list
<div className="text-center py-12 font-mono text-gray-500">
  <pre className="text-xs leading-relaxed">
{`    ┌─────────────────┐
    │                 │
    │   NO RESUMES    │
    │      YET        │
    │                 │
    └─────────────────┘`}
  </pre>
  <p className="mt-4 text-sm">[ CREATE YOUR FIRST RESUME ]</p>
</div>

// Empty job list
<div className="text-center py-12 font-mono text-gray-500">
  <pre className="text-xs leading-relaxed">
{`    ╔═══════════════════╗
    ║                   ║
    ║   NO JOBS SAVED   ║
    ║                   ║
    ╚═══════════════════╝`}
  </pre>
  <p className="mt-4 text-sm">[ ADD A JOB DESCRIPTION ]</p>
</div>

// Generic empty state
<div className="text-center py-8 font-mono text-gray-400">
  <span className="text-2xl">[ EMPTY ]</span>
  <p className="mt-2 text-xs">> NO DATA AVAILABLE</p>
</div>

ASCII Box Characters:

Single line: ┌ ┐ └ ┘ │ ─ ├ ┤ ┬ ┴ ┼
Double line: ╔ ╗ ╚ ╝ ║ ═ ╠ ╣ ╦ ╩ ╬
Mixed:       ╒ ╕ ╘ ╛ ╞ ╡ ╤ ╧ ╪

Loading States

Keep spinners for async operations - users need visual feedback that something is happening. Combine spinners with bracket-style labels:

// Standard loading - spinner + bracket label
<div className="flex items-center gap-2">
  <Loader2 className="w-4 h-4 animate-spin text-blue-700" />
  <span className="font-mono text-xs uppercase tracking-wider">
    [ PROCESSING ]
  </span>
</div>

// LLM/AI operations - spinner with context
<div className="flex items-center gap-2">
  <Loader2 className="w-4 h-4 animate-spin text-blue-700" />
  <span className="font-mono text-xs uppercase tracking-wider">
    [ GENERATING CONTENT ]
  </span>
</div>

// Saving state
<div className="flex items-center gap-2">
  <Loader2 className="w-3 h-3 animate-spin text-gray-500" />
  <span className="font-mono text-xs text-gray-500">
    [ SAVING... ]
  </span>
</div>

Completion states - clear transition from loading to done:

// Success completion
<div className="flex items-center gap-2">
  <Check className="w-4 h-4 text-green-700" />
  <span className="font-mono text-xs uppercase tracking-wider text-green-700">
    [ COMPLETE ]
  </span>
</div>

// With detail
<div className="flex items-center gap-2">
  <Check className="w-4 h-4 text-green-700" />
  <span className="font-mono text-xs text-green-700">
    [ SAVED SUCCESSFULLY ]
  </span>
</div>

Progress bars - only use when you have REAL progress data:

// Deterministic progress (file upload, multi-step process)
<div className="space-y-1">
  <div className="flex justify-between font-mono text-xs">
    <span>[ UPLOADING ]</span>
    <span>{progress}%</span>
  </div>
  <div className="h-2 bg-gray-200 border border-black">
    <div
      className="h-full bg-blue-700 transition-all"
      style={{ width: `${progress}%` }}
    />
  </div>
</div>

DO NOT use ASCII progress bars like [████░░░░] - they look cool but provide no real information for indeterminate operations.


Error States

// Error message with brackets
<div className="border border-red-600 bg-red-50 p-4">
  <p className="font-mono text-sm text-red-700">
    [ ERROR: CONNECTION FAILED ]
  </p>
  <p className="font-mono text-xs text-red-600 mt-1">
    > Unable to reach server. Check your connection.
  </p>
</div>

// 404 style
<div className="text-center py-12 font-mono">
  <pre className="text-6xl font-bold text-gray-300">404</pre>
  <p className="text-gray-500 mt-4">[ PAGE NOT FOUND ]</p>
  <p className="text-xs text-gray-400 mt-2">> The requested resource does not exist</p>
</div>

Anti-Patterns (NEVER DO)

  • NO rounded corners - always rounded-none
  • NO soft/blurred shadows - always hard offset shadows
  • NO gradient backgrounds - flat colors only
  • NO custom colors - use the defined palette
  • NO spring/bouncy animations
  • NO thick borders (2px+) for decoration
  • NO retro elements on resume components - keep resume areas clean

Summary: Make it look like a high-end architectural blueprint or a technical manual. Precise, bordered, and grid-aligned. Add retro terminal personality to UI chrome, but keep resume areas professional and clean.