The Player Hub, From Clubhouse to Rewards Hub
I built a whole room-decorating, avatar, and clubhouse economy over three weeks, then tore most of it out in one afternoon. Here's why, and what's left of it in the code.
If you dig through webapp/cosmetics.py
right now, you'll find a title achievement called room-hoarder,
another called fair-trader, and one called
trade-up-chemist. None of them are earnable
anymore. They're fossils — the last remaining trace of a feature I built
over about three weeks and then mostly deleted in a single afternoon. This
post is about why.
Act one: My Room
Back in late August, I shipped My Room: a personal space you could decorate with 22 draggable objects across 6 categories, set against 6 full-scene backgrounds, with the Pixel avatar editor built right into it. It was fun to build and it looked good in screenshots. Friends launched alongside it, so you could actually go look at someone else's room, which gave the whole thing a reason to exist beyond "decorate a virtual room by yourself," which, said out loud, is not much of a pitch.
It stuck around for about three weeks. Then I did something I probably shouldn't have, which is add an entire second progression system right on top of it before the first one had proven itself.
Act two: the clubhouse sprint
Over two days in mid-September I built, in roughly this order: a daily
item-crate unboxing feature with a rarity-based loot table, a syncable
inventory system with its own save keys, an item-trading layer (hence
fair-trader and
trade-up-chemist),
a Daily Bounties system with rotating quests, a Sticker Album, and — I want
to be honest about how far this went — an interactive pet system with
multiple species that had their own achievements. There was a real
clubhouse route with its own template and its own trophy art. I even wrote
tests for it.
In isolation, every one of those is a reasonable feature. Daily crates and bounties are the exact kind of "give people a reason to open the site today" mechanic I'd wanted since the Coins economy first went in. The problem is I built six of them at once, on top of a room-and-avatar system that was still just three weeks old, and none of them talked to each other in a way that felt like one coherent thing. A new player would've hit: an avatar editor, a room to decorate, a clubhouse with crates in it, a separate bounty board, a sticker album, and a pet — six surfaces, six mental models, and no obvious reason any of them needed to be separate screens instead of tabs on one screen.
The afternoon it all came down
Two days after the pet system shipped, I deleted it, along with My Room,
the avatar editor, and the clubhouse route. The commit is just called
removed the club house my room and avatar
and it removes over 3,000 lines — the room template alone was north of
2,100 lines by itself. That's not a small revert. That's admitting the
whole direction was wrong, not just one piece of it.
What replaced all of it is what's live now as the Player Hub: one screen, one currency (Coins), and six tabs — Daily Crate, Daily Bounties, Sticker Canvas, Achievements, Collection, and Customize. No room to walk around in, no separate avatar page, no pets. Everything that earned its place got folded into a tab; everything that was there mostly because it seemed cool at 1am got cut. Profile icons picked up real visual effects and selectable frames as part of the consolidation, which is honestly a better payoff for "look, I unlocked something" than a pet ever was, because it shows up everywhere your name does instead of on one page nobody else visits.
What's still there, if you know where to look
The interesting part, to me, is that the delete wasn't total. Achievement
titles are permanent once granted — if you'd earned
room-hoarder or
fair-trader
in that three-week window, you can still equip it today, so those ids are
still sitting in _TITLE_IDS
in webapp/cosmetics.py,
right next to titles that are still perfectly earnable, like
bounty-hunter and
sticker-grand-collector.
There's no comment marking which ones are dead. You'd only know by trying
to find the feature that grants them and coming up empty. I kind of like
that they're there — it's an honest record of the site's history that a
changelog entry doesn't really capture, sitting quietly in a set literal
nobody but me will ever read closely.
The account-sync side needed cleanup too, and that part I'm less
comfortable calling finished. Cosmetics only validate against a fixed set
of known ids — VALID_COSMETIC_IDS
in that same file — specifically so someone can't paste a made-up string
into a sync payload from devtools and have the server accept it as a real
unlock. That check never verifies you actually *earned* the id, only that
it exists in the catalog at all, which was an acceptable gap when the
worst case was a fake room decoration. It's a smaller gap now that the
clubhouse's inventory and trading layer are gone, but it's still there, and
closing it properly means moving unlock state server-side instead of
trusting the client's sync payload — a bigger project I punted on rather
than solved.
Was cutting it the right call?
Mostly, yes, but not entirely. The consolidated Player Hub is simpler to explain, simpler to maintain, and I'm fairly sure it's easier for a new player to actually understand in the first five minutes than "here's your room, here's your avatar, here's the clubhouse" ever was. But I don't think the underlying ideas were bad — a pet you actually take care of, ongoing trading between friends — I just shipped all of them at once instead of one at a time with room to see whether each one actually got used before building the next. If any of them come back, it'll be one at a time, bolted onto the Player Hub that already exists, not as a fourth new screen.
The honest lesson isn't "don't build ambitious features." It's that shipping six of them in the same 48 hours means you can't tell which one was actually worth keeping before you're already past the point where cutting feels expensive. Next time I'll ship one, sit with it for a week, and let that answer the question instead of guessing.
More from the Devlog