Skip to content

Pixel World — A Creative Pixel-Art Community, Built on a Strict MVP Architecture

The Pixel World game world

Pixel World is a web application where people create and share pixel art. Users explore a 2D world, receive a “quote of the day” as inspiration, and paint on a 16x16 canvas. Finished paintings — with their quote and a personal description attached — go up in a shared Museum where others can browse, like, and comment in real time. The in-world weather even mirrors the user’s actual local weather via geolocation.

Built with a four-person team in the DH2642 Interaction Programming course at KTH, together with David Segal, Krisztina Biro, and Gabi Kiryluk.

🔗 Live app · GitHub

What I Did

I was responsible for the application architecture: designing and implementing the Model-View-Presenter (MVP) structure, the Redux state management, and the integration between the React app and our custom P5.js game engine. Concretely:

  • Strict MVP separation. Views are pure functional components that receive everything through props; presenters (container components using React Redux’s connect) map state and actions to them; the model lives entirely in Redux Toolkit slices. We allowed exactly one documented exception — the reusable NavBar reads auth state directly via hooks rather than having user props threaded through every page.
  • Bridging Redux with a game engine. The world view isn’t ordinary DOM — it runs on a custom micro game engine (built by David) with its own render loop, wrapped in P5.js. I designed the communication layer so the engine stays in sync with the app: Redux state flows in as props through the P5 react wrapper, and the engine triggers custom events that dispatch back into the store. The engine keeps its own frame-by-frame state; Redux remains the single source of truth for everything that matters.
  • Refactoring slices from pages to features. We initially created one Redux slice per page, which quickly led to duplicated painting logic across the museum, detail, and profile pages. I led the refactor to feature-based slices — merging three page slices into a single paintingsSlice — which removed the duplication and made cross-page state (like a selected painting) natural instead of awkward.
  • Real-time sync as middleware. Likes and comments update live across clients. Rather than scattering Firebase listeners through components, I put them in RTK listener middleware: one middleware manages Firebase subscriptions (attaching and detaching them as users select paintings or log in/out) and dispatches actions when remote data changes; another handles painting-related side effects like persisting work-in-progress to Firebase. Components stay clean — they just read state.

How It Works

Welcome page Quote board
  • Quote of the Day — a daily quote (with limited refreshes per day, tracked per user in Firebase) inspires each painting; users can attach one quote to their artwork.
  • Pixel editor — a 16x16 canvas with pencil, eraser, fill, a color palette, and undo/redo.
  • Museum — a gallery of everyone’s paintings with a hall of fame for the three most liked, plus real-time likes and comments.
  • Dynamic weather — the world’s weather reflects the user’s real geolocation, fetched from the SMHI weather API.
  • Persistence — paintings, unfinished work, quotes, likes, and comments are stored in Firebase, with authentication via email/password or Google sign-in.

Tech Stack

React, Redux Toolkit (with listener middleware), React Redux, React Router, Firebase (auth, Firestore, hosting), Tailwind CSS, Material UI, P5.js with a custom component-based micro game engine, and Vite.

Reflection

The most valuable part of this project was proving that architectural discipline pays off even in a small team on a deadline. Because views never touched the store directly, we could redesign pages without touching state logic, and the slice refactor mid-project was painless precisely because the boundaries were clean. Integrating an imperative game loop into a declarative Redux world was the trickiest design problem — the props-in, events-out contract we landed on kept the two worlds from leaking into each other, and it’s a pattern I’d reach for again.