‹ Back to the archive
// Live Project still in progress. Last updated May 2026.
May 2026

Personal Portfolio Website

A self-hosted portfolio site built with Astro, Tailwind, and content-driven Markdown. The site you are looking at right now.

astrotailwindtypescriptweb-appmarkdownclaude-code
Hero image for Personal Portfolio Website

// Challenges

Going from empty repo to a finished portfolio meant lots of design iteration. Picking the right palette and font, getting the project taxonomy down to filters that actually help a recruiter, finding real images for every project, and writing all the project copy in a voice that sounds like me. Each pass made it cleaner.

// Skills Used

Astro 5 Tailwind CSS 4 TypeScript Content collections Markdown authoring Claude Code Information architecture Visual design

// Current Status

V1 is built and running locally. Final tasks before launch are hosting deployment to my own server, swapping in real project photos, finishing the resume PDF, and a last polish pass on copy.

Brief

The site you are looking at. A self-hosted, statically-generated portfolio that collects every project I have built and every season I have spent in robotics into one place. The brief was my own. I wanted something I could show to colleges, recruiters, and friends, that loaded fast, looked distinctive, and made my work easy to scan.

Process

Stack. Astro 5 with Tailwind CSS 4 and TypeScript. Astro because it ships static HTML by default, which means the site is fast and easy to host anywhere. Tailwind because the utility-first model lets me iterate on visuals at the speed of changing class names instead of editing CSS files. TypeScript because the content collections are typed end-to-end, so a missing image URL or a wrong tag value gets caught at build time.

Architecture. Every project is a Markdown file in src/content/projects/. The frontmatter holds the title, date, summary, tags, focus, skills, challenges, and outcome (or current status for in-progress projects). The Markdown body is the deep dive. Astro reads the collection at build time, generates one detail page per project, and powers the homepage and projects index from the same source. Adding a project is “create a Markdown file and add an image.”

Iteration cycles. This was the most-iterated project I have built. Color palette started as Solar Forge amber-gold, went through a Fraunces editorial serif phase, and ended on the current Anton condensed industrial direction with brass-gold accent. Fonts cycled from Inter to Space Grotesk to Newsreader to Fraunces to Audiowide to the current Anton plus JetBrains Mono pair. Each pass dropped something and committed harder to a single visual direction.

Filters. The /projects page has a filter system that was redesigned three times. First version had every granular tag as a filter button. Too noisy. Second version had six focus areas. Still too many. Final version has two filters (Hardware and Software) plus a granular tag chip system on each card that surfaces specific techniques (CAD, Onshape, Arduino, woodworking) without being filterable. The split between filter granularity and card detail granularity is the single biggest UX improvement on the site.

Accessibility pass. A full a11y review covering keyboard focus rings, prefers-reduced-motion, skip-to-content link, aria-current on nav, descriptive link labels on cards (so screen readers do not read every card’s contents as one giant link name), and a contrast bump on muted text. The accessibility work is invisible in screenshots but it is the difference between a portfolio that works for everyone and one that does not.

Voice. Every project’s copy went through a rewrite to sound like me, not like a press release. The robotics page especially got a team-player rewrite so the achievements read as the team’s wins, not as mine.

Skills built

  • Astro 5 end to end. Content collections, dynamic routing, layouts, components, MDX rendering, hot reload. This is the stack I’ll reach for the next time I need a content-driven site.
  • Tailwind CSS 4. New @theme syntax, CSS variable theming, the Vite plugin, utility composition. Comfortable using Tailwind for fast visual iteration without it becoming a maintenance problem.
  • TypeScript content schemas. Defining defineCollection schemas with Zod so every Markdown file is type-checked at build. Compile errors caught what would have been runtime issues.
  • Information architecture. Deciding what goes on the homepage versus the projects page versus the project detail page. What surfaces and what hides until clicked.
  • Visual design discipline. Picking one aesthetic direction and committing instead of mashing influences. The Anton condensed industrial direction is intentional and applied across every page consistently.
  • Accessibility engineering. WCAG-aligned focus, motion, and labeling. Not optional. Default.
  • Claude Code as a coding partner. Same workflow I used on the Cup Pong firmware and the trading bot. Describe the goal, review the output, iterate. The site exists because the iteration loop with Claude Code lets me try ideas faster than I could implement them solo from scratch.

What’s still left

  • Hosting deployment to my own server (have the domain, have the build, just need to wire the deploy).
  • Real project photos. Most images are stock right now. Swapping them for my actual project shots is the last big content task.
  • Resume PDF generation and linking from the About page.
  • A final copy pass to catch anything that still sounds like a robot wrote it.

Why this is on the site

A portfolio that lists a portfolio site as one of its projects is a slightly recursive move. It is on here because building the site itself was the biggest software project I have done so far. Every decision (palette, type, filter taxonomy, accessibility, voice) is documented in the commit history and visible in the result. The site is its own case study.