Files
Resume-Matcher/docs/style-guide.md
srbhr b833bf3db7 feat: enhance documentation and remove deprecated files
- Added a comprehensive Table of Contents to AGENTS.md for improved navigation.
- Expanded documentation with new backend and frontend guides, detailing architecture, API contracts, and workflows.
- Introduced new documents for backend architecture and requirements, outlining system design and API specifications.
- Removed outdated Makefile and setup.sh scripts to streamline project setup.
- Deleted yarn.lock to eliminate unnecessary dependency management files.
- Updated AGENTS.md to reflect changes in documentation structure and links.
2025-12-29 16:27:39 +05:30

19 KiB
Raw Blame History

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.

1. Core Philosophy

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

2. Color Palette

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

Color Name Hex / Tailwind Usage
Canvas Cream #F0F0E8 Main application background. Simulates paper.
Panel Grey #E5E5E0 Secondary backgrounds, workspaces, unselected areas.
Ink Black #000000 Borders, primary text, grid lines, hard shadows.
Hyper Blue #1D4ED8 (blue-700) Primary actions, links, active states, accents.
Paper White #FFFFFF Input 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 Text text-gray-500 Metadata, placeholders, descriptions.

3. 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).

4. 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] - Used for resume containers in viewer/builder
  • Builder Preview: shadow-[6px_6px_0px_0px_#000000] - Slightly smaller for nested contexts
  • Buttons (Hover): shadow-[2px_2px_0px_0px_#000000] - Small offset for interactive elements

Secondary Shadows (semi-transparent):

  • Page Containers: shadow-[8px_8px_0px_0px_rgba(0,0,0,0.1)] - Subtle background containers
  • Cards / Forms: shadow-[4px_4px_0px_0px_rgba(0,0,0,0.1)] - Light shadow for cards

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

Buttons

Swiss-style buttons use hard shadows, square corners, and clear semantic colors. The "press" effect is achieved by translating the button and removing the shadow on hover.

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

Variant Color Hex Use Case Example
default Hyper Blue #1D4ED8 (blue-700) Primary actions Save, Submit, Create
destructive Alert Red #DC2626 (red-600) Dangerous actions Delete, Remove
success Signal Green #15803D (green-700) Positive actions Download, Confirm
warning Alert Orange #F97316 (orange-500) Caution actions Reset, Clear, Undo
outline Transparent Black border Secondary actions Cancel, Back
secondary Panel Grey #E5E5E0 Tertiary actions Toolbar buttons
ghost Transparent No border/shadow Subtle actions Icon buttons
link Hyper Blue text #1D4ED8 Inline links Text navigation

Button Sizes

Size Height Padding Use Case
sm h-8 px-4 py-1 Compact UI, toolbars
default h-10 px-6 py-2 Standard buttons
lg h-12 px-8 py-3 Hero CTAs, emphasis
icon h-10 w-10 p-0 Icon-only buttons

Usage Examples

// Primary action (save, submit)
<Button variant="default">Save Changes</Button>

// Destructive action (delete)
<Button variant="destructive">Delete Resume</Button>

// Success action (download)
<Button variant="success">Download PDF</Button>

// Warning action (reset)
<Button variant="warning">Reset Form</Button>

// Secondary action (cancel, back)
<Button variant="outline">Cancel</Button>

// Tertiary action
<Button variant="secondary">More Options</Button>

// Icon button
<Button variant="ghost" size="icon"><Settings /></Button>

// Text link
<Button variant="link">Learn More</Button>

// Disabled state (automatic)
<Button disabled>Processing...</Button>

Disabled State

All buttons automatically receive:

  • opacity-50 - Reduced visibility
  • pointer-events-none - No interactions
  • Maintains variant color for context

Focus State

Sharp blue ring (not soft glow):

focus-visible:ring-2 focus-visible:ring-blue-700 focus-visible:ring-offset-2

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
  • Combine with Lucide icons for clarity

DON'T:

  • Add rounded-* classes (always square)
  • Use custom colors inline (use variants)
  • Mix shadow styles (keep consistent 2px offset)
  • Use soft/blurred shadows

Status Indicators

Swiss-style status indicators are small colored squares that provide at-a-glance system state information. They follow the brutalist aesthetic with solid colors and no rounded corners.

Base Styling

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

Indicator Variants

Color Tailwind Class Hex Use Case
Hyper Blue bg-blue-700 #1D4ED8 Active sections, editor mode
Signal Green bg-green-700 #15803D Ready state, healthy status, success
Alert Amber bg-amber-500 #F59E0B Warning state, setup required
Alert Red bg-red-600 #DC2626 Error state, offline, failed
Steel Grey bg-gray-500 #6B7280 Inactive, disabled, neutral

Usage Patterns

Section Headers - Indicate the current mode/panel:

<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>

Status Footers - Show system readiness with loading/offline states:

<div className="flex items-center gap-2">
  {isLoading ? (
    <>
      <Loader2 className="w-3 h-3 animate-spin text-gray-500" />
      <span className="font-mono text-xs text-gray-500">CHECKING...</span>
    </>
  ) : status ? (
    <>
      <div className={`w-3 h-3 ${status === 'ready' ? 'bg-green-700' : 'bg-amber-500'}`}></div>
      <span className={`font-mono text-xs font-bold ${status === 'ready' ? 'text-green-700' : 'text-amber-600'}`}>
        {status === 'ready' ? 'STATUS: READY' : 'STATUS: SETUP REQUIRED'}
      </span>
    </>
  ) : (
    <span className="font-mono text-xs text-gray-500">STATUS: OFFLINE</span>
  )}
</div>

Health Cards - Pair with icons for detailed status:

<div className="flex items-center gap-2">
  {isHealthy ? (
    <CheckCircle2 className="w-5 h-5 text-green-600" />
  ) : (
    <XCircle className="w-5 h-5 text-red-500" />
  )}
  <span className="font-mono text-sm font-bold">
    {isHealthy ? 'HEALTHY' : 'OFFLINE'}
  </span>
</div>

Last Fetched Indicator - Shows when cached data was refreshed:

<span className="font-mono text-xs text-gray-400 flex items-center gap-1">
  <Clock className="w-3 h-3" />
  {formatLastFetched()} {/* "Just now", "5m ago", "1h ago" */}
</span>

Text Color Pairing

When indicators accompany text labels, match the text color for consistency:

Indicator Text Class Use
bg-green-700 text-green-700 Ready, healthy, success
bg-amber-500 text-amber-600 Warning, setup required
bg-red-600 text-red-600 Error, offline, failed
bg-blue-700 text-blue-700 Active, selected, info

DO's and DON'Ts

DO:

  • Use consistent 12x12px (w-3 h-3) squares
  • Pair indicator color with matching text color
  • Use uppercase monospace font for status labels
  • Add font-bold to status text for emphasis

DON'T:

  • Add rounded corners (rounded-*)
  • Use gradients or multiple colors
  • Make indicators larger than the text they accompany
  • Use different sizes for the same type of indicator

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

Swiss-style collapsible sections used for settings and controls (e.g., Template & Formatting panel in Builder).

Structure

<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 /> {/* or ChevronDown when collapsed */}
  </button>

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

Template Thumbnails

Visual representation of resume templates. Used in the Template & Formatting panel.

<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 preview */}</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

Used for binary choices like Page Size (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 selecting spacing/sizing 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>

Margin Sliders

Range inputs styled for Swiss aesthetic.

/* Slider track */
h-1 bg-gray-200 rounded-none appearance-none

/* Slider thumb */
[&::-webkit-slider-thumb]:w-3
[&::-webkit-slider-thumb]:h-3
[&::-webkit-slider-thumb]:bg-blue-700
[&::-webkit-slider-thumb]:border-none

5. Layout Patterns

The "Canvas" Container

Pages are often wrapped in a centered container that floats on the #F0F0E8 background.

<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

Used for pages like the Resume Builder where equal padding on all sides is required.

{/* Outer wrapper - fixed viewport height with equal padding */}
<div className="h-screen w-full bg-[#F0F0E8] flex justify-center items-center p-4 md:p-8">
  {/* Main container - fills available space */}
  <div className="w-full h-full max-w-[95%] xl:max-w-[1800px] border border-black flex flex-col">
    {/* Header - fixed height */}
    <div className="border-b border-black p-6 md:p-8">...</div>

    {/* Content grid - fills remaining space */}
    <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 - fixed height */}
    <div className="p-4 border-t border-black">...</div>
  </div>
</div>

Key classes:

  • h-screen + items-center - Centers content vertically within viewport
  • h-full on inner container - Fills available space after padding
  • flex-1 min-h-0 on content grid - Allows grid to fill remaining height and enable scrolling
  • overflow-y-auto on panels - Enables independent scrolling

Grid Lines

Backgrounds often feature a graph-paper pattern to reinforce the engineering/technical theme.

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',
}}

