SCRAPT game server
Builtmy code, end to end
The authoritative backend that makes a game economy impossible to forge
SCRAPT was the fourth product in the Dark Oak line: a Unity 6 game rebuilt to run on the Nexus platform we had extracted from our own earlier work. I wrote the server that sits between them, and it is the engineering I would most want to be judged on.
Role
Personal build · 100% my own code
Timeline
2024 – 2025 · Dark Oak Studios
Stack
- TypeScript
- NestJS
- Fastify
- Prisma
- PostgreSQL
- Redis
- WebSockets
- OpenAPI
- React
- pnpm workspaces
The problem
A game client you do not control cannot be trusted with an economy. If the client tells the server what a player earned, then anyone running a modified build can mint currency, forge run results, or grant themselves items. Once that happens in a live economy you cannot unwind it, because the fraudulent balances are indistinguishable from real ones.
The earlier products in this line had the same exposure. Junction distributed real on-chain assets, so a client that could lie about its own rewards was not a theoretical problem. Solving it properly, once, in a place both the game and the platform could rely on, was the point of this build.
The approach
I put an authoritative server in the middle and made it the only path to the platform. The client opens a run, emits events during it, and closes it, and each of those passes through a validated endpoint with a typed DTO. Rewards are never accepted from the client. They are computed server-side against the run record and granted from there.
The data model does the heavy lifting: ten Prisma models covering users, progress, inventory, items, recipes, bounties, bounty claims, runs, run events and reward grants. Because the economy is fully described in the schema, validation is a question the server can always answer.
Three separate guards split the surface: a player auth guard on the game endpoints, an admin API key guard on the tooling, and a content read guard for the static game data. Session tokens are stored as ciphertext rather than plaintext or a plain hash, with an output sanitiser so tokens never leak through a response.
How it fits together
Unity 6 client
renders and inputs only
never trusted
SCRAPT game server
NestJS on Fastify · Prisma · Redis
3 auth guards · run validation
10 Prisma models: the game economy
Nexus platform
rewards · commerce · payouts
PostgreSQL + Redis
authoritative state
The client never reaches the platform directly. That is the whole design.
Shape of the codebase
108
TypeScript & Prisma source files
pnpm workspaces monorepo
10
domain modules
auth, runs, inventory, crafting, bounties, content, nexus, redis, prisma, health
10
Prisma models
the full game economy
3
layered auth guards
player, admin API key, content read
What else is in there
A WebSocket session channel for realtime state, Swagger and OpenAPI docs generated from the DTOs, class-validator on every input, a global HTTP exception filter so errors are consistent rather than leaky, ioredis for caching and session state, and Jest for the test suite.
Alongside the API there is a React and react-router admin and debug console for inspecting runs and inventory, and a shared contracts package so the client and server compile against the same TypeScript types instead of drifting apart.
My role
Every line of this service is mine. I designed the schema, wrote the modules, built the guards, wrote the admin tooling and documented the API.
The Unity game itself is not mine and I do not claim it. The gateway is. If you want to see how I think about trust boundaries, data modelling and API design, this is the artifact to ask me about.
Want to talk through how this was built?
I am happy to walk through the decisions, the parts that did not work, and what I would do differently. Email is the fastest way to reach me.