Booting portfolio system
20%
Skip to content
← Return to work

project

BOSA

A typed, content-driven portfolio built with Next.js, MDX, and a progressively enhanced Three.js visual system.

01
software
02
Designer and Developer
03
Next.js / React / TypeScript / MDX / Three.js / CSS Modules

BOSA is this portfolio, but I think of it less as a single page and more as a small publishing system with an atmosphere attached to it. The public result is a dark, terminal-like site with project cards, writing, repository links, and a persistent visual layer behind the content. The more useful part, though, is the way the site is put together: typed content, static detail routes, narrow client boundaries, and a WebGL artifact that can be turned down or replaced without taking the rest of the page with it.

I wanted the portfolio to feel deliberate without becoming a demo reel that gets in the way of reading. That is a harder balance than it sounds, because the same things that make a portfolio memorable can also make it fragile: smooth scrolling, preference panels, animated reveals, MDX pages, persistent backdrops, and reduced-motion behavior all want to touch the same browser state. The main idea was to keep those pieces useful and isolated, so the content stays the center of the site instead of becoming a passenger inside the effect.

The idea

The project started from a simple problem: I did not want every portfolio entry to be a custom page, and I also did not want the site to flatten everything into one reusable card. Some work only needs metadata, a repository link, and a short description. Other work deserves a longer prose page where the decisions, tradeoffs, and outcome can breathe a little. BOSA is built around that split.

Each entry has typed metadata for the parts that the rest of the site needs to understand: title, slug, category, date, excerpt, stack, role, highlights, and related fields. The optional MDX body is separate. That means the card grid, archive views, detail routes, and public content APIs can all read the same source of truth, while the long-form project pages only exist where they are actually useful.

That sounds like a small thing, but it changes the shape of the project. The portfolio is no longer a collection of hand-maintained pages that happen to look similar. It is closer to a repository of content that the interface can map into different views. For me, that is the important part. The design can change, the detail pages can become richer, and the homepage can stay compact without duplicating copy across the app.

Content and routing

BOSA uses the Next.js App Router with static detail routes for portfolio entries. Most of the site can stay server-rendered, which keeps the base content straightforward and avoids turning the whole page into a client application just because a few areas need browser APIs. The client components are kept narrow: motion, preference handling, scroll behavior, and the persistent visual system live where they are needed instead of leaking into every piece of content.

The content layer is also intentionally boring in a good way. Project and repository data live in typed modules, and the public facade exposes them through functions that the app can consume without caring about the file layout. Card mappers turn that content into UI-friendly shapes. The detail route can check whether an entry has an MDX body and render a richer page when it does, while simpler entries still work as proper portfolio records.

Where this shines is consistency. If a project title or excerpt changes, it does not need to be fixed in three places. If a card becomes clickable, it is using the same slug and metadata that the detail route already expects. If the archive needs a different grouping later, it can use the content model instead of scraping presentation markup. It is not a complicated architecture, but it is a useful one because it keeps the writing, the routes, and the interface pointing at the same thing.

There is also a practical maintenance benefit. A portfolio tends to rot when updating it feels like reopening a one-off design project every time. By making entries content-first, adding work becomes closer to filling in a structured record and writing the optional page when the project deserves it. That keeps the site easier to extend without making every future update feel like a redesign.

Motion without making it fragile

The visual side of BOSA is where the project could have easily become messy. The site has a persistent shell, smooth scrolling, animated section behavior, configuration controls, and a Three.js backdrop. Those pieces can make the site feel more alive, but they also create a lot of opportunities for things to fight each other: focus movement, anchor navigation, reduced motion, document visibility, canvas sizing, and user preferences all have to be respected.

The approach was to treat motion as progressive enhancement. The content should still be reachable if the immersive layer is reduced, disabled, or replaced by a static fallback. The Three.js artifact is there for atmosphere, not for core navigation. It can adapt quality, settle into a reduced-motion path, and avoid blocking the semantic content above it. I don't consider that optional polish. For this kind of site, it is what makes the difference between a visual identity and a gimmick.

There are two presentation modes because not every visitor wants the same amount of atmosphere. The regular presentation keeps the site calmer and more direct. The immersive presentation gives the backdrop more presence and lets the page feel more like an environment. Reduced motion forces the regular path, which is the right tradeoff. A preference control is only useful if it does not override the user's system-level comfort settings.

That being said, this is also the area with the most constraints. WebGL, smooth scrolling, and animation libraries all have their own opinions about timing and layout. BOSA keeps those concerns behind shared components and configuration boundaries as much as possible, because a single clever animation is not worth making the rest of the site harder to reason about. The goal was not to remove complexity completely. It was to put it in places where it could be understood.

The artifact

The central visual object is a WebGL artifact, a cube-like form that sits behind the portfolio as a persistent signal rather than a separate scene. It is dark, industrial, and a little editorial: dithered texture, fixed signal colors, and a shape that can feel technical without pretending to be a full sci-fi world. I have to say, I like this kind of backdrop most when it suggests a system instead of explaining one.

The artifact also gives the site a useful rhythm. Static content pages can feel flat when every section is just another card or text block, but too much animation can make the reading experience worse. Here the backdrop carries some of the identity, while the foreground stays mostly concerned with hierarchy, spacing, links, and readable prose. The result is a good enough vessel for a portfolio: distinctive, but not so loud that every project has to compete with it.

The important part is that the artifact is not treated as the portfolio's source of truth. The real work is still in the entries, repositories, metadata, and prose. The visual layer supports that work by giving the site a recognizable mood and by making navigation between sections feel connected. If it fails or steps down for performance reasons, the content model still holds up.

Takeaway

BOSA ended up being less about making a flashy portfolio and more about building a portfolio that can keep growing. The useful lesson was that content structure and visual ambition do not have to pull in opposite directions, but they need boundaries. Typed metadata, optional MDX bodies, static routes, and repository-backed APIs give the site a stable base. Narrow client components, reduced-motion support, fallbacks, and adaptive quality tiers let the atmospheric layer exist without owning the whole application.

I am pretty happy with that balance. There are still moving parts, and that is worth mentioning. A site with WebGL, smooth scrolling, preferences, and long-form content will always need more care than a plain static archive. But the pieces have a clear job now, and that makes the complexity feel manageable. For me, that is the real value of the project: it gives the portfolio a strong identity while keeping the writing and the work easy to maintain.