Redis Pixel War



This content originally appeared on DEV Community and was authored by Alfredo Salzillo ?

This is a submission for the Redis AI Challenge: Beyond the Cache.

What I Built

Redis Pixel War is a live, collaborative “pixel war” built on Next.js where anyone can paint single pixels on a 100×100 canvas. It showcases Redis 8 as a multi‑model, real‑time platform rather than just a cache. Every pixel change is persisted, broadcast to all connected clients, and recorded for history and stats.

Highlights:

  • Real‑time updates to all clients via Server‑Sent Events (SSE) powered by Redis Pub/Sub.
  • Durable primary storage of the canvas in Redis Hashes.
  • Presence tracking (who’s online) with Redis Sorted Sets and a Users Hash.
  • Audit/history of changes with a Redis Stream to enable time‑travel/replay or analytics.
  • Leaderboards and per‑user stats computed from Redis data.

Stack: Next.js (App Router), TypeScript, MUI, Redis 8 (node-redis).

Demo

Screenshot 1

Code

Redis Pixel War

A live, collaborative pixel war showcasing Redis as a multi‑model platform:

  • Primary storage: Redis Hash stores pixel colors.
  • Real‑time: Redis Pub/Sub broadcasts pixel updates consumed by Server‑Sent Events (SSE).
  • History/Audit: Each update is appended to a Redis Stream.
  • Presence: Redis ZSET + HASH track who is online and their display names.

Built with Next.js (App Router) and MUI.

Getting Started

  1. Prerequisites:

    • Node.js 18+
    • A Redis instance (local or hosted). Set REDIS_URL env var like redis://localhost:6379.
  2. Install dependencies:

    • npm install
  3. Run the dev server:

    • REDIS_URL=redis://localhost:6379 npm run dev
  4. Open the app:

How it works

  • Storage
    • Key canvas:colors (Hash): maps pixel index to hex color. The pixel index is computed as idx = y * WIDTH + x.
    • Key canvas:owners (Hash): optional mapping from pixel index to the userId who last painted it.
  • Real‑time updates
    • Pub/Sub channel canvas:updates

How I Used Redis 8 (Beyond Caching)

Redis is the system of record for the app and is used across multiple data models:

1) Primary storage (Hash)

  • Key canvas:colors stores pixel color by index: HSET canvas:colors <idx> <#hex>.
  • Key canvas:owners optionally stores the user who last painted each pixel.
  • Bootstrap endpoint GET /api/bootstrap uses HSCAN to stream initial colors to the client.

2) Real‑time messaging (Pub/Sub + SSE)

  • Channel canvas:updates publishes every pixel change as JSON { x, y, idx, color, userId, at }.
  • Server subscribes and relays messages to browsers via SSE at GET /api/stream with event type pixel.
  • A lightweight presence SSE event nudges clients to refresh presence periodically.

3) Presence (ZSET + HASH)

  • ZSET presence:online stores last‑seen timestamps (score = ms since epoch, member = userId).
  • HASH presence:users maps userId -> display name.
  • POST /api/presence/heartbeat updates ZSET and (optionally) the name in HASH.
  • GET /api/users/online prunes stale users (older than 30s) and returns the current online list.

4) History/Audit (Stream)

  • Stream stream:canvas receives an entry per pixel change (x, y, idx, color, userId, at).
  • This enables later analysis, replay, or moderation if needed.

5) Stats/Leaderboards

  • GET /api/users/top calculates top painters by scanning canvas:owners and enriching names from presence:users.
  • GET /api/users/me?id=... returns per‑user counts and board percentage.

Why Redis 8?

  • Combines multiple capabilities (Hashes, Pub/Sub, Streams, Sorted Sets) in one low‑latency system.
  • Simplifies architecture: no separate DB, broker, and metrics store — Redis handles them all.
  • Fast HSCAN and pub/sub deliver a snappy UX even as the board grows.

Architecture

  • Frontend: Next.js (App Router) + MUI; HTML5 Canvas for pixel rendering.
  • Backend: Next.js API routes.
  • Realtime: SSE endpoint subscribes to Redis Pub/Sub.
  • Data: Redis 8 as primary data store and event bus.

Credits

  • Solo project for the Redis AI Challenge.

Last updated: 2025-08-10.


This content originally appeared on DEV Community and was authored by Alfredo Salzillo ?