
A pragmatic rebuild of my portfolio — built for recruiters, respected by engineers, and maintainable for a solo dev. This post explains the problems I saw, the golden technical decisions I made, constraints I worked under, measurable results, and lessons learned.

Most personal portfolios I reviewed suffer from three recurring issues.

The long-term benefits and developer experience makes it a clear winner for a project / product that I would intend to maintain for a while

If you’ve been working with Next.js, you’ve probably heard of two main approaches: the Pages Router and the newer App Router.
/app) fetch, revalidate).layout.tsx, loading.tsx, error.tsx).getServerSideProps)./pages) getStaticProps, getServerSideProps._app.tsx, _document.tsx).While Pages Router has been around for a while and is super reliable.
The App Router is designed to handle things like reusable layouts and deeply nested pages. Which helps with folder organization and separation of concern which we will touch on later.

| Use Top-Level Folder when… | Use Co-location when… |
|---|---|
| Code is reused across many routes/features | Code is used by one route or feature |
| Component is part of a design system (Button, Modal) | Component is tightly coupled to a page |
| Logic is generic (auth, fetchers, formatters) | Logic is domain-specific |
| You want a stable public API for imports | You want easy deletion/refactoring |
| File would make sense in another app |

A CSS framework is a pre-written library of Cascading Style Sheets (CSS) code that provides a foundation of ready-made styles and components to streamline web development.
CSS frameworks generally fall into different categories, each with its own approach:
text-align-center, bg-blue-500). Developers compose these classes directly in HTML to build completely custom designs, offering maximum flexibility.| Aspect | Tailwind CSS | Bootstrap |
|---|---|---|
| Design philosophy | Utility-first (compose styles in markup) | Component-first (prebuilt UI components) |
| Styling control | Pixel-level, fully custom | Opinionated, follows Bootstrap’s design |
| Learning curve | Steeper at first (many utilities) | Easier initially (ready-made components) |
| Design consistency | Enforced via config (theme tokens) | Enforced via Bootstrap defaults |
| Custom designs | Excellent (no fighting the framework) | Can be harder (overriding styles) |

| Aspect | MDX | CMS |
|---|---|---|
| What it is | Markdown + JSX in code | Content management system (UI + backend) |
| Who edits content | Edited by Developers | Edited by Non-dev |
| Content location | In the codebase (Git) | In a database (cloud or self-hosted) |
| Workflow | Git-based (PRs, reviews) | UI-based (forms, publish buttons) |
| Custom components |
Building this project was not without it’s constraints
Holding a full time job unrelated to web development and building this meant that this entire side-project had to be:
After Deployment, I’ve ran some loading tests via Google’s Lighthouse Test.
If you’re building for the modern web, Google Lighthouse is your primary diagnostic tool. It is an open-source, automated tool designed to improve the quality of web pages. When you run a Lighthouse audit, it simulates a mobile or desktop user visiting your site and provides a report card across five key categories: Performance, Accessibility, Best Practices, SEO, and Progressive Web App (PWA).
Lighthouse doesn't just give you a random number; it calculates your score based on several specific "Core Web Vitals." Here are the three most common culprits behind low scores and how to fix them.
What it is: Measures loading performance. It marks the point in the page load timeline when the largest image or text block becomes visible.
priority attribute on your LCP image in Next.js.What it is: Measures visual stability. Have you ever tried to click a link, but the page suddenly shifted and you clicked an ad instead? That is a high CLS.
width and height (or aspect ratio) for images and video elements.min-h-[700px]) for content that loads asynchronously.What it is: Measures interactivity. It quantifies how long the main thread was "blocked" by JavaScript, preventing the user from clicking buttons or scrolling smoothly.
next/dynamic to load heavy components only when they are needed.Lighthouse scores of 80-90+% on both Desktop and Mobile (Average of 5 tests per page)
What I’d change: remove or prune excessive blog posts or long-form content that gets no traffic — favor high-signal case studies. (However, this would only be after I measure web analytics traffic on a later stage)
What I kept intentionally simple: certification list and concise project summaries — avoid turning the portfolio into an aggregator/scraper of every accomplishment. I had initially wanted to scrape all my certifications however with the frequency of site updates versus my own accreditations. I quickly realized that RPA was a tarpit/honeypot that was not worth the time-cost benefit.
| File wouldn’t make sense elsewhere |
Both folder structure goes hand in hand, however paying attention to your imports tells a better story of how your files/folders should be structured.
Quick heuristic
If deleting a route should delete the file → co-locate it.
If many routes depend on it → top-level folder.
| CSS output size | Very small (purged utilities) | Larger (ships full framework) |
| HTML verbosity | More classes per element | Cleaner HTML |
| JS dependency | None (CSS-only) | Often relies on Bootstrap JS |
| Long-term scalability | High (fits design systems well) | Medium (customization debt grows) |
| Refactoring UI | Safe & localized | Risky due to overrides |
| Best fit | Custom apps, design systems, product UI | Admin panels, prototypes, quick sites |
Tailwind is usually better when
However just because it fits my case doesn’t mean it works for you. And with Tailwind’s development being a little shaky, I’m not certain what the future holds.
In addition to all of these points, a few disadvantage of using Tailwind in my experience are as follows:
| Native & powerful |
| Possible, but often limited |
| Version control | Git (excellent) | CMS history (varies by tool) |
| Setup complexity | Low | Medium to high |
| Hosting dependency | None | Usually external service |
| Best for | Blogs, docs, dev-heavy sites | Marketing sites, content teams |
As they are both used for different cases and edited by two different set of users. It is obvious that it is solution dependent.
With that being said, The content you’re seeing on this page is managed in CMS whereas my blogs are MDX generated. Having had a taste of both worlds, my honest views for both have their own downsides and you would just have to pick your poison.
(If you’re interest in CMS, I’ll be posting a medium post about how I started my setup for Sanity CMS)