My portfolio at yousefx00.online started with a constraint I set for myself: no UI frameworks, no component library — just Next.js, CSS Modules, and a strict design system. This post is the breakdown of how it's built and why.
One accent color, used like punctuation
The entire visual identity is a near-black canvas (#05090C) with a single lime accent (#A6DA04). Everything else is grayscale. That restraint is what makes it feel intentional rather than decorated.
The tokens live in :root as CSS custom properties, so every component reads from the same palette:
:root {
--bg-primary: #05090C;
--bg-surface: #0D1216;
--accent: #A6DA04;
--text-secondary: #A7ABAD;
--border-subtle: #1B2226;
--font-heading: 'Sora', sans-serif;
--font-body: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}If I ever redesign, I change twelve lines — not two hundred components.
Three fonts, each with one job
- Sora for headings — geometric, techy, holds up at display sizes.
- Inter for body text — the safest readable choice on screens.
- JetBrains Mono reserved for labels, code, and the little
// eyebrowdetails that give the page its engineering flavor.
All three load in a single Google Fonts request, which keeps DNS lookups and connection overhead to one round trip.
The mono-label trick
My favorite detail is the eyebrow label above section titles:
.eyebrow::before {
content: '';
width: 20px;
height: 2px;
background: var(--accent);
border-radius: 2px;
}A tiny accent dash plus uppercase mono text reads like a terminal prompt. It costs nothing, scales to any section, and instantly signals "developer made this."
Motion that respects the user
Animations are limited to entrance fades, a pulsing status dot, and hover lifts — all under 700ms, all driven by a shared easing curve:
--transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);No parallax, no scroll-jacking. Motion should confirm an interaction happened, not perform for its own sake.
Performance choices
- Static generation everywhere. Every page prerenders; there's no client data fetching at all.
- CSS Modules over utility classes. Zero runtime cost, scoped by default, and the bundle only ships styles actually imported.
next/imagewith explicit sizes for the few raster assets, so layout never shifts.- One fixed navbar, blurred only after scroll, so the initial paint stays cheap.
The result is a site that scores green across Core Web Vitals without a single optimization library.
What I'd do differently
Three things, honestly: ship a real blog from day one (you're reading it), add Open Graph images earlier than feels necessary, and write the sitemap.ts before launch instead of after submitting to Search Console and wondering why coverage reports look sad.
Design systems aren't about limiting creativity — they're about spending your creativity where users can feel it.
