How we built Table Online — a multiplayer backgammon game in Flutter for web, iOS and Android
Engineering lessons from building a real-time game in Flutter, with the same code running in the browser and natively on mobile. State management, server sync, 60fps performance.
A few months ago we shipped Table Online — a classic multiplayer backgammon game you can play directly in your browser at table-online.ro, or as a native app on iPhone and Android. All of it is built in Flutter, with a single source codebase for all three platforms. This article is an engineering look behind the scenes.
Why Flutter for a multiplayer game
The choice wasn’t obvious. For games, many people reflexively recommend Unity or a custom engine. We picked Flutter for three concrete reasons:
- Animations are first-class in Flutter.
AnimationController,AnimatedBuilder,Hero,TweenAnimationBuilder— all motion data for backgammon pieces and dice is already solved by the framework. We didn’t have to write a physics engine. - The web lets you adopt without downloading. The biggest friction in mobile game adoption is installation. With Flutter web, the user lands, taps twice, plays a game. If they like it, they install the app later.
- One codebase, three platforms — and this isn’t just a marketing line. Game logic, move validation, server communication — they all live in the same file and behave identically everywhere.
Architecture
In short:
- Flutter frontend — UI, animations, local input. State management with Riverpod.
- Dart server on Cloud Run — the game authority. Every move is server-validated; the client only proposes.
- WebSockets for sync — one persistent connection per match, protobuf-style messages to save bandwidth.
- Firestore for persistent state — user profiles, match history, leaderboard.
The decision that mattered most: the server is source-of-truth. The client proposes a move, the server decides if it’s valid, then broadcasts the result to both players. This eliminates an entire class of cheating and makes debugging predictable.
Performance: holding 60fps in the browser
Flutter web is harder than native mobile on the performance front. A few things made the difference:
RepaintBoundaryaround the board — we isolate board repaints from the rest of the UI. Moving a piece doesn’t repaint the score.- HTML renderer for text-heavy pages, CanvasKit for the game page — Flutter web supports two renderers and you can pick per build. For the game page, CanvasKit wins clearly.
- Lazy loading assets — piece textures, sounds, victory animations only load when needed.
The most useful lesson
If I were starting over, I’d start with the web variant before mobile. It’s harder (Flutter web has fewer tools and more edge cases), but it forces correct architectural decisions early — bundle size, lazy loading, image optimization. The same decisions make the mobile build better later.
Want to discuss a Flutter project? Get in touch — we reply within one business day. And if you want to see the result in action, hop on table-online.ro and play a round.