Two Kids and Eight Projects Later

Updated:
8 min read

Not one big project. Eight of them, spread across GitHub and Tangled.

I should say up front: I also became a father to twins this year. The first few projects here (Hip UI, kich.io) overlap with the NICU stretch. I'd commute to the hospital every day after work; the coding happened at home, in the wee hours. The rest I built on parental leave, mostly late at night or during naps when they were both asleep.

That context matters for the numbers below. A lot of this wasn't "free time." It was the small windows I had, and coding was sometimes the thing that kept my brain occupied when I couldn't do much else.

Many of these projects kept asking the same question: what does it look like to build on the AT Protocol with modern full-stack TypeScript?

This post leads with the numbers and stack, then a short header per project with a collapsible write-up if you want the full story. Takeaways at the end.

The numbers

Between October 2025 and June 14, 2026:

Commits1,539
Lines of code~768,000
Documentation~54,000
Cursor tokens~8.8 billion

Take the LOC with a grain of salt. There's a fair amount of copy-paste architecture (hip-ui) in that number.

ProjectCommitsCode LOCActiveHost
kich.io640178,609Jan-MayGitHub
atstore.fyi26784,886Apr-MayGitHub
kikbak.tv7758,722Apr-MayGitHub
standard-reader.app177106,055JunGitHub
console.cocore.dev11287,701May-JunGitHub
Hip UI21891,722Oct 2025-AprTangled
forked18122,839May
vinyl-scrobbler3037,629MayGitHub

The stack I kept using

After eight projects a default stack showed up:

Full-stack web: TanStack Start + React + Vite. I scaffolded almost everything with the TanStack CLI.

Styling: StyleX + Hip UI. Hip UI is my own design system (shadcn-style copy-and-own, but built on React Aria). I've iterated on this between the projects and open sourced it. I don't plan to promote it much, but it's a good default for most projects.

Data: Postgres + Drizzle. Most of this was within Railway but I tried Neon for standard-reader.app.

AT Protocol: Custom lexicons published with goat, OAuth via @atcute/oauth-node-client, Tap consumers and Jetstream to index network data into Postgres.

Tooling: pnpm workspaces everywhere except forked (Bun). oxlint and oxfmt instead of ESLint/Prettier on the TS projects. Vitest for unit tests. Playwright on standard-reader.app for perf regression.

Observability: OpenTelemetry + Honeycomb on the heavier ingest stuff (kikbak.tv, standard-reader.app).

Throughout the projects I iterated on how I used AI. That started with Hip UI, right as models were getting good enough that it felt worth testing on real work.

Hip UI

218 commits · 91,722 LOC · Oct 2025 to Apr 2026

Hip UI is the design system everything else built on. I'd worked on three separate design systems before this and wanted one open, hackable base. shadcn-style copy-and-own, but built on React Aria with StyleX, and design tokens.

Full write-up

This is where my AI experiments started. Models had gotten good enough that generated components were usable, and Hip UI seemed like the right place to test that. Turborepo monorepo, docs site, and an MCP server. Hosted on Tangled, a git forge built on AT Protocol. Docs at hip-ui.tngl.io.

Every component started with AI. Load a Cursor skill, generate a first pass, reshape until it matched Hip UI's patterns. I was mostly testing which skills respected StyleX and React Aria and which I'd throw away. Hip UI ships an MCP server so other projects can pull in the design system properly.

API design and a11y review stayed manual even when the boilerplate came from a skill. Design systems punish inconsistency, so the workflow was skill → draft → edit → ship. That carried into kich.io and everything after.

kich.io

640 commits · 178,609 LOC · Jan 3 to May 24

kich.io is a smart kitchen assistant: pantry inventory, recipes, grocery lists.

It started as personal software. My wife nerd-sniped me into building something that could keep track of our pantry, and my own ideas ballooned it from there into recipes and grocery lists. Then I got double nerd-sniped by people on Bluesky to make it an ATProto app. That pivot turned kich.io into my first real ATProto app: it has its own lexicons (io.kich.*), OAuth, tap sync, the works.

Full write-up

AI wrote almost all of kich.io. The backend I barely touched: server functions, ingest, lexicon handlers, the database layer. All of it came out of Cursor sessions and I rarely edited that code directly. On the UI I stepped in more, but usually only when I couldn't prompt my way to the exact result I wanted. For layout and design, I used MagicPath to ideate on screens before building them out in Hip UI.

