githeroproduct-developmentchangelogai-workflowsolodev

What I shipped in February (and how it actually went)

February 27, 2026

At the start of February, GitHero was down. Not crashed - deliberately shut down. I had decided to go back to basics, keep the blog, and show a coming soon page until I knew exactly what the app should be. It felt like the right call when I made it. It felt less right three days later when I realized I missed building.

On February 5th I published a post about how projects never end up where they started. I spent several hours on it, trying to get every thought articulated clearly - the pivot, the reasoning, what gamification had actually taught me. Then I unpublished it the same day and left it in a draft folder. I'm still not sure why. Sometimes you write something to figure out what you think, not to tell anyone about it.

I wrote it in limbo - app gone, direction unclear, but convinced that pivoting away from gamification toward something more substantive was correct. A week later I resurrected the app from an archive snapshot and started building again. February turned out to be the most productive month since the project started.

This is a rundown of what actually shipped, how I worked on it, and what went sideways along the way.

The app came back

Resurrecting GitHero from an archive snapshot was more dramatic than it needed to be. The snapshot was from the right point in time, but that also meant auth flows, sync logic, and some edge cases in API handling needed to be fixed again. Three pull requests just to get back to working state: GitHub OAuth that actually worked, sync that handled invalid tokens without exploding, and a build step that forgot to generate the Prisma client before the Next.js build ran.

None of it was glamorous. But it was necessary, and it moved fast. I've learned that underestimating infrastructure work is a mistake you only make once.

Contribution trend sparkline

The single biggest thing I built in February. A sparkline is a small time-series graph with no axes or labels - compressed information that tells a story in minimal space. The idea was to show 52 weeks of commit activity as a curve instead of GitHub's grid of green squares.

I worked on it in an isolated git worktree through my project manager skill. It's a workflow I've written about in the context of the tech lead workflow - in short: feature work happens in a separate worktree so main is never blocked and rolling back is straightforward if something breaks. The sparkline PR was #7, and it contained five commits: a utility for generating SVG paths from raw data, integration on the profile page, an OG image for Twitter/X, a widget format via the API, and an option in the widget generator.

The hard part wasn't path generation. It was deciding how to normalize the curve. If a user has one week with 80 commits and another with 2, a linear scale looks like an EKG with one spike and then nothing. I landed on a soft normalization that preserves the relative shape without letting extreme values dominate the entire picture.

There's still room to improve it. But that's the trade-off you always make on solo projects: good enough to ship, or good enough that it never ships.

Activity Card and sharing to X

Once the sparkline existed on the profile page, I wanted to be able to share it. That seems like a simple requirement - "add a share button" - but it expanded quickly.

Sharing to X requires an OG image. The OG image needs to be generated dynamically based on the user's data. But which graph should be shown - the sparkline or the contribution heatmap? That depends on which tab the user has active when they click share. So I needed to pass the active variant along in the API call. And while I was at it I added tabs to the Activity Card - one for trend, one for contributions - with a share dropdown that respects what you're actually looking at.

This was one of those times my project manager skill actually earned its keep. I had started with "add a share button" and noticed I was drifting into scope creep in real time. Asked the skill what was actually required for an acceptable MVP, got back a shorter list, and stuck to it. The best AI collaboration is often the kind that steers you away from what you wanted to do.

Insights bugs that had been hiding

The Insights page - weekly analysis of your coding patterns - had three bugs that nobody had reported but were all pretty bad once you found them.

The time chart only showed 9am. No matter how you spread your commits throughout the day, every bar was empty except one. Root cause: I was building the hour distribution from GitHub's commitContributionsByRepository API, which returns one contribution per day per repo - not per individual commit. The data coming in was fundamentally limited. The fix was to build the hour distribution from commitStats.committedAt instead, which is populated from the REST API with exact commit timestamps.

Private repo names leaked into flair text. The shareable insights page correctly anonymizes private repos in the chart, but the flair text - a small line under each insight card - was never sanitized. So the text "First week Horsemate2 appears as most active" was visible publicly to anyone visiting your profile. Horsemate2 is a private repo. That kind of bug is uncomfortable to find.

PRs and reviews always showed 0. The sync job sets dailyStats.prs to 0 and never updates it. The PR data exists in PullRequestStats with createdAt timestamps, but the insights calculation never looked in that table. Same for reviews. Straightforward to fix once you find it - direct COUNT queries against the right tables - but it had been wrong since the insights feature was first built.

All three surfaced in the same session. It often goes that way: you start looking at one problem, you start understanding the system more deeply, and bugs reveal themselves.

Other things that shipped

Account settings and delete flow. Users can now manage their account and delete it. Not spectacular, but it's one of those things that needs to exist if you're taking the project seriously.

DataFast analytics. Added pageview tracking and CTA tracking via DataFast. I wanted a lightweight alternative to PostHog for simple traffic overview without managing event schemas.

Per-language OG images for the leaderboard. The leaderboard page has filters per programming language. Now unique OG images are generated for each language filter, so sharing the Python leaderboard looks like the Python leaderboard and not the generic homepage.

How the month actually went

I work alone. That means there's nobody to catch scope creep, architecture decisions that feel right but aren't, or bugs sitting in blind spots. I've replaced some of that with AI workflow: a project manager skill to challenge decisions and keep scope in check, a tech lead mode for architecture discussions, and isolated worktrees for feature work.

It works better than operating without it. It's not a substitute for actual collaboration. The difference shows most when you're about to make a decision you know is probably wrong but want to be talked into anyway - an AI that agrees isn't valuable. One that asks "why that specific choice and not X" is.

February ended with a clearer picture of what GitHero is. A profile that tells a story about how you work. Shareable, honest, data from GitHub without being yet another dashboard full of numbers nobody interprets.

That's what I'm building toward, anyway. Ask me again in March.


GitHero is at githero.dev. If you find bugs or have opinions about what should be built next, find me on X.