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.
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 reusableNavBarreads auth state directly via hooks rather than havinguserprops 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
- 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.