Lawrence Plante
← ./all-work

SCRAPT game server

Built

my 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

WS + REST

SCRAPT game server

NestJS on Fastify · Prisma · Redis

3 auth guards · run validation

10 Prisma models: the game economy

server only

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.