Project
Catan
Full-stack digital Settlers of Catan: one C# rules engine driving Blazor WebAssembly, MAUI Hybrid, and a SignalR multiplayer server, with dual SVG and Three.js boards.
A from-scratch digital adaptation of Settlers of Catan, built as an end-to-end .NET 10 solution. It runs as a Blazor WebAssembly web app, a MAUI Blazor Hybrid desktop/mobile app (Windows, macOS, Android, iOS), and a standalone ASP.NET Core multiplayer server — all sharing a single rules engine and UI component library.

Architecture
The codebase is structured as eight projects with strict layering:
- A transport- and UI-agnostic GameCore library that owns all game rules — board generation, turn state machine, building/trade/robber/development-card managers, victory calculator
- A shared protocol layer of typed commands and events
- A Razor component library consumed by both the WebAssembly host and the MAUI WebView host
- A thin SignalR server that acts as a pure transport — every inbound message is unwrapped by a hub filter and dispatched through MediatR to handlers that live alongside the rules engine
Dual board renderers
The board is rendered two ways:
- A 2D SVG implementation for fast first paint and accessibility
- A full Three.js scene (~2k+ lines of JS across ~20 modular renderers — tiles, props, harbors, robber, pieces, highlights, animations, camera) interop'd from Blazor for a 3D view with seeded procedural terrain, hit-testing, and animated state changes
Game state is JSON-serialized through custom converters for hex coordinates, vertex/edge IDs, resource bundles, and polymorphic buildings, and survives round-trips between server, clients, and persisted snapshots.
Real-time multiplayer
A single /hubs/catan SignalR endpoint with an envelope protocol — typed commands (CreateLobbyCommand, RollDiceCommand, ProposeTradeCommand, etc.) and events (DiceRolled, BuildingPlaced, TradeProposed, …) are deserialized by a hub filter, routed via MediatR to handlers, and rebroadcast to lobby/game groups managed by dedicated group services.
The same handler infrastructure runs in-process inside the MAUI host for offline single-device "hot-seat" play with no server required.
Composition and testing
Cross-cutting concerns are wired with Autofac modules (GameModule, ClientModule, UIModule, ServerModule) so each host composes only the services it needs. The test project covers ~52 files of unit, integration, and end-to-end tests — including SignalR end-to-end tests that exercise the real hub, real MediatR pipeline, and real serialization stack.
Highlights
- One rules engine, five hosts. The same GameCore assembly drives single-player MAUI, hot-seat play, WebAssembly multiplayer, the SignalR server, and tests.
- Transport-agnostic protocol. Commands and events are plain C# records dispatched by MediatR; SignalR is a thin envelope on top, so the rules engine doesn't know it's networked.
- Dual renderers. A 2D SVG board and a modular Three.js scene (camera controller, animation manager, hit-target builder, mesh factories, prop factory, etc.) share the same hex-coordinate math.
- Hot-seat and online from the same code path. The MAUI build skips the server entirely and runs the multiplayer service in-process for local pass-and-play.
Tech stack
- .NET 10, C# 13 — strict-null, signed assemblies
- Blazor WebAssembly + MAUI Blazor Hybrid (Windows / macOS / Android / iOS / Web)
- ASP.NET Core + SignalR (Newtonsoft.Json protocol, custom envelope hub filter)
- MediatR for command/event dispatch shared across in-process and networked play
- Autofac for modular DI across five hosts
- Three.js for 3D board rendering, SVG for 2D fallback, JS interop from Blazor
- xUnit for unit / integration / end-to-end test layers
- .NET 10
- C# 13
- Blazor WebAssembly
- MAUI Blazor Hybrid
- ASP.NET Core
- SignalR
- MediatR
- Autofac
- Three.js
- SVG
- xUnit