Building a Fast, Accessible Portfolio with Next.js and Tailwind
When I set out to rebuild my portfolio, I gave myself two rules that everything else had to bend around: it should load fast on a mediocre connection, and it should work for everyone regardless of how they browse the web. A portfolio is a developer's proof of work, so cutting corners on the two things I claim to care about professionally wasn't an option. Here's how the site came together and the decisions that shaped it.
Why performance and accessibility came first
It's easy to treat speed and accessibility as things you bolt on at the end, right before launch, when there's no time left to do them properly. I've learned the hard way that they're architectural decisions, not finishing touches. If you pick a heavy client-side framework, ship a megabyte of JavaScript, and lean on divs for everything, no amount of last-minute tweaking will save you. So I started from the constraints and worked inward: assume a slow phone in Ghana on patchy data, assume a keyboard-only visitor, assume a screen reader. If the site holds up under those assumptions, it holds up for everyone.
The stack
The site runs on Next.js with the App Router, written in TypeScript, and styled with Tailwind CSS. That combination does a lot of the heavy lifting for free. The App Router lets me render pages on the server by default, so most of what reaches the browser is finished HTML rather than a blank shell waiting on JavaScript. TypeScript keeps me honest about the shape of my data, especially as the blog and CV pages grew their own content models. Tailwind means my styles ship as a single small, purged stylesheet instead of a growing pile of bespoke CSS I'd eventually be afraid to touch.
How I hit 90+ on Lighthouse
The performance score didn't come from one clever trick — it came from refusing to ship things I didn't need.
Images are the usual culprit, so every image goes through Next.js's <Image> component, which serves modern formats, sizes them for the actual viewport, and lazy-loads anything below the fold. Fonts are self-hosted and preloaded rather than pulled from a third-party origin at runtime, which removes a render-blocking round trip. Most of the site is static or server-rendered, so there's very little client-side JavaScript to parse and execute — the interactive bits (the contact form, a few animations) are the only things that hydrate. I also kept third-party scripts to almost zero, because each one is a tax on every page load whether the visitor uses that feature or not.
The result is a site where the meaningful content paints quickly and the layout doesn't jump around while it settles.
Accessibility choices that mattered
Accessibility started with semantics. Headings follow a real outline, navigation lives in a <nav>, and buttons are buttons — which means keyboard users and screen readers get the structure for free instead of me reconstructing it with ARIA patches. Every interactive element has a visible focus state, so you can always see where you are when tabbing through the page. I checked color contrast against WCAG AA so text stays legible for low-vision visitors, and I respect the prefers-reduced-motion setting so animations calm down for anyone who finds movement distracting or nauseating. Images carry meaningful alt text, and the contact form pairs every field with a proper label rather than relying on placeholder text that vanishes the moment you start typing.
None of this is exotic. It's mostly a matter of using the platform the way it was designed and testing with a keyboard before shipping.
What I'd improve next
I'm not done. The blog you're reading is new, and I want to build out a proper content pipeline with structured data so posts surface well in search. I'd like to add automated Lighthouse checks in CI so a regression fails the build instead of quietly shipping. And I want to run a real screen-reader pass end to end — automated tools catch maybe half of accessibility issues, and the other half you only find by actually listening to the page.
If you're building your own portfolio, my advice is simple: decide up front that fast and accessible are requirements, not nice-to-haves, and let that shape your stack. Everything gets easier when those aren't afterthoughts.
Building something similar or want to talk shop? Get in touch — I'd love to hear what you're working on.