consequences
An online multiplayer version of the classic paper party game where players take turns writing answers to prompts without knowing what others wrote, then revealing the resulting stories together.

Description
Consequences is an online multiplayer version of the classic paper party game where players take turns writing answers to prompts without knowing what others wrote, then revealing the resulting stories together. Players join via a room code, customize a little avatar, and play through rounds of writing before a reveal phase where the stories are read out line by line.
This one actually has a history, it first appeared in my graveyard of dead projects back in February 2024. The original idea included AI-generated images at the end of each story, but free image generation wasn't good enough at the time and the cost per game didn't make sense. I always wanted to come back to it though, and after playing an online version of STOP with some friends I remembered the idea, stripped out the AI image generation part, and wrote it up in a weekend.
The game supports 2-10 players per room, optional round timers, bilingual prompts (English and Spanish), and a custom avatar creator that ended up being one of my favorite parts of the project. No accounts, no login, you join, you play, you leave. There's no reason to store anything past the game.
This one actually has a history, it first appeared in my graveyard of dead projects back in February 2024. The original idea included AI-generated images at the end of each story, but free image generation wasn't good enough at the time and the cost per game didn't make sense. I always wanted to come back to it though, and after playing an online version of STOP with some friends I remembered the idea, stripped out the AI image generation part, and wrote it up in a weekend.
The game supports 2-10 players per room, optional round timers, bilingual prompts (English and Spanish), and a custom avatar creator that ended up being one of my favorite parts of the project. No accounts, no login, you join, you play, you leave. There's no reason to store anything past the game.
Technologies
This is a departure from my usual stack. The whole thing is built with Elixir and Phoenix LiveView, which I'd been wanting to try for a while. Even though the project was small, the fit felt perfect. LiveView handles all the real-time UI updates over WebSockets without me having to manually manage socket connections or figure out how the UI should respond to state changes. Everything felt baked in and ready to go. I leaned on the canonical Phoenix way of implementing rooms and layered my game logic on top of that.
The game state lives entirely in memory via GenServers, one per room, supervised by a DynamicSupervisor. No database, completely intentional. I didn't want the hassle of deploying and managing a database for something that's inherently ephemeral. Rooms auto-terminate after 2 hours of inactivity.
For the avatar system, I wanted something like Gartic Phone's avatars. I looked for libraries to do it but couldn't find a great fit. I ended up using facesjs, limiting it heavily, no body, no accessories, zoomed way in so the face shapes get lost, which made them look more cartoony. Since I'm not much of an artist, I extended it with extra eye, nose, and mouth SVGs that I generated with Gemini, plus some fun skin colors beyond the realistic palette.
The frontend styling uses Tailwind v4 with daisyUI. I wanted to explore a different visual direction, more cartoony and playful to match what the app is about. I've been doing some work on my portfolio that I'm happy with, but it didn't make sense to use a more refined or serious aesthetic here. Bold outlines, rounded typography, hand-stamped offset shadows. Fun over polish.
Deployed on Railway, which was a first for me and a surprisingly great experience.
The game state lives entirely in memory via GenServers, one per room, supervised by a DynamicSupervisor. No database, completely intentional. I didn't want the hassle of deploying and managing a database for something that's inherently ephemeral. Rooms auto-terminate after 2 hours of inactivity.
For the avatar system, I wanted something like Gartic Phone's avatars. I looked for libraries to do it but couldn't find a great fit. I ended up using facesjs, limiting it heavily, no body, no accessories, zoomed way in so the face shapes get lost, which made them look more cartoony. Since I'm not much of an artist, I extended it with extra eye, nose, and mouth SVGs that I generated with Gemini, plus some fun skin colors beyond the realistic palette.
The frontend styling uses Tailwind v4 with daisyUI. I wanted to explore a different visual direction, more cartoony and playful to match what the app is about. I've been doing some work on my portfolio that I'm happy with, but it didn't make sense to use a more refined or serious aesthetic here. Bold outlines, rounded typography, hand-stamped offset shadows. Fun over polish.
Deployed on Railway, which was a first for me and a surprisingly great experience.
Things Learned
The biggest takeaway was about learning with AI tools. I'm used to using agentic coding, but mostly with tech I already understand. Using it to learn something from scratch was a different experience, the AI would just gloss over things and get them right without me understanding the why behind the decisions. It made me realize that AI assistance is much better as a force multiplier for things you already have a foundation in than as a tool for going from zero to one. I had to actively put myself in a learning mood at times rather than defaulting to "get the thing working" mode.
On the tech selection side, I spent real time evaluating options, LiveView vs Convex vs hand-rolled WebSocket support, and choosing deliberately rather than defaulting to whatever I'm most comfortable with. That felt good. This is also my first real-time multiplayer app, so there were a bunch of things to figure out around connection handling, host handoff when someone disconnects, and making sure the game keeps moving even when players drop (the game fills in default answers for disconnected players).
On the tech selection side, I spent real time evaluating options, LiveView vs Convex vs hand-rolled WebSocket support, and choosing deliberately rather than defaulting to whatever I'm most comfortable with. That felt good. This is also my first real-time multiplayer app, so there were a bunch of things to figure out around connection handling, host handoff when someone disconnects, and making sure the game keeps moving even when players drop (the game fills in default answers for disconnected players).
Gallery









