Card Games
A gaming website featuring classic card games with both single-player and multiplayer modes. Users can chat with friends, compete on leaderboards, and enjoy the social aspects of gaming.

Overview
A full-stack multiplayer card games platform built for the ADES (Application Development Enterprise Studios) module at Singapore Polytechnic with a team of five. Each member owned one game; I handled the broader site infrastructure.
The stack is PERN (PostgreSQL, Express, React, Node.js) with Cloudinary for media, Redis for online status, and Socket.io for real-time features.
Features
- Blackjack, Poker, Hearts, and Crazy Eights
- Login, register, Google Sign-In, and reCAPTCHA v2
- Multiplayer, real-time chat, and friend system with live presence
- Leaderboards per game mode
- Admin dashboard to add/update games and users.
What I worked on
- Set up the frontend and converted it to React (compiled via Babel) and built the landing pages, and set up the backend project structure.
- Built login and register — UI, Google Sign-In, reCAPTCHA v2, and backend routes with input sanitisation, bcrypt, and JWT
- Architected online presence tracking with Socket.io and Redis, friend system, and chat
- Developed Blackjack with single-player (vs bot) and real-time multiplayer, including leaderboard
- Set up Cloudinary for image and video hosting
Challenges
Keeping the codebase clean was a challenge throughout the project. With five people working across different parts of the app, it was hard to maintain a consistent coding style, and the file structure kept shifting as the project grew — meaning we constantly had to update each other on where things lived and how new code should be organized.
Reflection
Working in a team of five taught me a lot about collaboration, using GitHub and frequent meetings to stay aligned under deadline pressure. My biggest personal challenge was jumping into new tools without fully reading the docs or planning the implementation first, which caused avoidable rework. Going forward, I want to be more patient, and I'd like to revisit this project to improve the website and address the hosting limitations.
Notes
● Why is it offline?
The project is currently not live. After the module ended, a few hosting providers dropped their free tiers, which broke the deployment — ElephantSQL and Redis both discontinued their free plans. I'm planning to migrate to Supabase and Upstash as replacements, and I'm looking into a better long-term host for the backend.
On the frontend, I've since added Vite for bundling and set up ESLint and Prettier for better code consistency and style.
Screenshots
Under the Hood
Architecture
The application uses the PERN stack. The frontend is built with React, compiled via Babel, and hosted on Netlify. The backend is powered by a ExpressJS and SocketIO deployed on Render (migrated from Heroku after its free tier ended).
Data is stored in a Supabase PostgreSQL database (migrated from ElephantSQL after its free tier ended), while temporary real-time user presence states are managed via Upstash (migrated from Redis). Both migrations have been tested locally but are not yet deployed. Continuous delivery is handled directly via GitHub webhooks linked to both Netlify and Render.
Technical Deep Dives
Blackjack multiplayer using Socket.IO
To implement multiplayer in Blackjack, we use Socket.IO on the backend. The client sends the relevant data to the server so that the server can create the game state. Once the game starts, all the client needs to do is send the player's move, and the server will calculate the outcome and draw the cards before broadcasting the updated state to everyone. This approach prevents clients from cheating, and also allows us to control what cards are shown and what values are hidden from each player.
Online Status Using Redis
When I first implemented the online status feature, it was stored as a variable inside the backend server. I soon realized this approach was not scalable — not that it particularly mattered for a small project, but I wanted to learn how a real-world production app would handle it. This led me to explore Redis. Redis stands for Remote Dictionary Server and is a key/value NoSQL database that stores its data in memory, meaning data is lost if the server restarts. This makes it well-suited for volatile data such as online status.
Chat System (Socket.IO and DB)
The chat system handles messages in two simple steps:
- Real-time: When a user sends a message, it is instantly delivered to everyone in the room through Socket.IO, so there is no waiting.
- Saving: At the same time, the message is saved to the database in the background so that chat history is not lost.
Process
For this ADES project, we started by brainstorming ideas before deciding on a card game website, as it allowed each of us to work on our own game.
We used Figma to create wireframes and prototypes before starting development. For CA1, we were required to build the website using plain HTML, JS, and CSS only.
For CA2, we were encouraged to convert our code to React to learn how it works and understand that it is essentially a layer of abstraction built on top of plain JavaScript.
We also expanded the project by adding multiplayer, a chatting system, and many more features such as Google Sign-In and reCAPTCHA.
- Brainstorm website ideas
- Wireframe and Prototype using Figma
- CA1: Code Plain HTML, JS, and CSS — building of core games
- CA2: Convert to React and add more features (Multiplayer, Chat etc)