Creating a 2D React match replay tool for PUBG - Part 1

Playerunknown’s Battlegrounds (PUBG) is a popular online Battle Royale game where 100 people parachute to an island, search for weapons and items, and fight to be the last man standing. The game developers provide a public API, and one of the endpoints provides telemetry data of every game that’s played. The data is rather good and guarantees at least one player datapoint per 10 seconds, which enables rendering this:

[IMAGE HERE]

In this blog series, I’ll be walking through the entire frontend and backend codebases as well as how the application is deployed. This was a fun project to build, and I’m enjoying maintaining and improving it. Although I haven’t marketed it anywhere aside from a Reddit post months ago, the site continues to receive just over 1,000 unique visitors daily along with several pull requests and collaboration. (The project is available on GitHub)

Overview

The backend is effectively a large caching layer on top of PUBG’s APIs that pulls out relevant data and surfaces it to the client via GraphQL using Apollo and Hapi. It never requests the same data from PUBG twice, and I expire the data from my PostgreSQL database as it’s expired from PUBG’s API in a background worker - this keeps the size down and ensures we never guide the user to an irretrievable match.

Once the user’s chosen a match, the remainder of the interaction happens on the client side - telemetry data itself is provided via a separate endpoint, and it’s only ever retrieved by the client. After parsing the raw telemetry data in a web worker, we render the match using canvas via konvajs/react-konva. I have a high bar for performance, and part three will include my path to reaching a constant 60fps during playback.

The final part in the series will discuss how the application is deployed (GitHub webhooks) and served (nginx / Docker). It’s a simple and developer friendly CI/CD pipeline, and has been the perfect solution for a small single developer project.

Up next

Head on over to Part 2: GraphQL backend for the short and simple API story.