This is a submission for the GitHub Finish-Up-A-Thon Challenge
An app I started in 2024 as a basic life counter, abandoned, and finally came back to finish... this time as a proper deck-testing companion for Star Wars Unlimited.
🛠️ What I Built
SWU Playtesting is a companion app built with React Native + Expo (web + Android) for the trading card game Star Wars Unlimited. It keeps track of how your decks actually perform. You can register decks, log test games, and it tracks each deck's record, matchups, and history. And because you still need to count life while you play, the whole thing doubles as a themed life counter.
In short: it turns the question from "who's winning this game?" into "which of my decks actually wins?".
⏳ Where It Started (the unfinished project)
In 2024 I started to build an app that could be used as a life counter for Star Wars Unlimited. The life counters I found out there weren't really adapted for this game, and theme-wise they had nothing to do with it either, so I decided to get hands-on with a React Native app I could use for myself.
I would have liked to build something bigger, but over time I ended up abandoning it. It worked as a basic life counter, yes, but there was no way to customize anything: colors, initial life points, nothing. Everything was static. The styles weren't even particularly good. At the very least, it needed a Settings screen.
This is how it looked:
|
|
Two life totals, an initiative marker, and a reset button in the middle. That was it. Clearly just a first step — a truly complete app would have a lot more going on.
✅ The Comeback Story
When I came back to it for this challenge, the plan was small: add a few settings so the user could customize the app a little, and clean up the UI. But the more I looked at it, the more I kept thinking... what kind of app would I actually want to use? And an idea came to mind.
I saw it clearly: what I really wanted was a playtesting app. Something that lets me keep track of my decks, see how they perform against other decks, and still count life during the actual game — registering wins and losses as I go. That was the plan. So I started building toward it, one feature at a time.
A note on how I built it: spec-driven development
Here's one of the parts I'm most proud of, and the thing that actually let me finish.
Instead of letting an AI agent dance on his own across the codebase, I drove everything through spec-driven development with OpenSpec. Every feature started as a written proposal (the why and the what changes), then a design doc for the trade-offs, then a tasks list — and only then did I let Claude Code implement it. Each finished feature became one clean, self-contained change.
The payoff shows up in the git history:
Ah... how satisfying it is to see such a clean commit history after applying spec-driven development correctly. Six features, six commits, each one a complete and reviewable step. No shocking diffs or "fix the bug again" commit messages... just a readable story of the app growing up.
So here's that story, feature by feature.
feat-001: A home and some settings
What I wanted: Stop dropping the player straight into a hardcoded life counter with life locked at 30, red vs green - that's not a personalized app that's an assumption.
So the first real step added a Home screen (Start Game / Settings / Exit) and a Settings screen where you could pick team colors per side and choose your life mode (count down from a value you set, or count up from 0). And crucially, it all persisted with AsyncStorage, so that you set it once, and the app remembers.
To add different colors, I needed help from Claude Code to re-generate the images that I already had to change the glow color. It took me a while to get the result I wanted, so if I could go back in time I'd probably work on my own assets using Canva or a similar tool.
|
|
feat-002: Settings that actually make sense
What I wanted: The "Count Up / Count Down" toggle was trying to explain two ideas at once, and it wasn't the best user experience.
So I collapsed the whole thing into a single Initial life points value you can type directly (or step with +/−). While I was in there, I added two small quality-of-life options I'd actually use: an animations toggle (for a snappier, lower-motion feel) and haptic feedback on +/− presses for mobile.
feat-003: The app gets a memory (deck tracking)
What I wanted: This is the one that changed everything. A life counter forgets every game the moment it ends. But the players who test decks - the people I was building this for - track their win-rates and matchups in spreadsheets. I wanted to move all of that into the app.
So I added a shared pool of named decks (aspects, leader, archetype, notes), a persisted game log, and stats derived from it (record, win%, streak). Each deck got a detail screen with head-to-head matchups (grouped by event, with strategy notes), a full game history, and a Bulk Add flow to backfill a whole season of testing at once. The stats are symmetric — recording "A beat B" updates both decks automatically.
feat-004: Making it look finished (modernize UI)
What I wanted: By now the app did a lot, but it still looked unfinished. The space background only showed up in-game, the dialog buttons were a saturated blue/red that fought the theme. The reset control looked like a "refresh" arrow.
So this was a pure visual pass: an animated starfield behind every screen (and a static fallback when you turn motion off), metallic dialog buttons instead of the clashing colors, the reset arrow became a proper hamburger menu, and the blurry initiative bitmap became a crisp vector token that finally looks right in landscape too.
feat-005: From "life counter" to "SWU Playtesting"
What I wanted: The app had quietly become a deck-testing tool, but it still introduced itself as a life counter. Time to commit to what it actually was.
So I renamed my app to SWU Playtesting, added a standard bottom tab bar (Home, Decks, and Settings), and turned Home into a dashboard: Your top-performing deck, a ranked list of your decks with one-tap Test, and a quick Play Test Game button. New icon, a calmer denser starfield, real branding.
To generate the icon, I went back-and-forth with Claude Design and Google Stitch for a while, but I finally used Claude Design. I'll get into more details about my AI experience later.
feat-006: A real design system (the final redesign)
What I wanted: Well, the style still wasn't quite to my taste after all... I found it a little flat. I wanted every screen to feel like a finished product.
So I built an actual design system: shared metallic-silver + gold tokens and a reusable component kit, then restyled the app around it. Starting with a redesigned Home with a metallic header, deck cards with numbers-only records and recent-form sparklines, and a gold Play Test Game button. Same tokens everywhere, so the next screen stays consistent by construction. This is the version you see in the demo below.
🎬 Demo
A quick walkthrough: Home, the decks and their stats, settings, and then starting a test game and counting life.
Video
Portrait: Main screens
![]() Home |
![]() Decks |
![]() Deck detail |
![]() Settings |
![]() Life counter |
Landscape: Home and Life Counter
🤖 My Experience with AI
I'll be upfront about my tooling here. Instead of GitHub Copilot, the AI assistant I actually reached for was Claude Code (the desktop app). For this challenge I had a limited amount of time and a huge number of possibilities to explore, so I wanted an agent that could automate the work in a performant way, and Claude Code was the one I felt most confident with.
But the agent was only half of it. To make sure I'd get high-quality work, avoiding hallucinations and saving costs wherever I could, I paired it with spec-driven development via OpenSpec. Every feature was a written proposal → design → tasks before a single line of code, and that discipline is exactly what produced the clean six-commit history above. The spec did the thinking; the agent did the typing.
For assets and a couple of screens I leaned on a few tools together. I used Claude Code Design for visual exploration, and I made good use of Google Stitch, especially for the Home page redesign: I'd send screenshots of the app's current state and ask for specific improvements, and after a few tries I got exactly what I needed. Then I handed those screenshots back to Claude Code to actually implement the redesign.
One funny lesson: the icons Google Stitch generated were a bit off from what I had in mind, so I went back to Claude Design to generate the final icon art. Right tool for the right job.
🧗 Challenges & Lessons
- Scope creep is real. I sat down to "add a settings screen" and stood up with a deck-tracking playtesting companion. Letting the project become what it wanted to be was the best decision I made, but only because spec-driven development kept each step bounded so it never turned into a mess.
- Specs keep an AI honest. The temptation with an agent is to just say "make it nicer" and let it dance. Forcing every change through a proposal first meant putting on the table what was being changed and why. And the diffs could be reviewed at anytime. Giving that context to an AI is a huge advantage.
- Design is iteration. The look went through three identities (basic → modernized → a full metallic design system) before it felt mine. Bouncing between Google Stitch and Claude Design until the icons and Home were right took patience, but I knew what I wanted and the final result is worth it.
🧰 Tech Stack
Expo SDK - React Native - AsyncStorage - Node's built-in test runner - OpenSpec for spec-driven development - Claude Code - Google Stitch + Claude Design for assets.
📦 Repo & Try It
- Code: https://github.com/IcarusTheFly/swu-playtesting/tree/finish-up-a-thon-challenge
- License: Proprietary - all rights reserved (it's a personal project, and the Star Wars theming isn't mine to relicense).
-
Run it:
npm install→npm run web
🔭 Where It Goes From Here
The app is the tool I wanted in the first place. The obvious next step isn't a missing feature, it's distribution: getting it polished for the Google Play Store so other SWU players can test their decks the same way I test mine.
Thanks for reading! If you play Star Wars Unlimited and want to track the performance of your favourite deck while having a life counter to use in your games, this is exactly what I built. 🎴














Top comments (0)