The backend and the data¶
One service holds all of Kacky's truth: the backend, a .NET / ASP.NET Core app (src/KackyGG.Api).
Everything a player sees — a record, a rank, whether a server is live — is a value the backend
decided and stored. Nothing else gets to be the authority.
What it stores¶
The backend keeps the core things in a PostgreSQL database, through EF Core. The handful of entities you actually need to know:
- Event — one edition's batch of maps, with its type, start, and end.
- Map — a single Kacky map. Its real identity is the map's UID, not its number (numbers aren't unique across families).
- Player — someone who plays in-game, optionally linked to a website account.
- Finish — every completion. One row per time crossed.
- Record — a player's best online time on a map in an event.
How they hang together:
Event ─* EventMap *─ Map (an event's maps)
Map ─* Finish *─ Player (every completion)
Map ─* Record *─ Player (best online time per event)
Finish and Record look similar and aren't — that split is the thing people trip on, and Records vs Finishes owns the full story.
How it serves everything¶
The backend talks to the world three ways:
- REST — the website and admin panel read and write over a normal HTTP API.
- SignalR — live pushes (server status, updates) so the site doesn't have to keep asking.
- Redis Streams — it consumes what the in-game controllers report and writes it to the database.
The frontends don't hand-write their API code. They generate it from the backend's OpenAPI spec, so when the backend's shape changes, the clients regenerate to match — they can't quietly drift out of sync.
Where the rules live¶
Rank cutoffs, what counts toward which edition, which times are trustworthy — that logic lives in the backend, in one place, not scattered across each client. A client asks; the backend answers with the one true version. That's the whole point of a single source of truth: there's no second opinion to disagree with.