This Website
The site you are reading — a home for what I'm building (HitterLoop) and a record of what I'm working on.
- Status
- Building
- Category
- Web
- Started
- Sep 1, 2026
- Timeline
- Sep 1 – now
- Next.js
- TypeScript
- React
- Tailwind CSS
- MDX
Overview
This site is where I keep a record of what I'm building — HitterLoop, mainly. Most personal sites are a résumé with a nicer font. I wanted something closer to a dashboard — a place where the content updates because I am still doing the work, not because I remembered to update a portfolio.
It is deliberately built in the open, and it is its own first case study.
Why I Built It
I had the usual scattering. Projects lived in GitHub repos with thin READMEs. Side projects lived in folders and notes with no context around them. None of it added up to a view of what I was actually working on.
The annoyance that started it: I could not answer "what have you been doing for the last three months?" without opening four apps and doing arithmetic.
The Idea
One site, one focus, one changelog.
The key decision was to treat the site as a read surface over structured data rather than a set of hand-written pages. Every item on the homepage comes from a typed record somewhere. If I want the homepage to say something new, I add data, not markup.
The second decision was a hard split between what is public and what is not. Anything personal that I track for myself stays behind authentication; the public site only carries what I am happy to publish.
How It Works
Three layers, and the boundary between them is the interesting part.
content/ + data/ typed records — MDX frontmatter, TS modules
↓
lib/data/*.ts the only modules a page may import
↓
app/** server components; near-zero client JavaScript
Pages never touch a data file directly; they go through async functions that return typed records, so swapping a local file for a database changes the body of one function and nothing else.
Pages are server components by default. Client components exist only where they earn it: the theme toggle, the active-navigation underline, and the interactive calculators on the older Money pages.
The Build
Content. Project write-ups are MDX with typed frontmatter, parsed at build time. Editing a project means editing a file in the repo, which is the only workflow I will reliably keep up with.
Charts. Hand-written SVG, rendered on the server for the site's own charts. No charting library, no client bundle, and they inherit theme colours from CSS variables so dark mode is correct rather than inverted.
Personal tools. Anything I track privately lives in a separate, authenticated area backed by a database with row-level security. It is excluded from the sitemap, from indexing and from analytics, and nothing from it is rendered on the public site.
Problems I Ran Into
The public/private boundary had to be structural. My first pass had a single
data module with a visibility flag on each record and filtering at the page
level. That works right up until the day I forget one filter. Moving personal
data out of the public codebase paths entirely removed the whole class of mistake.
Charts were the wrong place to reach for a library. I started with a charting library, and one chart alone pulled in a client bundle larger than the rest of the page. For a handful of chart types with fixed requirements, writing the SVG directly was less code than configuring the library away from its defaults.
Even spacing lied about a gap. The first chart placed points by index, so a long gap in the data looked identical to a short one. Positioning by date made the gap visible, which is the honest picture.
What I Learned
Structuring the data first made the design decisions easy. Once a value was a field on a typed record rather than a string in a component, the question stopped being "what should this card say" and became "what does this number mean", which is a much better question to be designing around.
Also: the amount of client JavaScript a site needs is usually a design decision, not a technical one.
What I Would Change
I would decide what is public and what is private before writing a single component, and define the public types first, rather than walking them backwards out of the markup.
Current Status
Built and running: homepage, projects, /now and /about, all server-rendered, both themes, no horizontal
overflow down to 320px, and no accessibility violations under axe.
The earlier finance tools and videos remain live at their direct URLs but are no longer part of the main site. Current work is keeping the HitterLoop write-up accurate as the product changes.