Headers with "Tabs"

Section headers often use a "tab" or "status block" aesthetic on the left or right.

  • Solid block of color (Blue or Black).
  • Monospace text describing the current mode (e.g., LIVE PREVIEW, EDITOR PANEL).

6. Paginated Preview System

The Resume Builder features a WYSIWYG paginated preview that shows exactly what the PDF will look like.

Architecture

components/preview/
├── page-container.tsx      # Single page wrapper with margin guides
├── paginated-preview.tsx   # Main preview with controls
├── use-pagination.ts       # Page break calculation hook
└── index.ts                # Barrel exports

lib/constants/
└── page-dimensions.ts      # Page size constants and utilities

Page Dimensions

Page Size Width Height Use Case
A4 210mm 297mm International standard
US Letter 215.9mm 279.4mm North American standard

PageContainer Component

Renders a single page at exact dimensions with optional margin guides.

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

Visual Elements:

  • White background with 2px black border
  • Swiss-style shadow: shadow-[6px_6px_0px_0px_#000000]
  • Optional dashed blue margin guides (toggleable)
  • Page number indicator: Page X of Y (bottom-right, monospace)

Preview Controls

Located in a toolbar above the preview area:

Control Icon Function
Zoom Out ZoomOut Decrease zoom (min 40%)
Zoom Level Text Shows current zoom %
Zoom In ZoomIn Increase zoom (max 150%)
Margins Toggle Eye/EyeOff Show/hide margin guides
Page Count FileText Shows total pages
<div className="flex items-center gap-2">
  <Button variant="ghost" size="icon"><ZoomOut /></Button>
  <span className="font-mono text-xs w-12 text-center">60%</span>
  <Button variant="ghost" size="icon"><ZoomIn /></Button>
  <div className="w-px h-5 bg-gray-400 mx-2" />
  <Button variant={showMargins ? 'secondary' : 'ghost'} size="sm">
    <Eye /> Margins
  </Button>
</div>

Page Break Indicators

Visual separator between pages in the preview:

<div className="flex items-center gap-2 py-2">
  <div className="h-px w-8 bg-gray-400" />
  <span className="font-mono text-[10px] text-gray-500 uppercase tracking-wider">
    Page Break
  </span>
  <div className="h-px w-8 bg-gray-400" />
</div>

Pagination Rules

The preview automatically calculates page breaks with these rules:

  1. Sections CAN span pages - Experience, Projects, etc. flow naturally
  2. Individual items stay together - Single job entries, project entries don't split
  3. 50% minimum fill - Pages must be at least half full before moving an item
  4. Section titles protected - Titles won't be orphaned at page bottom

CSS Classes for Page Breaks:

/* Individual items stay together */
.resume-body .resume-item {
  break-inside: avoid;
  page-break-inside: avoid;
}

/* Section titles stay with content */
.resume-body .resume-section-title {
  break-after: avoid;
  page-break-after: avoid;
}

/* Explicit no-break marker */
.resume-body [data-no-break] {
  break-inside: avoid;
}

Margin Guides

When enabled, shows the printable content area:

<div
  className="absolute pointer-events-none z-10"
  style={{
    top: marginTopPx,
    left: marginLeftPx,
    width: contentWidth,
    height: contentHeight,
    border: '1px dashed rgba(29, 78, 216, 0.5)',
  }}
>
  {/* Corner markers */}
  <div className="absolute -top-1 -left-1 w-2 h-2 border-t border-l border-blue-500" />
  ...
</div>

Preview Background

The scrollable preview area uses a subtle grid pattern:

<div
  className="flex-1 overflow-auto bg-[#D5D5D0] p-6"
  style={{
    backgroundImage: 'linear-gradient(rgba(0,0,0,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(0,0,0,0.03) 1px, transparent 1px)',
    backgroundSize: '20px 20px',
  }}
>

Summary: Make it look like a high-end architectural blueprint or a technical manual. Precise, bordered, and grid-aligned.