Inspiration

Most "daily" browser games — Wordle-likes, daily puzzles — are solitary. You play, you see your own result, and that's it. Reddit's entire identity is community, not solo play, so we wanted a daily game where the shared result is the whole point: something a subreddit builds together, where showing up (or not) visibly changes what everyone else sees. A collaborative pixel canvas was the simplest way to make "coming back" a communal act instead of a personal habit.

What it does

Streak Wall gives a subreddit a fresh pixel-art grid every day, built around a community-voted theme. Each player gets a small number of tiles to paint, refilled on a drip (one every 15 minutes once you run out) so there's a reason to check back multiple times a day, not just once. Painted tiles slowly fade if the community goes quiet, so the wall's vibrancy is a live signal of how active people have actually been. A hidden target pattern gives the community something to paint toward together, XP and levels reward individual contribution, streak badges (First Stroke, 10-Day, 25-Day, 100-Day) reward long-term return visits, and a wildcard color slot lets players mix a custom shade for a limited 15-minute window when the fixed palette isn't enough. Anyone can suggest tomorrow's theme, and the top-voted suggestion wins — so the community drives its own content, not just its own art.

How we built it

Streak Wall is built on Devvit Web, Reddit's platform for interactive posts. After early attempts to hand-build a scaffold from documentation alone kept failing at deploy time, we switched to starting from Reddit's official Devvit "Bare" template, which gave us the correct build configuration out of the box.

The architecture is a clean client/server split. The server runs on Node's raw http module (via @devvit/web/server's createServer/getServerPort) rather than a framework, with Redis handling all persistent state — mosaics, tile counts, streaks, badges, XP, leaderboards, and the live activity feed. The client is vanilla TypeScript compiled by esbuild, with the mosaic grid drawn directly on an HTML Canvas — no game engine. A single shared types file (src/shared/api.ts) is the contract between client and server: tile shapes, mosaic state, badge definitions, XP constants, and endpoint names all live there so both sides can never drift out of sync.

Decay is computed server-side on every read rather than stored — each tile's placedAt timestamp is mapped through a decay function that returns an alpha value the client uses directly as canvas opacity, so tiles never disappear, they just dim until repainted. XP uses a square-root leveling curve (level = floor(sqrt(xp / 50)) + 1) so early levels come fast and later ones take real commitment. The splash screen and full game screen are separate compiled entrypoints, and the splash's pixel-art tree background is generated procedurally from a seeded PRNG rather than a static image, so the generation logic itself could be unit-verified independent of any canvas or browser.

Challenges we ran into

The single biggest recurring issue was TypeScript's noUncheckedIndexedAccess strictness combined with a fast-moving codebase: array/record lookups that looked safe kept surfacing as T | undefined, and a few of these slipped through into a merged PR before being caught, which silently broke the production build — meaning the app kept running on a stale bundle while we thought new features were live. That taught us to always run a real tsc --build and a real esbuild bundle before trusting that a change had landed, not just eyeball the diff.

We also hit a subtler bug: an early version of the dark/light theme toggle used localStorage for persistence, which is inaccessible inside Reddit's sandboxed iframe. Because that call wasn't defensively wrapped, it silently prevented the whole toggle's click handler from ever attaching — the button was visibly present but did nothing, which took real digging to trace back to a storage-access exception rather than a CSS or logic bug. The fix was to accept that theme resets to dark on every load, which turned out to be the right call for this environment anyway, not just a workaround.

Beyond that: getting Redis-backed daily resets, decay, and per-user rate limiting to all agree with each other under concurrent multi-player writes took care, and reconciling a scoring/pattern system that needed to support both a small hand-authored shape library (6–11 tiles) and an unlimited procedural fallback for higher levels meant designing two different generators that had to produce provably exact tile counts every time — verified in isolation before ever touching a canvas.

Accomplishments that we're proud of

Getting a real, live post running in an actual Reddit feed — not a local mockup — with dynamic state (today's theme, painted percentage, active-player count) rendering correctly is the one we're proudest of. It proves the full loop works end to end: grid creation, Redis state, decay, canvas rendering, and the feed entrypoint all talking to each other correctly on a real subreddit. We're also proud of catching and fixing real production bugs (the stale-build issue, the iframe storage issue) by verifying against the actual deployed repo rather than assuming our local view of the code was still accurate.

What we learned

We learned Reddit's Devvit Web app model in real depth — how entrypoints, scheduled jobs, and the client/server split actually work in production, not just in the docs. We learned that iframe-embedded apps have real, non-obvious platform constraints (storage access chief among them) that only show up once you're testing inside the real host, not in a standalone browser tab. And we learned to treat "it compiles" and "it's actually the code that's deployed" as two separate questions worth checking independently.

What's next for Streak Wall

  • Finish wiring the pattern-matching completion bonus and wildcard color timer into the live Redis state
  • Add a decay-archive gallery so each day's finished (or unfinished) mosaic isn't lost when the next one begins
  • Polish mobile responsiveness further, since judges review on desktop but mobile-friendliness is a scoring bonus
  • Submit the app listing, demo post, and Developer Platform feedback survey ahead of the deadline

Built With

Share this project:

Updates

Submission history