Back to portfolio

Design System

The system behind this portfolio

This page walks through the actual tokens, type scale, and components running the site you're on right now - not a separate mockup. Every color, spacing value, button, and section pattern below is imported straight from the production code (down to the case-study block components), so what you see here is exactly what's shipping. It's meant to be enough on its own to build another page in this system.

Foundations

Layout & spacing

Every page sits in a max-w-shell (1280px) container with px-[6vw] side margins, so gutters scale with the viewport instead of snapping between fixed breakpoints. Vertical rhythm between major sections is py-16 md:py-24. Corners use one radius token, rounded-ds (2px) - sharp enough to read as structural, not soft/decorative. Borders are almost always border-paper/10 to border-paper/18, never solid paper.

Spacing scale · base 4px (Tailwind default)

1
2
3
4
6
8
10
12
16
20
24

Radius · --radius-ds: 2px

One radius everywhere - buttons, cards, images, badges. No larger "soft" radius exists in this system.

Foundations

Accessible color palette

A fixed dark shell, no light mode, built around one paper-on-ink text pairing and three accent colors. I check every accent's contrast ratio against the ink background against WCAG 2.1 before I let it carry text. If a color only passes at large sizes, it's restricted to labels and headlines, never body copy.

#0B0B0F
Ink--ink

Base surface

The fixed dark shell every page sits on. Never used as a text color on light surfaces.

#F7F7F2
Paper--paper

Primary text

18.28:1 on ink · AAA

Body copy, headlines, and primary UI text on the ink surface.

#FF2E83
Pink--pink

Primary accent

5.59:1 on ink · AA

Primary buttons, links, and the loudest accent. Safe for normal-size text on ink.

#7B61FF
Violet--violet

Secondary accent

4.67:1 on ink · AA

Numbered labels and secondary emphasis. It clears AA for normal text on ink, but only just, so I keep it to short labels, not paragraphs.

#C6FF00
Lime--lime

Interactive / focus

16.56:1 on ink · AAA

Hover states, focus rings, and active nav indicators. High contrast, used sparingly so it stays meaningful.

#F3D6FF
Lilac--lilac

Soft accent

14.85:1 on ink · AAA

A rare decorative fill, like a resume hover state. I don't use it for body text.

Foundations

Typography

Archivo carries every weight of the interface, from body copy to the heaviest display headlines. Caveat, a handwritten accent face, only shows up for a single emphasized word here and there. I never let it carry a full sentence.

H1 · font-display · 900 · clamp(36px, 6.5vw, 64px)

Designing systems people trust

H2 · font-display · 900 · 30 to 48px

Products, not just screens

H3 · font-display · 900 · 20 to 24px

A section heading, like inside a case study

Body · font-sans (Archivo) · 400 · 16px

Body copy sits at a comfortable reading measure, medium contrast against ink at paper/70, and generous line height, so a long case-study passage stays easy to scan.

Label / eyebrow · font-mono · 10px · uppercase · tracked

Section label example

Accent · font-accent (Caveat) · single word only

Designing systems people actually trust.

Components

Buttons

Four variants, two sizes. primary is the only filled button in the system - use it once per view for the one action that matters most.

variant="primary"

variant="outline"

variant="arrow" · text link with a hover-expanding gap

variant="destructive" · reserved for delete/remove actions (admin tool)

disabled state

Components

Badges & tags

Three small pill patterns cover every "label on top of content" need in the system.

Kind badge · case study header

Shipped

Skill tag · About section

Interaction Design

Project tag chip · overlaid on an image

AI Concept

Components

Numbered section header

Every top-level homepage section (Work, Approach, About, Contact) opens with this exact pattern: a violet index number, a lime mono eyebrow, then the display headline. Copy this block verbatim and renumber it for a new section.

05New Section

Headline goes here

Components

Cards

One bordered card shape, two ways to fill it: an icon + title + body (Approach, case-study principle cards), or plain content. Both use rounded-ds border border-paper/12 p-6.

Icon card title

Icon in a bordered box, then a medium-weight title, then paper/60 body copy. Used for principles, pillars, and "what shipped" summaries.

Plain card title

Same shell without the icon slot - for content-only cards where an icon would just be decoration.

Case study components

The full case-study block vocabulary

These are the actual components (components/case-study-template.tsx) that every case study on this site is built from - imported here directly, not recreated, so there's zero drift from production. Compose a new case study (or any long-form page) by stringing these together.

type: "text"

A text block

The default building block - a heading (optional) plus one or more paragraphs. Use it for narrative sections: the challenge, a reframe, a reflection.

type: "list"

A bulleted list

Pink-dot bullets, used for scannable enumerations:

  • First point
  • Second point
  • Third point

type: "quote"

