Color and target size
Recomputes contrast for every color token pair in both themes against WCAG AA, and requires interactive text controls to be at least 24px tall. It caught four real contrast defects when it was introduced.
64 checks
I redesigned kousikdutta.com so a hiring manager meets two flagship stories first, and directed a build that checks every release before it goes out.
Problem
The old gallery set every project at the same level and left a reviewer to piece my career together. It looked like a polish job, but polish without hierarchy only makes clutter more convincing.
What I found
The job was making the strongest work easy to find without flattening the range behind it.

What I decided
Home carries the hiring read: the flagship projects lead into full case studies, supporting work stays compact, the career is one list on the homepage with “The full story” folded under it, and the resume is one PDF.


What I decided
Shared navigation, theme-aware media, route metadata and release checks keep every project page inside one system, so no page drifts off on its own.

What I decided
Claude built a 1.49 MB particle engine that hit its frame-rate target. I deleted it because it explained nothing. AI will build anything I describe, so knowing what to delete is the job.
What shipped
Each gate exists because an earlier release let that mistake through.
Recomputes contrast for every color token pair in both themes against WCAG AA, and requires interactive text controls to be at least 24px tall. It caught four real contrast defects when it was introduced.
64 checks
Fails on any image over 300 KB, any unconverted raster, and any source model left where it would be deployed. Added after the homepage was found shipping 8 MB.
13.9 MB of 14 MB budget for all images across the site
Requires every route to ship its own social card, drawn from the site’s own type and color tokens and held under 400 KB. Added after every route was found sharing a single image, so a shared link never showed the page it pointed at.
20 routes covered

Fails on alt text that names a section and a counter, a filename, or a bare noun. Added after 32 images shipped with placeholder alt like “Research overview 4,” which passed the accessibility gate and still told a screen reader nothing.
30 alt texts in the source checked
Generated on 2026-10-22 from the same build data that feeds the gates above.
generate-journal-metadatatsc -bcheck-decisionsbuild-reportvite buildpostbuildprerendercheck-glasscheck-a11ycheck-weightcheck-ogcheck-seocheck-altcheck-escapescheck-voiceRequires every published design decision to include considered options, positive and negative consequences, and a kill criterion. A decision cannot ship as a preference with the cost removed.
scripts/check-decisions.mjsFails the build if any compiled CSS blurs the backdrop, so glass cannot creep back in through a refactor or a utility class.
scripts/check-glass.mjsReads every page’s built HTML the way a crawler does, and fails on a missing or duplicate title, a description outside 120 to 160 characters, a canonical that disagrees with og:url, a card of the wrong size, JSON-LD that does not parse, or a page without exactly one h1. Added after the sitemap was found listing a noindex page and the structured data pointing at a card that no longer existed.
scripts/check-seo.mjsFails on visible escape sequences and em dashes in source copy. Comments are ignored, so the gate checks what readers can actually encounter.
scripts/check-escapes.mjsFails when a log entry uses the phrases that most often give generated writing away: filler transitions, stock openers, and vocabulary nobody says out loud.
scripts/check-voice.mjsLooking back
Next time I’d put the site in front of people who hire much earlier. The checks verify the rules I encode; they can’t tell me whether a reviewer understood the work, or whether every accessibility issue has been found.
There was no brief, so I took on what nobody asks of a portfolio: a social card for every route, and a build that checks contrast, alt text and its own copy before anything ships. I talk each change through out loud, Claude Code writes it, and I review every change.