Skip to content
Journal

Rebuilding Habbo.dk for adults, ten years late

skyskraber is my hobby — a 2D chat universe for Danish-speaking adults in the lineage of Habbo, Netstationen, and 3Dbyen. 123 tables, 51 WebSocket modules, one engineer.

6 min read#skyskraber#habbo#websockets#chat-platform

I was eleven the first time I logged into Habbo.dk. My mother had bought me a Habbo coin card from the kiosk on the corner, on the understanding that this was instead of a Christmas present. I spent the coins on a sofa. A pixel sofa, in a pixel room, in a hotel that existed nowhere except in a Flash applet running on a beige iMac in my parents' kitchen.

That was 2007. Habbo.dk closed in January 2015. I was, by then, a teenager who'd moved on to Facebook and IRC and the early shoots of what would eventually become the rest of my career. But I remember the sofa.

I also remember, with a level of detail that surprises me, the specific feel of a populated chat room at 8pm on a Tuesday. The pixel jostle of avatars on a sofa that wasn't yours. The way private messages opened in a little floating window that you could drag around. The slightly anxious wait between sending "hi" and seeing the three dots that meant somebody, on the other side of a screen somewhere in Denmark, was typing back.

Habbo.dk is gone. So is 3Dbyen. Netstationen is still alive but it's an outlier — a piece of living Danish internet history, almost three decades old, that has very deliberately not modernised. The whole genre — 2D avatar chat, real-time rooms, player economy, the lot — has been hollowed out and replaced with TikTok and Discord and a faint cultural assumption that adults don't do this kind of thing anymore.

I'm building skyskraber on the bet that the assumption is wrong.

What skyskraber is, and who it's for

skyskraber — Danish for "skyscraper" — is a real-time 2D social chat platform. Themed rooms. Customisable avatars. Apartments you can decorate. A player-driven marketplace with auctions. Quests with multi-chapter storylines and scripted bot NPCs. Minigames you remember from a flash arcade in 2009: lottery, roulette, coinflip, rock-paper-scissors. Loot chests. Stripe-integrated premium subscriptions.

It is, very specifically, for Danish-speaking adults. 18+, no exceptions. The age gate is a feature, not a paperwork concession. The whole genre's reputation problem from the 2000s — predators on children's chat platforms, moderation that couldn't scale, parents who were right to be suspicious — gets sidestepped by simply not having children on the platform. Most of the actual users of Habbo.dk in 2014, before it closed, were already adults logging in for the nostalgia. The 2026 version of this product can lean into that audience instead of pretending around it.

If you remember the timeline — Arto, Habbo.dk, Netstationen, Sol — you already know exactly what skyskraber is. If you don't, the Habbo.dk obituary on the skyskraber blog is a better explanation than I can manage in three paragraphs here.

Why now, and not five years ago

The honest answer is that five years ago I couldn't have built this. Not by myself.

A 2D real-time multiplayer platform with the surface area of a small SaaS — economy, marketplace, moderation, quests, achievements, payments, admin tooling, the works — is not a weekend project. It is two or three years of full-time engineering at a small studio. It is exactly the kind of project that, historically, an indie developer would start on a wave of enthusiasm and abandon at the 30% mark when the scope reveals itself.

What changed is the pair-programming loop. I work with Claude as a genuine collaborator — not as a code-completion tool, but as a second engineer who reviews, refuses, and explores. The skyskraber codebase exists in something close to its current form because the cost of "I'm not sure how I'd structure this, let me think out loud with someone who knows the stack" dropped to nearly zero. Range matters more than headcount, especially when the range is multiplied by a second mind that doesn't get tired at 11pm.

The other thing that changed is hoststack — my own European PaaS — coming together. A heavy real-time WebSocket workload on a hobby budget would historically have meant a bare Hetzner box, a bunch of late-night reverse-proxy configuration, and a brittle deploy story. Running skyskraber on hoststack means git push, blue-green rollout, managed Postgres and Redis next to the service, and WebSocket handover during deploys that connected users don't notice. The platform's job is to make this kind of project a tractable hobby project. It does.

Scale check

Calling skyskraber a hobby project is technically accurate and somewhat misleading. At the time of writing, the repo contains:

  • 123 database tables

  • 42 backend services

  • 41 API route files

  • 51 WebSocket modules

  • 172 frontend route files (23 public, 149 inside the authenticated chat SPA)

  • 81 backend test files

For comparison: this very site, micci.dk, has roughly one-tenth of that surface area. skyskraber is, in operational terms, a small SaaS that happens to be a hobby. The reason it's tractable as a hobby is that the same stack I use commercially — Bun, Hono, Drizzle, React 19, TanStack Router and Query, Tailwind — also runs the hobby. Context-switching is the silent killer of solo work. Same stack everywhere means I can open apps/api/src/services in any of my repos and already know the conventions.

The two interesting bits, technically

There are two engineering decisions in skyskraber that I'd probably never have made for a commercial product, and that I think are the most interesting things in the codebase.

The first is the dual-app frontend. skyskraber ships two completely separate applications from one repository: a public marketing site (index.html) and an authenticated chat SPA (chat.html). They share components, hooks, API clients, and types — but each has its own route tree, its own entry point, and its own bundle. The marketing site is small, fast, and crawlable. The chat SPA is heavy and never indexed. The marketing site doesn't pay the bundle-size cost of the chat app, and the chat app doesn't carry the weight of marketing copy and SEO scaffolding. The seam between them is two index.html files and a Vite configuration. Five lines of decision, days of payoff.

The second is the WebSocket architecture. 51 WS modules sounds like a lot until you start enumerating: rooms, presence, movement, chat, typing indicators, message moderation, room state, item trades, marketplace listings, marketplace bids, quest progress, bot dialogue, minigame state, admin notifications, jail enforcement. Each one has its own message shape, its own broadcast scope, its own reconnection semantics. Half the surface area of the codebase is just answering the question of who needs to know about what event, and when, without melting the broadcast layer.

I'll write a deeper post about each of these at some point. For now, the version-one observation is that real-time multiplayer is mostly a taxonomy problem, not a technology problem. Picking the right channels and scopes matters more than picking the right WebSocket library.

Where to look next

If the nostalgia angle is the thing that hooks you, the skyskraber blog is the right place to read more. It's in Danish, because the audience is. The piece on why avatar chat is growing again as people get tired of video meetings is the most interesting cultural argument I've made for the product so far.

If you're a developer reading this and thinking about your own out-of-hand hobby project, the part I'd encourage you to steal isn't the genre. It's the same-stack-everywhere discipline. The reason I have time to build a hobby chat universe at all is that nothing in my commercial stack is unfamiliar when I sit down at the hobby codebase. Bun is Bun. Hono is Hono. Drizzle is Drizzle. The mental tax of context-switching, which used to eat half a Saturday afternoon every time, is gone.

If you remember Habbo.dk, skyskraber.dk is open. You'll know what to do. The sofa is purple this time.

Was this useful?