Portfolio Website

2026 – Present

Next.js 16TypeScriptReact 19Tailwind CSS v4Framer Motionnext-intlnext-themesMDXDockerTraefik
GitHub
Portfolio Website

Overview

This is the site you're looking at right now. I built it from scratch because I wanted full control over design, content, and hosting rather than working within the constraints of a template or a managed platform. It has four visual themes, bilingual content, responsive layouts, and runs on my own server.

Design system

The theming works in two independent layers:

Dark/light mode is handled by next-themes and stored as a class on <html>. Every design theme has both a dark and a light variant.

Design themes are four visual palettes, each with its own typography, colors, and hero animation:

  • Atelier (default) — editorial luxury. Gold rules, Cormorant Garamond headings, lots of whitespace. Draws from high-end print design.
  • Iris — dreamscape. Glowing concentric rings, gradient name treatment, soft constellation dots. Quieter and more ambient.
  • Manifesto — acid editorial. High contrast, compressed type, a marquee strip, outlined vs. filled name contrast. Loud on purpose.
  • Cobalt — mission control. Monospace font, dot-grid background, scanlines, a HUD metrics panel. Meant to feel like a developer dashboard.

An inline script in <head> reads the stored theme from localStorage before React hydrates, so there's no flash of wrong colors on load. All component styling goes through CSS custom properties that each theme overrides, which means components don't need conditional theme logic.

Themes can be changed easily on the fly with the theme switcher: Theme Switcher

Hero animations

Each theme has its own hero section with a distinct entrance animation: sliding gold rules and a name reveal for Atelier, ring pulses and a star constellation fade for Iris, clip-path name reveal with a marquee strip for Manifesto, typewriter cursor with a scanline overlay for Cobalt. Switching themes remounts the section via a key prop, so the animation replays cleanly.

0:00 / 0:00
All four hero themes in action

Architecture

The site runs on Next.js 16 App Router with all routes under [locale]/. Invalid locales return a 404.

Content lives in content/{locale}/ and comes in two forms:

  • JSON for structured data (experience, education, certificates, publications, about)
  • MDX for project pages like this one, parsed with gray-matter and rendered via next-mdx-remote

Project slugs come from the English filenames. If no German MDX file exists for a project, the loader falls back to the English version, so only content that actually differs needs a separate file.

Sections like Certificates and Publications hide themselves (page and navbar) when all their entries are marked hidden. Section numbers use Roman numerals and recompute dynamically.

Internationalization

UI strings (messages/{locale}.json) go through next-intl. Content (bios, job descriptions, project writeups) lives in locale-specific JSON and MDX files. The two can be translated independently. Currently supported: English and German.

Typography

Six font families load at build time via next/font/google. Each theme switches --font-sans and --font-display to pick its own typefaces:

  • Atelier: Jost + Cormorant Garamond
  • Cobalt: Plus Jakarta Sans
  • Iris: Sora
  • Manifesto: DM Mono + Fraunces

JetBrains Mono is the monospace font across all themes.

Mobile

Every section adapts to small screens. Hero layouts reflow to a single column, stat panels stack, project cards use fluid grids, and typography scales with clamp(). The navbar collapses to a mobile menu with appropriately sized touch targets.

Deployment

The portfolio is self-hosted on my home server as a Docker container. Traefik handles TLS and routing. Pushing to main triggers a GitHub Actions workflow that builds the image, pushes it to GHCR, and deploys it to the server automatically.

Stack

LayerTechnology
FrameworkNext.js 16 (App Router)
LanguageTypeScript
UIReact 19
StylingTailwind CSS v4
AnimationsFramer Motion
ContentMDX + gray-matter + next-mdx-remote
i18nnext-intl
Themingnext-themes + custom CSS variable system
Fontsnext/font/google (6 families)
DeploymentDocker + Traefik (self-hosted)