A large pink-bordered pull-quote - only ever real copy pulled verbatim from research, testing, or product text, never invented for effect.

Attribution or context line

type: "stat"

Headline numbers

Big Archivo-900 figures for scannable stats, instead of burying a number in a paragraph.

86%

expected a behavior the product didn't support

+45%

task success after the fix shipped

2.3x

faster completion time

type: "tradeoffs" · Negotiations & trade-offs

A real constraint, decision, and resolution

Surfaces the negotiation behind a decision - never a hypothetical.

Constraint

What forced the decision - a deadline, a technical limit, a research finding.

Decision

What was chosen because of that constraint.

Resolution

How it was validated or why it held up.

type: "tiers" · MVP / ideal scoping

Tiered solution options

Single-patty-to-3x3 style scoping, so a reviewer can see the range considered.

Single

MVP

The smallest version that solves the core problem.

Shipped for MVP

Double-double

Next iteration

Adds the highest-value follow-up, still scoped tightly.

3x3

Long-term vision

The full-featured version, for later.

type: "process" · numbered steps

A numbered process

  1. Step one

    What happens first, and why it comes first.

  2. Step two

    What gets decided or discovered at this stage.

  3. Step three

    How the previous step changes what happens next.

type: "cards" · icon grid

Principles or takeaways

First principle

One sentence explaining why it matters.

Second principle

One sentence explaining why it matters.

Third principle

One sentence explaining why it matters.

type: "metrics" · results table

A/B or usability results

Row-level results, with a highlight color for the standout win.

TaskSuccessTimeEase
Task A+45%2.3x faster2.2x more direct
Task B22% fasterFewer misclicks

An optional footnote for context that doesn't fit in the table.

type: "compare" · before/after

Before and after

Two images side by side, each with its own caption - the clearest way to show what changed.

Before state placeholder

Before

After state placeholder

After

type: "split" · alternating text + image

Text next to its supporting visual

Pairs an insight directly with a screenshot instead of always stacking full-width blocks. Pass flip: true to mirror which side the image sits on.

Placeholder

Image caption

type: "placeholder" · honest "coming soon"

Visual coming soon

For a visual that doesn't exist yet - never a broken image.

Foundations

Motion & accessibility

  • Every animation (orbs, blink, view transitions) is wrapped in a prefers-reduced-motion: reduce media query in globals.css that forces durations to ~0 - motion is never load-bearing for understanding content.
  • Focus states use focus-visible:outline focus-visible:outline-lime - keyboard focus is always visibly distinct from hover.
  • Text selection is styled (::selection) to lime-on-ink instead of the browser default, so it stays legible against the dark shell.
  • Every accent color is contrast-checked against ink (see the palette above) before it's allowed to carry text, not just used decoratively.

Process

How this gets built

This site isn't hand-coded line by line, and it isn't a no-code builder either. Every page here, including this one, is built through direct AI pairing - I decide what should change and why, an agent edits the actual files in this repo, and nothing ships without a check.

The loop

  1. Direct it in conversation

    I describe what should change and why - a content fix, a new feature, a bug - the same way I'd brief a teammate, not a ticket queue.

  2. The agent edits the real files

    Claude Code / GitHub Copilot edits this repo directly - the components, tokens, and case-study data you're looking at right now, not a separate mockup.

  3. Verify before it ships

    Every change gets a TypeScript check and a real browser pass - visually and functionally - before it's trusted, not just "looks right in chat."

  4. Ship

    Committed to GitHub with a real message, auto-deployed by Vercel - usually live within minutes of the conversation that started it.

Swappable

VS Code + GitHub Copilot Chat

Claude Sonnet coding sessions

Vercel hosting

Durable

Design tokens in globals.css

The case-study data model (lib/case-studies.ts)

This page - documents the system so any future session can pick it back up

What that actually produces

One real design system

Every token and component on this page is the same code running the live site, not redrawn for show.

Checked against real audiences

Résumé and case-study copy get reviewed against ATS parsing, recruiter scan time, and hiring-manager depth before anything ships.

Version-controlled, not vibes

Every change is a real git commit with a message - reversible and deployed through the same pipeline as a production app.

Foundations

Logo (extra credit)

A simple wordmark, built entirely from the type system above. No separate illustration tool, so it scales and recolors exactly like the rest of the interface.

SF
Shawn Farnum.
SF

In production

High-fidelity design

I didn't build a separate high-fidelity mockup for this one. The system is implemented directly on the live, shipped site, so the homepage link below is the high-fidelity design. It's already built and deployed with the exact tokens and type scale documented on this page.

For the showcased project, I'm linking the SoundCloud UX Research case study. It's the most complete one right now, with final copy, layout, and visuals all done. The Cotality/OneHome capstone is still in progress, and it'll take over this slot once the final report lands.