Guess The Word
A real-time multiplayer word guessing game
Overview
Guess The Word is a real-time multiplayer word guessing game where players take turns guessing a word until they come to an agreement.
Features
- Real-time multiplayer gameplay using WebSockets
- Responsive design that works on desktop and mobile devices
- Player authentication using Supabase
Tech Stack
SvelteKit & Svelte
Svelte is a new rendering library that was created at The Guardian and was ranked as the most admired web framework in Stack Overflow’s 2024 Developer Survey.
SvelteKit is the server-side part of Svelte that enables Server Side Rendering, REST APIs, etc.
Svelte is part of a new breed of web frameworks that compile component source code down into JavaScript, instead of being a pure JavaScript library. Svelte’s popularity is why React is introducing the React Compiler.
Being a web framework in the 2020s, Svelte is also keenly aware of the need for Server Side Rendering and its interplay with Client Side Rendering. SvelteKit very explicitly models where data loading is happening: server-only, client-only, or both. This explicit modeling of the data loading lifecycle introduces some interesting problems.
I had a lot of trouble understanding how to perform authentication, because knowing where to store the JWT token and when to trust it were mental models I didn’t have before. In the end, I went with server hooks, storing the auth details in locals
, then performing server-side loading of a user’s credentials every time they navigate to a page that needs authentication. I couldn’t trust the JWT token in the Authorization
header handed to me from the client-side, because the client could have modified it. The Lucia guide was incredibly helpful in understanding how to set up authentication.
WebSockets
Socket.io is the WebSockets implementation of choice for this project.
Originally I wanted to use Spring’s STOMP support with a Kotlin backend. Unfortunately, the STOMP.js library isn’t really well-known in the JavaScript ecosystem; this is probably a reflection of how STOMP is mostly a messaging middleware integration, and that usually happens in the backend. I also got tired of having to duplicate the message object models on both Kotlin and JavaScript sides, and other constraints in this project compelled me to look for a pure JavaScript solution. You can still find the original Kotlin backend here.
Node.js & Express.js
An Express.js server in the backend provides:
- RESTful API endpoints for game creation and deletion
- Socket.io server to manage game state
- User authentication and session management
The server talks to Supabase, an open-source Firebase alternative. Supabase allowed me to use standard Postgres instead of proprietary constructs only available in Firebase.
Games are created by making an entry in the Games
table, and only events from authenticated users can trigger the server to create it. After a game ends, the entry is deleted.
Originally, the plan was to store finished games and then run some kind of analytics on them. I quickly realized that not enough people would be playing the game, so any kind of analytics generated would be overkill. Maybe one day I’ll get around to it.