Tharindu Munasinghe
Projects

Case study

This Portfolio

This very site: a personal portfolio designed and built end-to-end with Claude Code assisting, one real feature at a time.

This portfolio's homepage with the hero and role tags

At a glance

Role
Sole designer and developer, built end-to-end with Claude Code assisting
Status
Live and actively maintained
Platform
Web (responsive, desktop and mobile)
Tools
Claude Code · VS Code · Git · GitHub · Vercel
Tech stack
Next.js 16 · React 19 · TypeScript · Tailwind CSS v4 · EmailJS · Vercel

Sections

  1. 1. The Problem
  2. 2. Approach
  3. 3. Real Decisions & Fixes
  4. 4. Outcome

Section 1

The Problem

A portfolio needed to exist: one place showing who Tharindu is, the real projects he's shipped, and a working way for people to actually reach him, built on a real design system instead of a generic template.

Section 2

Approach

Built up in layers, starting with tokens and primitives before any page content existed:

  • Turned a supplied color palette and type scale (the Forest and Mint palette, an Inter type ramp) into actual CSS custom properties and Tailwind utilities, not just a reference document.
  • Built a small component library first, a Button, NavLink, Navbar, and ThemeToggle, before writing any page content, so every later page reused the same primitives instead of one-off styles.
  • Added a manual light/dark toggle on top of the system preference, using a data-theme override and an inline script so the stored theme applies before first paint instead of flashing the default.
  • Wired the contact form straight to EmailJS with no backend, since a static portfolio has nowhere to run server code, then confirmed the same setup actually worked once deployed to Vercel, not just in local dev.

Section 3

Real Decisions & Fixes

Part of using an AI coding agent well is checking its claims instead of accepting them. A few examples from this build:

  • React's ViewTransition component, documented for this Next.js version, turned out not to exist in the installed stable React build. That got checked with a one-line Node script before any code was written around it, rather than shipping something that would silently do nothing.
  • The theme toggle's icon briefly mismatched between server and client, because its initial state read localStorage during render. Fixed by always rendering the same default on both sides and correcting it in a layout effect just before paint.
  • Tapping a card or button on a phone left it visually stuck in its hover state until tapping elsewhere. Fixed once, site-wide, by redefining Tailwind's hover variant to require an actual hover-capable pointer.
  • EmailJS's service ID, template ID, and public key are safe to keep in the client code itself. The whole integration runs in the browser, so an environment variable would not have hidden them any better; the real safeguard is the allowed-domains list in the EmailJS dashboard.

Section 4

Outcome

A live, responsive portfolio with a real design system, working project case studies with an image carousel, and a working contact form, built with iterative assistance from Claude Code, with the developer checking claims and fixing what it got wrong along the way, rather than accepting output at face value.

Links

More projects