2026.06 - Present

Clover — An Open-Source Engineering Portfolio

An open-source personal portfolio built as an engineering project, documenting the architecture, decisions, and development process behind the work.

AstroTypeScriptDesign SystemDocumentation-Driven Development

Why I Built It

I wanted a portfolio that goes beyond showing a static list of past projects.

The site itself should demonstrate my engineering approach: how I make technical decisions, structure reusable systems, document trade-offs, and iterate on a product.

That led to Clover — a personal engineering portfolio built as an open-source software project.

The goal isn’t just to publish a clean website. The goal is to make the repository, system architecture, internal documentation, build process, and finished site part of the portfolio.

This project serves two clear purposes:

  • A public showcase for my engineering work.
  • A long-term codebase to show how I design, build, review, and evolve software.

What I Wanted to Build

Instead of a static resume page, I wanted a working system: a static Astro site structured around five core pillars — Projects, Writing, Notes, Resume, and About. These run on a shared Content Collections layer rather than fragmented, single-use page templates.

Under the hood, the architecture relies on two key choices: a token-based Design System consumed by every component, and project documentation (Sprint records, ADRs, roadmap) maintained directly alongside the code to prevent context drift.

Engineering Approach

Clover Architecture

Clover is organized as a small, content-driven system rather than a collection of distinct, one-off pages.

flowchart TB
  C["Clover<br/>Astro + TypeScript"] --> P["Five content pillars"]
  P --> P1["Projects"]
  P --> P2["Writing"]
  P --> P3["Notes"]
  P --> P4["Resume"]
  P --> P5["About"]

  C --> CC["Shared Content Collections"]
  CC --> P

  C --> DS["Token-based Design System"]
  DS --> UI["Reusable UI primitives"]
  UI --> P

  C --> DOC["Documentation"]
  DOC --> D1["Sprint records"]
  DOC --> D2["ADRs"]
  DOC --> D3["Roadmap"]

  C --> DEP["Static delivery"]
  DEP --> G["GitHub Pages"]
Content, UI infrastructure, documentation, and static delivery form one connected system.

The system map explicitly ties content, UI infrastructure, documentation, and static delivery together into one pipeline.

Each architectural decision was evaluated against explicit trade-offs and documented so it could be revisited later without re-litigating the core reasoning.

Key Decisions

Astro

The portfolio is content-heavy and does not need a full client-side application state. Astro gives us a minimal static baseline while keeping the door open for interactive UI elements when necessary.

Trade-off: Prioritizes static build delivery and low complexity over a single-page application framework.

GitHub Pages

As an open-source static portfolio, the project does not require a dynamic backend server. GitHub Pages handles static host infrastructure directly alongside source control and CI/CD runs.

Trade-off: Accepts static hosting boundaries in exchange for zero maintenance overhead and low operational costs.

Component First

Rather than building pages in isolation, I built basic UI primitives first and composed them into larger layouts later.

Trade-off: Requires more setup effort up front, but eliminates duplicate markup and speeds up global styling updates later.

Documentation First

Documentation lives in the codebase as a build asset rather than a post-launch chore.

Trade-off: Increases initial development time per feature, but retains essential context for both human code reviews and AI coding agents.

Development Journey

Sprint 01 — Foundation

Sprint 01 established the initial application structure and documentation framework.

The focus was kept tight: set up the Astro workspace, define the base layout, configure environment rules, and set up decision records.

This resulted in a minimal, deployable foundation that supported future sprints without compounding technical debt.

Sprint 02 — Design System

Sprint 02 shifted focus from page routes to reusable component infrastructure.

Instead of writing custom styles on individual pages, I extracted core UI primitives, including buttons, layout containers, headings, section blocks, cards, and link variants.

I separated the CSS architecture into distinct layers so visual variables could change without breaking component logic.

This sprint shifted the codebase from a single website into a reusable design framework for building pages.

Sprint 03 — Content

Sprint 03 introduced the content layer on top of the Sprint 02 design primitives.

It started with a unified Content Collections infrastructure — a single schema and query layer shared by Projects, Writing, and Notes. Every section was built out as an empty shell first: list routes, detail routes, and empty states were wired up and tested end-to-end before drafting long-form content.

Validating the content engine early ensured that rendering bugs were caught before content creation became a bottleneck.

Sprint Evolution

Development followed a clear path: set up the base platform, build reusable UI systems, then validate the content pipeline end-to-end.

flowchart LR
  S1["Sprint 01<br/>Foundation<br/><br/>Working Astro site<br/>Core layout<br/>Documentation + decisions"] -->
  S2["Sprint 02<br/>Design System<br/><br/>UI primitives<br/>Design tokens<br/>Clear CSS responsibilities"] -->
  S3["Sprint 03<br/>Content<br/><br/>Content Collections<br/>Section shells<br/>End-to-end verification"]

  S1 --> R["Reusable engineering foundation"]
  S2 --> R
  S3 --> R
Each sprint builds toward a reusable engineering foundation.

The process moved the codebase from an initial web page prototype to an extensible publishing system.

What I Learned

The best insights from building Clover came from observing where the architecture, workflows, or initial assumptions fell short.

I learned that architectural decisions only matter if they survive across development sessions. Early on, several design choices lived only in memory. When a new AI context session suggested conflicting implementations later, the problem wasn’t the AI’s idea — it was that the original trade-offs were never written down anywhere accessible. I now use ADRs as durable memory for the repository so any contributor (human or AI) shares the exact same context.

I ran into a similar context issue when an AI agent removed the default Astro homepage without creating a replacement route. The build passed and the code was syntactically correct, but the site was broken for visitors. The agent satisfied the literal command (“delete this file”), but missed the real task requirement (“replace the old landing page”). I now treat explicit verification steps and boundary definitions as core acceptance criteria.

The Design System grew out of a similar practical problem. Early page layouts looked fine, but CSS values were hardcoded directly inside individual component files. Nothing broke immediately, but maintaining those styles would have turned into a mess as the site expanded. Extracting design tokens early stopped visual drift before it spread. Whenever a pattern is going to repeat, defining the abstraction early is much cheaper than refactoring it later.

I hit a similar lesson with my definition of done. I used to accept code changes piecemeal across multiple review turns. Eventually, I realized that small piecemeal updates aren’t the same as an integrated feature. Every task output should be a complete unit that can be built, tested, and reviewed on its own.

These experiences shaped how I maintain engineering standards.

Rules aren’t just arbitrary instructions; they are persistent project memory. They preserve core decisions, operational constraints, and hard-earned lessons that would otherwise get lost over time.

This matters even more when using AI tools in your workflow.

The goal isn’t to add rules for the sake of strictness. The goal is to keep project knowledge explicit so every change builds on top of the same baseline context.

That idea sits at the center of how Clover is designed and built.

Current Status

The Content Collections pipeline and all five core section shells — Projects, Writing, Notes, Resume, and About — are built and verified.

Projects and Writing hold the first published pieces, while About contains the current profile details. Notes and Resume use validated schema mock data to confirm layout behavior and data boundaries.

The codebase is under active development, with upcoming sprints focused on visual polishing, long-form content, and underlying tooling improvements.