Portfolio Web Application

This portfolio is a personal web application designed to present my projects through a minimal layout, controlled interaction, and multiple API integrations, within a structured and maintainable setup.

Next.jsReactTypeScriptTailwind CSSFramer Motion

Overall structure

The site is organized around a small number of clearly defined sections: Home, Work, About, and Bookmarks.

Home is intentionally compact and works as a one-screen overview built around a Bento-style grid. Work hosts all projects. About is a narrative page about me and is meant to become a dedicated entry point for my CV and a more complete presentation. Bookmarks is currently inactive and planned as a curated space for references and topics I follow.

Each section is isolated both conceptually and technically. Routing and layout boundaries are treated as real constraints rather than conveniences, to avoid the site gradually turning into a tightly coupled structure as it grows.

Technical foundation

The site is built with Next.js 16 using the App Router and a server-first approach. Pages and layouts are React Server Components by default. Client components are only introduced when interaction, browser APIs, or local state make them unavoidable. This keeps rendering predictable and limits unnecessary client-side JavaScript.

Routing relies on route groups and isolated segments so shared shell concerns don't leak into feature logic. Project pages are statically generated with generateStaticParams(), giving stable performance while keeping the content workflow simple.

At the code level, isolation is enforced rather than implied. Import boundaries are checked via ESLint to prevent cross-segment dependencies, and I avoid barrel exports to keep dependency graphs explicit and tree-shaking effective. In a few places, small pieces of logic are intentionally duplicated instead of shared, purely to preserve bundle boundaries and avoid accidental coupling. That tradeoff is deliberate.

Bento grid and interactions

The Home page is composed as a Bento grid rendered mostly on the server. Interactive cards are isolated into client components and lazy-loaded when needed. Any heavier widget is paired with a fixed-size skeleton so the layout remains stable while data or libraries load.

This keeps the page usable immediately, even when some cards rely on external APIs or large client-side libraries. The grid itself stays simple; complexity is pushed into clearly scoped widgets with well-defined responsibilities.

Motion is present but controlled. Animations are used for feedback and transitions, not decoration, and are kept lightweight and respectful of reduced-motion preferences.

Location Map 3D

The location map is a client-only component built with Mapbox GL in a fixed 3D configuration. It uses a predefined pitch and bearing with controlled rotation that stops on user interaction. Map tiles are served through a server-side MapTiler proxy to avoid exposing API keys. The component is lazy-loaded with a fixed-height skeleton and rendered without SSR, as it depends on browser APIs.

Monkeytype API Typing Metrics

This card fetches typing performance data from the Monkeytype API via a server route and normalizes it by time modes (15, 30, 60, and 120 seconds). The data is reduced to core metrics (WPM, accuracy, consistency) before being rendered. Client-side logic handles timed updates with proper effect cleanup, and fallback values ensure the UI remains stable if the API fails.

AI SDK Prompt

The AI prompt is a lightweight, text-first interactive component built around a reusable prompt-input system. It uses Vercel AI SDK types to keep the interface structured without implementing a full chat flow. Interactions are minimal and focused, with limited motion used only to guide attention.

Live data integrations

Several cards on the Home grid rely on real external data.

GitHub activity is fetched through a server API route wrapping the GitHub GraphQL API. When that fails, the system falls back to parsing the public contributions SVG. The goal is simple: the card should never break because of an API constraint.

The Spotify card retrieves the currently playing track via an OAuth-based server route, with a fallback to recently played tracks when nothing is active.

Typing stats are pulled from the Monkeytype API and transformed into a small, readable summary across multiple time modes. On the client side, the component manages timed transitions and cleans up its effects carefully to avoid stale intervals during navigation.

The location card combines a server-side MapTiler proxy (to avoid exposing keys) with a client-only Mapbox GL setup. It uses a controlled 3D view with rotation and interaction handling that pauses automation as soon as the user takes control.

Project content system

Projects are written in MDX with YAML frontmatter. Content is fully separated from presentation, which lets me add or update projects without touching layout code. Metadata is parsed with gray-matter, and pages are rendered through an RSC-compatible MDX pipeline.

Beyond basic rendering, the pipeline normalizes content (image paths, metadata, structure) so projects behave consistently at build time. A single template controls layout, typography, navigation, and media, keeping all case studies aligned while leaving the writing itself flexible.

Design system and UI

The UI is built on top of Tailwind CSS v4, with a lightweight design-token layer implemented through CSS variables. Core values such as typography, spacing, radii, and colors are centralized to keep the interface consistent while allowing individual components to stay simple and focused. The goal isn't to build an exhaustive design system, but a stable foundation that can evolve without friction.

Interactive components use Radix primitives and CVA to keep behavior accessible and styling explicit. MDX content relies on a dedicated typography setup focused on readability.

Styling choices aim for a premium, modern interface: restrained color usage, clear hierarchy, and careful spacing rather than visual noise. Variable Geist fonts are served in WOFF2 with font-display: swap, keeping rendering fast and stable.

Why this project

This project started as a technical and design challenge. The goal was to combine several technologies including ones I wanted to explore more deeply, and make them work together in a coherent, production-ready web application.

I took inspiration from modern, premium portfolio websites to design an interactive home grid with a minimalist visual language. The intent was not to replicate a specific style, but to understand how contemporary layouts, motion, and spacing can be combined without overwhelming the interface. Every visual decision was made with the constraint that the UI should stay readable, restrained, and functional.

On the technical side, the focus was on building a solid foundation rather than pushing complexity. I wanted to control the project end to end: architecture, data flow, performance tradeoffs, and UI behavior. This meant choosing tools and libraries I found relevant, integrating them carefully, and making sure they worked well together without over-engineering the system.

Its designed as a mid-term project, with a solid foundation that can evolve gradually over time.

If you want to know more about this project, feel free to reach out.

© 2026 Matt Claustre. All rights reserved.