In the product itself, kitchen features like recipe suggestions and parsing also leaned on models. I had AI write the observability instrumentation too. That pattern has held up across projects: bugs and perf problems are much easier to find and fix when the traces are already there.

For how I ran the sessions, I used Deciduous, a decision graph tool for AI-assisted development. As you work, it builds a persistent graph of goals, decisions, actions, and outcomes. When a Cursor session ends or context compacts, you can query what was tried, what got rejected, and why. I'm not sure how well it really did. I'd need to have built those features without it to know. The project came together well though, and it's useful to go back and see what was tried and why.

Skills were a separate layer. I pulled reusable agent capabilities from skills.sh, the open agent skills directory. Things like vercel-react-best-practices, UI animation, lint-and-validate, and code review. Install once with npx skills add, swap them in per task.

Browse what's already on the platform: kich.io/discover has community recipes and collections.

atstore.fyi

267 commits · 84,886 LOC · Apr 8 to May 23

atstore.fyi is an open directory for the Atmosphere. App Store-quality discovery, but the listings are protocol-native records, not rows in a database we own.

The gap I kept running into: we'd spent months debating login pages, and nobody was answering the question that comes right after sign-in. What can I actually do with an Atmosphere account? Legacy app lists were dead, expired, or squatted. I wanted something that felt like an app store built on the same primitives as the apps it lists.

Full write-up

How it got built:

  • Archaeology: scraped old app-listing sites and manually verified every entry. Most were gone.
  • Lexicon discovery: walked NSID → domain across published lexicons to ask whether something was actually an app.
  • Listings as records: seed on the ATStore account, builders claim and move stewardship to their own PDS. Portable, revocable, no lock-in.
  • Protocol-native features: reviews live on the reviewer's PDS, OAuth scope scrubbing (every permission surfaced, with a loud warning on transition:generic), interoperability detection ("Works with…" from shared lexicons), Germ affordances on listings, live creator updates pulled from standard.site publications instead of inventing a changelog lexicon.

I reached out to people in the working group and kept finding folks already debating the same directory problem. A few weeks before launch I donated the project to the AT Protocol Community Fund. Volunteers picked up lexicon work, categorization, translations, and UX. It stopped being my side project.

At launch: 102 claimed apps, 172 reviews. ATStore was never meant to be the one directory, just one node in a network of directories reading the same open data. Code lives at ATProtocol-Community/ATStore now.

AI wrote most of the code. I focused on design, UX, and features; MagicPath for layouts, Cursor for admin tools and scraping scripts. skills.sh and the Hip UI MCP for agents. The hard part was data collection and hygiene, not UI. I manually reviewed every listing.

kikbak.tv

77 commits · 58,722 LOC · Apr 16 to May 12

kikbak.tv is my longest-running project. It started in college as a collaborative YouTube playlist app and morphed over the years into a We Are Hunted-inspired music video chart. The core idea stayed: crawl the blogs people actually read and surface what's playing. These days it indexes hundreds of blogs looking for YouTube links, ranks by genre and recency, and pulls in Bluesky chatter around videos.

Full write-up

It's also an AT Protocol app. Sign in and your saved links live on your PDS, not in a kikbak-owned table. For each video on the chart we also pull related posts from Bluesky, so you can see what people are saying about a track without leaving the page.

AI was mainly for tooling that helped me pull up and process the data I needed. I lost all my blog data on MongoDB from a previous kikbak iteration, then bought a list of music blogs to seed the next one. I generated admin tools and scripts to pare it down to something useful.

AI largely helped me solve another problem: categorizing articles. Knowing whether an article is about a music video and what genre that video belongs to is very useful for a site like kikbak. In the past, the tools failed or were not very good at this work, so I never shipped it. But using today's off the shelf models, I was able to integrate it accurately and cheaply into the process.

I also used Claude on the UI side. I landed on a grid layout for the videos that I actually like: dense, browsable, and a bit more interesting than a straight list. Claude is good at generating options, but you still have to cut most of it. It throws in extra copy, chrome, and ideas that do not help the page do its job. I had to decide what was worth keeping and strip the rest.

The AI setup on this one matched everything I'd settled on by then. It was working.

