🚀 Inspiration
We've always been huge fans of Reddit's r/place. The co-operation, the chaos, the spontaneous creation of art... it's magical. We wanted to capture that same energy but add a twist. Our core idea was, "What if the canvas fought back?"
This led us to create Pixel Canvas Defense. It's not just a blank canvas; it's a game where the community has to unite not just to create art, but to defend it from a constant, real-time "glitch" mechanic that tries to erase their work. It's creation with a shared purpose.
🎨 What it does
Pixel Canvas Defense is a real-time, collaborative pixel art game with a built-in enemy.
- Paint: Anyone can select a color and place a pixel on the shared 50x50 canvas.
- Defend: A server-side "glitch" mechanic constantly attacks, erasing random clusters of pixels. The entire canvas even shakes to warn everyone when a big "wave" of decay hits.
- Collaborate: You see everyone's pixels (and the glitch's decay) appear live without needing to refresh. The community has to work together to repaint and maintain the art.
🛠️ How we built it
We built this using the Devvit Web platform. The entire app is built in React and TypeScript.
Frontend: The client is a single React app.
App.tsxis the "brain". It manages the singleconnectRealtimeconnection, calculates the dynamic pixel size, and holds all the app's state (like the canvas data, cooldowns, and stats).Backend: We used Devvit's built-in Node.js server to create our API. We have
/api/initto load the canvas and/api/paintto handle new pixels.Database & Real-time: Devvit's built-in Redis was the MVP. We use it for everything:
canvas:main(Hash): Stores the entire canvas state (color and owner).cooldown:[username](Key): Stores a user's cooldown timestamp, enforced on the server.nextGlitchTime(Key): A global timestamp for the next decay event.
Real-Time: We use a single
connectRealtimecall inApp.tsxthat listens for all message types (paint,decay,presenceUpdate). It updates the central React state, which then flows down to all components, keeping everything in sync.
🧠 Challenges we ran into
We hit some major walls that forced us to learn and adapt.
The Serverless Timer: Our biggest "oh no" moment was when our decay timer (
setInterval) crashed the server with aNo context founderror. We learned the hard way that the Devvit server is serverless and you can't have persistent timers. We had to completely refactor our logic into a "lazy"checkAndRunDecayfunction that runs inside a user's API call. This was a huge paradigm shift.Real-Time Not Working: For the longest time, we couldn't see other users' pixels. We were debugging for ages before realizing we had two
connectRealtimecalls in different components. We had to refactor everything to use a single connection inApp.tsxas the single source of truth.
🏆 Accomplishments that we're proud of
We're honestly just thrilled that it all works.
- The Responsive Grid: Seeing the grid perfectly resize to fit any screen (desktop or mobile) felt like a huge win. It's compliant with the rules and looks great.
- The Mod Template Feature: We're really proud of this. A mod can start a new game by simply clicking a menu item and pasting an image JSON. The app then processes that on the client-side and renders it as a template. It's a really cool, user-friendly way to set a community goal.
- The "Feel": Adding the "blip" sound on paint, the "flash" feedback, and the full-screen "shake" when the glitch attacks made it feel like a real, polished game, not just a tech demo.
📖 What we learned
This was a crash course in building for a serverless, real-time platform.
- Think Serverless: You can't just
setInterval. Your backend logic must be stateless and run inside a request. This changed how we designed our core game loop. - State Management is King: In a real-time app, having a single source of truth is non-negotiable. Consolidating our real-time logic into
App.tsxsolved all our state-syncing bugs. - Devvit is Powerful: The built-in Redis and Realtime services are incredibly powerful. We built a complex, persistent, multiplayer app without ever provisioning a database or a websocket server.
🔮 What's next for Pixel Canvas Defense
This was a blast. If we had more time, we'd love to:
- Expand Mod Tools: Let moderators set the
DECAY_INTERVALorCOOLDOWN_SECONDSthemselves via the settings. - Bigger Canvas: Scale up to 100x100 or more (though this would need more performance tuning!).
- Persistent Leaderboards: The app already tracks stats, but we'd love to build a persistent "All-Time Top Defenders" leaderboard that lives across multiple posts.
Built With
- css
- devvit
- html
- javascript
- node.js
- react
- redis
- tailwind
- typescript

Log in or sign up for Devpost to join the conversation.