This Website!
This portfolio, rebuilt from scratch. The old version was a client-rendered React single-page app; I rebuilt it as a fast, static Astro site that ships almost no JavaScript, with a theme-aware design system in Tailwind, typed content for the projects and posts, and a full structured-data layer so both people and AI answer engines can read it well. You are looking at it right now.
- Astro
- TypeScript
- Tailwind CSS
- HTML5
- CSS
- Git
- GitHub
- Inkscape
Summary. The site you are reading. I took my old React single-page app and rebuilt it as a fast, static Astro site: a theme-aware design system, typed content for the projects and posts, and a structured-data layer so it reads well for both people and AI answer engines. It is the same soul as before, lifted to where I am now.
From a junior single-page app to a static site
The first version was a client-rendered React and Vite single-page app. It worked, but it shipped a blank page until the JavaScript loaded, and there was little for a search engine or an AI engine to read. I rebuilt it on Astro, which renders real HTML at build time and ships almost no JavaScript, so the first paint is instant and every page is fully readable on its own.
One source, two readers
The projects, posts, FAQ, and the experience timeline each live in one place, and that one source feeds both the visible components and the JSON-LD: a Person, a CreativeWork for each project, an Article for each post, an FAQPage, and a BreadcrumbList. On top of that the site has a sitemap, a robots file that welcomes AI crawlers, and a curated llms.txt, and the writing is answer-first with question-shaped headings so an AI engine can quote a single section cleanly.
The design system
Colours, spacing, and shadows are CSS variables switched by a class, so light and dark are one system rather than two stylesheets. The type is Fira Sans, the sky accent is used sparingly on a calm base, and the experience timeline, cards, and buttons all draw from the same tokens. Motion is subtle and respects reduced-motion. The goal was to feel like me, not like a template.
Performance
The output is static HTML with no framework shipped to the browser; the only JavaScript is a few small vanilla pieces for the theme switch, the project filters, and the mobile menu. The font is self-hosted, images are optimized to WebP at build time, and the scrollbar gutter is reserved so nothing shifts between pages. On Google PageSpeed Insights it scores 100 for performance, accessibility, best practices, and SEO, on both mobile and desktop, with every Core Web Vital green. Test it yourself.
Stack
Astro 5, Tailwind CSS, and TypeScript, with typed content collections for the projects and the blog, linted with ESLint, and deployed as plain static files. The logo and the small icons are hand-drawn in Inkscape.
Questions
Why rebuild it in Astro instead of React?
The old site was a client-rendered single-page app, which meant a blank page until JavaScript loaded and little for search or AI engines to read. Astro renders real HTML at build time and ships almost no JavaScript, so it is faster and far easier for both people and machines to read.
What does "structured data" do here?
Alongside the visible page, each page emits JSON-LD that describes it in a machine-readable way, who I am, what each project is, what each post is, and the breadcrumb trail. It comes from the same data as the visible content, so the two never drift.
How fast and accessible is it?
On Google PageSpeed Insights it scores 100 for performance, accessibility, best practices, and SEO, with every Core Web Vital green and 3/3 on the AI agent readiness check, on both mobile and desktop. You can re-run the test yourself at pagespeed.web.dev.