Design System

The visual and interaction foundation of fred6.nl, tokens, components, and the decisions behind them.

Clients see how decisions get made, not just what they look like. AI agents get a structured map of every token and component in the system.

Tokens: 47 Components: 4 Updated: 2026

Decisions

Every design choice is a trade-off. These are the six that define fred6.nl's system character, the reasoning behind each one matters as much as the choice itself.

  1. 01

    Amber accent only, no blue tones

    Contemporary, warm, unexpected in tech. Blue is the default palette of every SaaS product; amber creates immediate distinctiveness. A single accent hue enforces discipline, there is no second colour to reach for.

  2. 02

    Light-first with manual dark toggle

    Portfolio work shows best on light. Dark mode is a user preference, not a default. The toggle is persistent via localStorage, but the initial experience is the light mode, the context in which the visual work was created.

  3. 03

    Tags are non-interactive labels

    At 5–10 projects, filtering adds complexity without user value. The cognitive cost of a filter UI, learning the interaction, resetting state, recovering from empty results, outweighs any benefit at this scale. If the portfolio grows to 20+ projects, a dedicated filter row above the grid is the right pattern. Until then, scrolling is the interface.

  4. 04

    Geist typeface

    Tech-forward, free, purpose-built for screens by Vercel. It reads with authority at large display sizes and stays legible at caption scale. Self-hosted as woff2, no Google Fonts dependency, no external DNS lookup on load.

  5. 05

    CSS custom properties for all tokens

    No JS token files, no build-time transforms, no runtime overhead. Tokens live in tokens.css as native CSS custom properties, consumed directly in component <style> blocks. The browser handles dark mode via data-theme attribute overrides on the <html> element.

  6. 06

    cursor: default on non-interactive pill elements

    An explicit honesty signal. A pointer cursor on a non-clickable element is a broken promise, it invites a click that goes nowhere. Tags declare their non-interactive nature at the cursor level, before the user commits to an interaction that will not happen.

Color

The palette is deliberately restrained. A single warm accent, amber, sits against a cool-grey neutral scale. No blue tones appear anywhere in the system; this is intentional (see Decisions). Semantic tokens alias the raw scale so components never reach for primitive values directly.

Neutral scale

--color-neutral-0 hsl(0 0% 100%)
--color-neutral-50 hsl(220 14% 96%)
--color-neutral-100 hsl(220 13% 91%)
--color-neutral-200 hsl(220 11% 80%)
--color-neutral-400 hsl(220 9% 55%)
--color-neutral-600 hsl(220 10% 35%)
--color-neutral-800 hsl(220 12% 18%)
--color-neutral-900 hsl(220 14% 10%)
--color-neutral-950 hsl(220 16% 6%)

Accent, amber Brand accent

The sole chromatic hue in the system. No blue tones are used, amber reads as warm, contemporary, and unexpected in a tech context.

--color-accent hsl(45 48% 37%)
--color-accent-light hsl(45 48% 50%)
--color-accent-subtle hsl(45 48% 37% / 0.15)
--color-accent-fg hsl(45 48% 36%) 4.67:1 on white

Semantic tokens

Components consume semantic tokens, never raw primitives. These aliases flip automatically between light and dark mode via data-theme.

--color-surface Page background neutral-0 / neutral-950
--color-surface-raised Cards, code chips, inputs neutral-50 / neutral-900
--color-surface-glass Frosted nav, glass panels white/0.7 · dark/0.75
--color-border Dividers, input outlines neutral-100 / neutral-800
--color-text Body copy, headings neutral-900 / neutral-50
--color-text-secondary Captions, nav links (idle) neutral-400 (both modes)

Typography

Geist, purpose-built for screens by Vercel, released as open source. All sizes are fluid clamp() values that scale smoothly between mobile and desktop viewports without breakpoint jumps.

Type scale

--text-xs clamp(0.75rem, 0.7rem + 0.25vw, 0.8125rem) The quick brown fox
--text-sm clamp(0.875rem, 0.8rem + 0.35vw, 0.9375rem) The quick brown fox
--text-base clamp(1rem, 0.95rem + 0.25vw, 1.0625rem) The quick brown fox
--text-lg clamp(1.125rem, 1rem + 0.65vw, 1.25rem) The quick brown fox
--text-xl clamp(1.25rem, 1.1rem + 0.85vw, 1.5rem) The quick brown fox
--text-2xl clamp(1.5rem, 1.25rem + 1.3vw, 2rem) The quick brown fox
--text-3xl clamp(2rem, 1.5rem + 2.5vw, 3rem) The quick fox
--text-display clamp(3rem, 2rem + 5vw, 5rem) The quick fox

