DEV Community

Cover image for I built a live pixel library where vibe coders sit together while their AI works
Choi Minho
Choi Minho

Posted on

I built a live pixel library where vibe coders sit together while their AI works

Vibe coding alone at night gets lonely. You send a prompt, the agent goes off for a few minutes, and you sit there staring at a terminal.

So I built Vibrary: a live pixel-art library where people coding with AI sit together. When you run Claude Code, Codex or Gemini CLI, your character takes a seat and a little bubble shows what your AI is doing — thinking, editing, running tests, shipping. When someone deploys, the whole room claps.

A pixel-art library where characters sit at desks while speech bubbles show what each person's AI is doing

The clip is demo mode with sample people. The real library is still small.

This post is about how it's built and the things that went wrong along the way. Almost all of the code was written with Claude Code; I did the planning, the pixel art direction and a lot of testing.

What it does

  • A live room. Everyone's AI activity shows up as a character at a desk, in real time, across five floors.
  • Privacy first. No code, prompts or file paths ever leave your machine. Only the kind of activity and some numbers.
  • A verified card for your GitHub README. Tokens used, commits, deploys, AI work time — so "I use AI a lot" becomes something you can actually show.
  • Free promotion. Register what you built and it shows up on the library's wall display.

A Vibrary AI builder card on a GitHub profile showing active days, tokens, AI work time, deploys and commits

1. Start with one ugly HTML file

The whole library began as a single HTML file with a canvas: rooms, seats, characters, bubbles, an elevator between floors. Iterating on the feel was much faster when everything was in one place and I could just refresh.

When it was time to ship, I didn't rewrite it. Claude wrote a small build script that takes the prototype and turns it into the pieces the Next.js app loads: the engine script, the markup and the CSS. The script also patches a handful of spots for "live mode" (real people instead of sample ones).

The same script handles translation: every Korean string literal in the engine is replaced from a JSON dictionary at build time, and the build fails loudly if anything is left untranslated.

Lesson: a throwaway prototype doesn't have to be thrown away. A build step that adapts it is often cheaper than a rewrite.

2. Privacy as a hard rule, enforced on both ends

The CLI watches your AI tool's activity locally and only sends something like this:

{ "kind": "edit", "tool": "claude_code", "data": { "added": 42, "removed": 7 } }
Enter fullscreen mode Exit fullscreen mode

On the server, the ingest function keeps only numeric fields from a fixed list and drops everything else, so even a buggy or modified client can't smuggle text through.

What counts as a "deploy" (for example git push or gh pr merge) lives in a rules file on the server. When I found commands being misclassified, I could fix the rules without shipping a new CLI — and the CLI re-scans when the rules version changes.

3. Signed auto-updates

A CLI that updates itself is convenient and scary. Vibrary's CLI checks for a new version at most once a day, then:

  1. downloads the npm tarball and checks its sha512 integrity,
  2. verifies an ed25519 signature on the actual script with a public key baked into the old version,
  3. test-runs the new file,
  4. swaps it in and keeps the previous one around.

If any step fails, nothing changes. The signing key never leaves my machine, so a compromised npm account alone can't push code to people.

4. Realtime presence was the hardest part

Presence (who's sitting where) runs on Supabase Realtime. The bug that took the longest: people sometimes showed up on the wrong floor after reconnecting.

The cause: one person can briefly have more than one presence entry (a reload, two tabs), and I was reading the first one. The fix was boring but solid:

  • always trust the newest entry,
  • re-reconcile the whole room every 15 seconds instead of only reacting to events.

People who close the tab but whose AI is still working stay seated as "ghosts", and members who were here in the last 24 hours stay as "resting" (with a little zZ), so the room doesn't feel empty when you're the only one awake.

5. Make it fast by measuring first

A canvas full of text and bubbles redrawn every frame got heavy. My first guesses about what was slow were wrong; profiling showed text measurement and redrawing static boards every frame. Caching measureText results and pre-rendering the boards into offscreen canvases helped, and so did loading the leaderboard in parallel instead of after everything else.

One more fun one: the engine used to seat ~200 sample characters and then clear them in live mode, which meant the header briefly said "223 online" before showing the real number. Now live mode simply never seats them.

6. Anti-cheat that punished the wrong person

I added daily caps to stop people from gaming the leaderboard: over 30 deploys in a day and that day got flagged and dropped from rankings. The first person it caught was me, on a heavy deploy day.

I removed automatic flagging. Everything counts now, unusually busy days are listed for manual review, and only a human can exclude a day. Automated "fairness" that hits your most active users is worse than none.

What I'd tell someone starting a similar project

  • Keep the fun part (the look and feel) in a fast prototype as long as you can.
  • Decide what you will never collect on day one, and enforce it on the server, not just the client.
  • Treat auto-update as a security feature, not a convenience.
  • Profile before optimizing — especially when an AI is writing the optimizations.

Vibrary is free, and you can look around without signing in: vibrary.dev. If you code with agents for hours, I'd love to hear what would make you keep it open in a tab.

Top comments (2)

Collapse
 
koda2026 profile image
Harun - solo dev •

choi, this is a brilliant solution to a very real problem: the loneliness of vibe coding. the pixel-art library concept is not just fun, it's genuinely community-building. 🐯🎨

as a developer who obsesses over security and constraint-driven architecture, i have massive respect for the technical choices you made here:

  1. privacy by design: stripping everything but numeric fields on the server is the exact right way to ensure no prompts or code ever leak.
  2. signed auto-updates: using ed25519 and sha512 integrity checks for a self-updating cli is top-tier, enterprise-grade security. most indie devs skip this, but you treated it as a core feature.
  3. the supabase presence fix: re-reconciling the room every 15s instead of blindly trusting the first event is a classic, bulletproof way to handle realtime state drift. (i use supabase for koda too, so i feel this one deeply!)
  4. the anti-cheat lesson: you nailed it. automated "fairness" that accidentally flags your most active power users is always worse than a simple manual review.

also, the build script that adapts a throwaway html prototype into a next.js app instead of forcing a from-scratch rewrite is peak pragmatic engineering.

keep shipping this. it’s a fantastic tool, and the github readme card is a genius growth loop. 💻✨

Collapse
 
lenchoi profile image
Choi Minho •

Thanks so much Harun! The privacy rule came first, before any pixel art, since it's always the first question devs ask. Curious what you're building with Koda? Would love to take a look.