Samuel Anes

Sabacc · Founder and lead developer

Real-Time Multiplayer Card Game

A web app for playing Sabacc, the card game from Star Wars, against other people online. I built it alone, open-sourced it, and brought on developers from across the country. It has served 1,000+ users and is still running.

Live · sabacc.samuelanes.com

2023–present · Solo until April 2024, then a team project

SvelteKit · TypeScript · Python · Flask · Socket.IO · SQLite · PostgreSQL

An eight-player Sabacc game on the current table layout
An eight-player Traditional Sabacc game on the current table.

Overview

Sabacc is played in rounds of drawing, trading, and betting. The site supports three variants, each with its own deck and rules: Traditional, Corellian Spike, and Kessel. Players make an account, host a game with their own settings for antes, blinds, and starting credits, and play with the people they invite. Games are saved as they go, and each one keeps a move history that can be replayed.

Architecture

The front end is SvelteKit, compiled ahead of time, with components that update as game state changes. A Flask backend owns all the game logic and the database. Ordinary requests like logging in, hosting a game, and loading stats go over HTTPS. When a player opens a game, the page joins a Socket.IO room for that game and keeps the connection open.

The server has the final say. When a player acts, the client sends the action, not a new game state. The server checks that the player is in the game, applies the move using that variant’s rules, saves it, and pushes the update to everyone in the room. Nothing polls, and no client can decide how a move turns out.

Diagram: users load the Svelte interface, which calls Flask over HTTPS; live game data flows over WebSockets to Socket.IO; Flask stores data in SQLite
How requests flow. HTTPS carries basic data, and WebSockets carry live game data.

Hidden Information

A card game can’t send the whole game state to every player, because anyone can open the browser’s developer tools and read the WebSocket messages. So an update isn’t one message sent to the whole room. The server builds a separate copy for each connected player, with the deck removed and every other player’s cards blanked out. In Traditional Sabacc, protected cards are played face up, so those stay visible.

The move history gets the same treatment, so replaying a game in progress can’t reveal a hand either. Players see the full record only after the game ends.

Variant Architecture

The first version had one variant and two players. Adding a second variant meant either copying the server or restructuring it, so I rebuilt the backend around classes. Base classes for the card, deck, hand, player, and game hold everything the variants share: turn order, saving to and loading from the database, and the per-player hiding above. Each variant subclasses them with its own phases, legal actions, hand values, and scoring. Corellian Spike and then Kessel were added this way without forking the server.

Database Migrations

The app started on SQLite. When the class-based backend arrived, I moved it to PostgreSQL, whose custom composite types could store cards and players as structured values. Later we moved back to SQLite, because a single database file made cloud hosting simpler and meant new contributors didn’t have to set up Postgres just to run the project.

Both moves happened with real accounts and games in the database. The conversion script loads each game with the old classes, turns it into a plain dictionary, rebuilds it with the new classes, and writes it to the new schema. The migration reuses the code the game already runs on, instead of mapping columns by hand.

Team and Scale

I built the first versions alone and hosted them on a Raspberry Pi. Once I shared the project online, other developers wanted to help, so I started a Discord for players and contributors and moved the code into a shared organization repository. It now has 455 commits, about two-thirds of them mine, and the site runs in the cloud.

Interface Evolution

First version of the Sabacc interface: two colored boxes of text for two players
The first version. Two players, and text only.
Second version of the interface with card images and a pot graphic
More than two players, and the first graphics.
Early poker table layout with players seated around a green table
The first table layout, with every player seated around it.
The mobile layout of a Sabacc game using the Pescado card theme
The current mobile layout, shown with the Pescado card theme. Players can choose card designs, table themes, and dark mode.