Font weights

Aa --weight-regular 400
Aa --weight-medium 500
Aa --weight-semibold 600
Aa --weight-bold 700

Line heights

--leading-tight · 1.1

Design systems are living artifacts. They breathe with the product they serve.

--leading-snug · 1.3

Design systems are living artifacts. They breathe with the product they serve.

--leading-normal · 1.5

Design systems are living artifacts. They breathe with the product they serve.

--leading-relaxed · 1.7

Design systems are living artifacts. They breathe with the product they serve.

Spacing

A fixed 4px base unit scale. The visual ruler below renders each token as a bar whose width matches the actual token value, making the relationships between steps immediately legible.

--space-1 0.25rem
--space-2 0.5rem
--space-3 0.75rem
--space-4 1rem
--space-5 1.25rem
--space-6 1.5rem
--space-8 2rem
--space-10 2.5rem
--space-12 3rem
--space-16 4rem
--space-20 5rem
--space-24 6rem
--space-32 8rem

Motion

Three intentional easing curves and three duration tokens. Hover each demo box to see the easing in action, the box slides 60px right and returns. All animation in the system is CSS-only, no JavaScript motion libraries.

Easing curves

--ease-out-expo cubic-bezier(0.16, 1, 0.3, 1) UI transitions, nav, buttons
--ease-spring cubic-bezier(0.34, 1.56, 0.64, 1) Playful moments, icons, accents

Duration tokens

--duration-fast 120ms, hover states, focus rings
--duration-base 220ms, most UI transitions
--duration-slow 400ms, page-level animations

Composition

Tokens don't live in isolation. This is what the system looks like when everything comes together, real components, real tokens, no mocks.

Hero — gradient · display type · CTAs

Designing platforms.

Building design systems that bring structure and clarity to complex environments.

Project card — surface · border · type · tags
Philips · 2024

Web Platform Design

Bringing structure and consistency to a fragmented digital ecosystem.

Design System UI
Dark mode — same tokens, dark surface
Philips · 2024

Web Platform Design

Bringing structure and consistency to a fragmented digital ecosystem.

Design System UI

Button

Three variants covering the full interaction spectrum. Primary draws attention with the amber accent fill. Ghost holds space without competing. Text is for in-line or low-emphasis navigation cues.

Component API

Prop Type Default Values
label string required Any string
variant string 'primary' 'primary' | 'ghost' | 'text'
href string Renders as <a> when present
type string 'button' 'button' | 'submit' | 'reset'

Light context

Dark context

Tag

Non-interactive label pills used to classify project work. Tags are purely presentational, they communicate metadata, not actions.

Accessibility decisions

  • cursor: default, explicit honesty signal. The element is not interactive; it must not look like it is.
  • role="list" wrapper, when multiple tags are rendered together, the parent should carry role="list" so screen readers announce the count.
  • Contrast ratio 4.67:1, --color-accent-fg (hsl 45 48% 36%) against white. Passes WCAG AA (4.5:1). Dark mode uses hsl(45 55% 68%) for sufficient contrast on dark surfaces.
  • user-select: none, prevents accidental text selection on non-text content.

Component API

Prop Type Default Values
label string required Any string
size string 'md' 'md' | 'sm'

Light context

md
    Design Systems UI Design Figma
sm
    Design Systems UI Design Figma

Dark context

md
    Design Systems UI Design Figma
sm
    Design Systems UI Design Figma

FrostedPanel

A backdrop-blur glass surface. Used sparingly, the nav gains this treatment after 16px of scroll, and intentional "glass moment" layouts can use it for visual depth. Overusing frosted glass flattens the effect; restraint is the rule.

Component API

Prop Type Default Values
class string Forwarded to wrapper div for sizing/spacing

Content is passed via <slot />. The component owns only the glass surface, sizing, padding, and layout are always the consumer's responsibility.

In use

Glass surface

Backdrop blur of 12px (--glass-blur). Background opacity adapts via --glass-bg, 72% white on light, 72% dark on dark. Border uses --glass-border.

backdrop-filter light + dark

Seen enough to want to talk?

Get in touch