Moaaz.

project

How I Built My Portfolio

A walk-through of the stack behind moaaz.be, Next.js 16, Tailwind v4, MDX content, Vercel hosting, and GitHub for version control, and the small decisions that shaped it.

Back to blog
30 May 20264 min read
Next.js

Building this site was one of those side-of-the-desk projects that I kept coming back to between internship shifts. It started life as a plain resume page, and over time turned into a proper e-portfolio: a place that tells the story of what I work on instead of just listing it.

This post is a short tour of what's under the hood.

What I wanted from it

A few things were non-negotiable:

The stack

Framework

Next.js 16 on the App Router, with React 19 and TypeScript. Every route is pre-rendered at build time, so the site is essentially a folder of HTML and assets by the time it ships.

Styling

Tailwind CSS v4, paired with CSS custom properties for the light/dark theme switch. No design system library, just utilities and a small set of reusable components (cards, pills, section labels, page shell).

A tiny bit of motion: Motion (formerly Framer Motion) drives the floating nav and scroll fades.

Content

This is where the architecture actually lives.

Images

I shoot most event photos on a phone, which means HEIC and DNG files end up in the repo before they ever see the web. sharp handles all of that: it decodes the raw, rotates by EXIF orientation, resizes to a sensible max width, and saves a mozjpeg-encoded JPEG into public/. The result is the original quality without the original file size.

Icons & UI bits

lucide-react is the only icon set. clsx for conditional class strings. That's about it, the rest is hand-rolled components.

Hosting & version control

This pairing means the workflow is: write a post in MDX, commit, push. The site rebuilds itself.

How the routes are organised

/                       one-pager: intro, featured projects, latest posts, experience
/about                  bio, skills, languages
/portfolio              every post in one place
/projects               all project case studies
/projects/[slug]        a single project + linked posts
/blog                   all blog posts
/blog/[slug]            a single post with gallery and related posts
/experience             full work + education timeline
/skills                 grouped skills + languages
/resume                 CV PDF view + download
/contact                email, LinkedIn, GitHub
/colophon               the longer-form version of this post

Anchor navigation stays on the home page; route navigation is in the sticky top bar.

Decisions I'd make the same way again

What's next

A few things I haven't built yet but want to:

If you're curious about how a specific page works, the source is open at github.com/TwoEazy, or check the colophon for a more reference-style breakdown of the stack.

Tags

Next.jsReactTypeScriptTailwindMDXVercelGitHubportfolio