console.cocore.dev

112 commits (428 total in repo) · 87,701 LOC · May 7 to Jun 14

console.cocore.dev is about receipts for computational work on the AT Protocol. Decentralized compute without a central coordinator. Providers sign records to their PDS, AppViews index them, requesters use a console.

Full write-up

This is Deving Gaffney's project. He's been ideating on decentralized compute for years; recent tech (the AT Protocol, cheap inference, better dev tooling) finally made a lot of it buildable. I own the console UI: friends, chat, model pages, device pairing. Lexicon, Rust provider, and AppView are shared.

My contribution was mostly monorepo knowledge and tooling. I set up the repo so it was easy to iterate with AI: workspace boundaries, agent rules, and fast checks that agents (and humans) could run without guessing. I also used cocore as a testbed for a new toolchain: aube, mise, and hk. mise was the standout; it managed all the start scripts across the Rust provider, AppView, and console, so booting a local stack stopped being README archaeology.

AI handled most of the bootstrap work: dev setup docs, local env, UI iteration in Cursor. Once mise could bring everything up, I could work on the console instead of the monorepo plumbing.

On the design side, I'd already used Claude on kikbak.tv for layout. Cocore was where I leaned into Claude Design and customized Hip UI for the product: darker palette, monospace accents, more terminal than the polished default on kich.io or atstore.fyi.

Tech:

  • Rust provider + Swift provider shell
  • TS monorepo: @cocore/console, @cocore/appview, @cocore/sdk
  • mise + aube + hk for env, packages, and hooks
  • Effect for all console server functions (required by cursor rules)
  • Hip UI MCP in .mcp.json for Claude Code
  • Schema-first: lexicons win, never hand-edit generated types

forked

18 commits · 122,839 LOC · May 12 to May 21

forked is cross-platform food discovery. The idea is to review dishes on how good the food actually is, not the full restaurant experience. Yelp reviews wander into service, vibe, parking, and everything else; forked is map-native menu pins where the unit of review is the item on the plate. React Native + web from one codebase.

Full write-up

This was my first React Native project and a break from the TanStack + StyleX stack I'd been repeating. I bought Takeout to see what a good cross-platform repo looks like: Bun instead of pnpm, Tamagui instead of StyleX, One / Expo for native, Docker Compose and Zero for the backend, the tko CLI, agent docs baked in.

Nearly all of the dev work has been agent-driven. Takeout type-checks reliably and the agents keep writing tests. My hand-rolled monorepos never felt that automatic. CLAUDE.md has explicit "don't cheat" rules (no commenting out code, no any, no skipped tests, never delete bun.lock). CLAUDE.md and AGENTS.md steer agents well because they're always in context.

I'm still working on it, but progress is slow. The new stack takes longer to move in, so my attention kept drifting back to the stuff I was shipping faster.

vinyl-scrobbler

30 commits · 37,629 LOC · May 29 to May 31

vinyl-scrobbler is a home-network now-playing display and scrobbler. Personal software that only runs on my LAN. It's also an AT Protocol project: listens get recorded to teal.fm on my PDS. The TV side shows what's playing, how far into the track you are, and the lyrics. On vinyl you don't get any of that without stopping to look it up.

Full write-up

A spare old iPhone sits by the record player running Shazam through a Pushcut webhook; identifications stream over SSE to a web UI and an Apple TV client. The longer plan is a smart plug on the record player so plays get tracked automatically; right now the phone does the listening.

Before most of the code, I had AI interview me about the project, one question at a time, until we had APP_VISION.md. From that we generated TODO.md, and agents.md told every session to keep both current.

On Apple TV, TVML is a lot like vanilla JavaScript, and the app had data-sync bugs: one part of the UI updating would clog another, and the screen would lie about what was playing. Sounded like a React problem. The existing React TVML bindings are more than a decade old and unmaintained, so I had AI generate a replacement with hooks and effects.

The Apple TV design was entirely mine. Apple's TV design system is straightforward, and you really cannot mess it up. Extending their design language was just as easy, so there was no reason to reach for AI design.

standard-reader.app

177 commits · 106,055 LOC · Jun 5 to Jun 13

standard-reader.app is a reader for standard.site publications on the AT Protocol. RSS reader vibes (Goon / Reeder), but built around discovery: a directory of publications on the network, not just stuff you already follow. Publications are signed records in author repos, not feeds we poll.

Full write-up

standard.site data comes in through Tap into Neon Postgres. For everything around an article, I used microcosm instead of building crawlers. Constellation takes an article URL and returns what links to it: Bluesky posts, margin.at notes, Semble cosmik cards, cross-publication citations, cosmik graph edges. That feeds Discussion, "Cited in," related reading, and trending. Comment counts cache locally and refresh from Constellation in the background. Slingshot is the fallback for slow PDS reads (Sifa resume chips on author profiles).

The dev setup was the same as my other projects by this point. Same AI workflow, same stack habits.

RSS is great, and this looks a lot like it. But the open nature of the AT Protocol means you can build a reader without locking into one company's platform. Content isn't walled to a single site; it can move. What that means for businesses building on AT Protocol is still unclear when anyone can index the same records and ship a competing reader.

AI Workflow Takeaways

A few things worked across projects.

Skills for UI. A small set from skills.sh (React best practices, animation, lint-and-validate, code review) was enough. Load the skill, generate a draft, edit. Started on Hip UI, kept using it through kich.io, atstore.fyi, and standard-reader.app.

Hip UI + MCP. Building out my own design system was super fun and applying it helped me spot the things I need to improve. The MCP server made it easy to get real APIs and tokens into agents, highly recommended for large systems!

APP_VISION.md interviews. The vinyl-scrobbler pattern I'll reuse: AI asks one question at a time until APP_VISION.md is clear, generate TODO.md from it, tell AGENTS.md to keep both updated. Good for kickoff and later marketing copy.

AI design. Claude Design is good, but watch out for adopting the tool's own visual style. Lean on it too hard and everything starts to look like the same generic AI design. What's actually useful is layouts and arrangement. AI is strong at composition when you already have design system primitives to work from. Point at a running prototype and say "make these two things look as close as possible." That works well.

The job shifts toward UX and product thinking. Make sure the thing works, then make sure it works for humans: labels, flow, where things live. I coded less and thought about the product more. AI made it easier to apply the design sensibilities I'd built up over my career and actually land the version of the app I had in my head.

AT Protocol takeaways

I've been building in this space since 2024, but these projects were my first full AT Protocol stack apps. I wanted to learn the ropes. I like user-owned data and think there's a lot we can build now that we couldn't before.

The model is simple

AT Protocol, in practice: publish records, something indexes them, that's an app. Fire records, run a listener, update a database.

It gets messy when canonical data lives on a PDS and your UI reads from Postgres. You can't await a PDS write like a local transaction, so you end up with optimistic UI. React Query fixed most of it; a few spots stayed janky. I tried TanStack DB and bounced off it. The generated code was more than I wanted to maintain.

What goes on the protocol

If the data would be public, put it on the protocol. There's no private data yet. Households on kich.io and some reading-list shapes on standard-reader.app would probably be private if that existed.

You don't need everything on the protocol. Just the leaf records. The AppView does the rest. On forked, the records are simple; aggregation and presentation live in the indexer. Same idea as Bluesky feeds: the feed contents aren't a blob in your PDS, and different indexers can interpret the same records differently.

Auth, lexicons, ingest

OAuth: @atcute/oauth-node-client and the patterns I copied project to project worked well. Remembers your handle, a few clicks to sign in. console.cocore.dev has the newest login flow.

Lexicons: goat makes publishing easy. I used plan mode when designing schemas and reviewed what went in before picking an NSID.

Ingest: start with Tap. Jetstream for one-off custom stuff without backfill. microcosm goes further than you'd expect (standard-reader.app uses Constellation and Slingshot heavily).

What's still missing

Tap + your own database is simple on paper and a lot of work in practice. HappyView is close, but I need more control over the ingestion pipeline. Most app-view-in-a-box tools handle lexicon publish/ingest but not custom logic in the middle. I want that DX next to my code, not as another Docker thing off to the side. For now, Tap worker + Postgres is what I trust.

What's next

Work! My paternity leave is ending, and I won't have time for all these fun little side projects. I'll keep working on the ones that I have and probably create a few more personal tools. But for now I'm focusing on my job and my family.

Enjoying the blog?

Subscribe to get new posts delivered straight to wherever you read standard.site publications.

Subscribe