When I landed the website gig for my company, it was not because I had some official “Director of Web” title. We had already paid a contracting agency a frankly painful amount of money to redesign the entire site. When they finally showed us the “new” version, our entire C-suite basically laughed them off the call. It looked like an old GeoCities page with a spinning logo and almost nothing else that felt modern or on brand.
At that point the money was already gone, so leadership figured there was not much to lose by letting me take a crack at it. Worst case, we fall back to the site we already paid for. Best case, the internal IT guy strikes gold.
In one of our earlier calls, our CEO had mentioned that he loved old retro 8-bit style games and had even asked the agency to hide a little easter egg somewhere. They never did it. So when I started rebuilding the site myself, I decided to actually deliver on that ask.
The result is this little canvas game in the footer. On the surface, the footer just says “hover the bar to play.” When you do, the Zyston logo breaks apart into pixels and turns into a tiny survival game. It is a nod to the CEO’s 8-bit nostalgia, it fits the cyber / threat theme, and it quietly shows that the website is not just a template someone dragged together. It is custom, and it was built by someone who knows how to ship real features end to end.
When I built this “Packet Stream Sorter” widget, the idea was to show what “high volume ingest” actually feels like instead of just writing another line of marketing copy about it. The main page talks about pulling in alerts from O365, firewalls, endpoints, and cloud, so this mini-game takes that concept and turns it into a little conveyor belt where you literally drag packets into the right intake lanes. It keeps the same dark Zyston aesthetic, but underneath it is a fully custom HTML5 canvas app that tracks routes, errors, and rolling efficiency, so it doubles as a fun easter egg and a subtle visual metaphor for what the platform is supposed to be doing.
On screen you get a card with a top bar that reads “High-Volume Ingest — Packet Stream Sorter,” a throughput bar that fills based on your efficiency, live stats like “X routed” and “Eff Y%,” and the canvas doing all the heavy lifting. Colored packets roll in from the left across a glowing conveyor, each labeled as O365, Firewall, Endpoint, or Cloud. You can grab a packet and drag it into the matching lane at the bottom, or you can use keys 1 through 4 to route the furthest packet that has crossed a certain “gate” line on the belt. If you get it right, the lane flashes a soft green and your routed count and efficiency go up. If you miss or let a packet fall off the right edge, the lane flashes red and your efficiency drops, and the throughput bar shrinks accordingly.
Technically, the whole thing is wrapped in an IIFE so it does not leak anything into the global scope of the page. The canvas is sized based on the .card container and then scaled by device pixel ratio with ctx.setTransform(DPR, 0, 0, DPR, 0, 0), which keeps the lines and text crisp on retina screens without blowing up performance. Layout is responsive: layout() uses the card width to compute lane positions and widths so there are always four lanes that fit neatly on the right side, with enough space for long labels like “Firewall” and “Endpoint,” and a consistent baseline calculated from the card height (H * 0.58) that controls the belt and lane positions.
Each packet is a simple object with position, velocity, dimensions, and a type reference. I use measureText in measureLabel() to size the packet width dynamically based on the label text, then add padding so the rounded rectangle fits the text exactly instead of using a fixed random width. Drawing is all done with a roundRect() helper. Each packet gets a body in its main color, a darker stripe on the bottom half, and then a center label drawn with a semibold UI font and forced to land on half-pixel coordinates for crispness. The conveyor itself is just a dark rectangle with a vertical gradient overlay that adds a faint white and orange sheen, which makes it feel like a lit conveyor belt without needing any images.
Input handling is intentionally minimal. Pointer events compute the click position relative to the canvas and then walk the packets from topmost to bottom to find a hit, storing an offsetX and offsetY so the packet stays under your cursor when you drag it. When you release, the code checks for intersection with any lane using a simple axis aligned bounding box check. If you dropped it over a lane, it marks the packet as removed, updates efficiency, and adds a short-lived flash overlay object that draws a colored border on top of the lane for a few hundred milliseconds. Keyboard routing works a little differently: when you press 1 through 4, it scans for the furthest packet to the right that is past a gate position (60 percent of the width) and not grabbed or already removed, then compares its type to the chosen lane and scores it the same way. That gives a quick “hotkey triage” feel without needing to move the mouse at all.
For performance and UX, the widget keeps a rolling window of the last RECENT_N decisions instead of recalculating efficiency from all time. Each route or miss pushes a 1 or 0 into the recent array and trims it to the last 25 entries, then computes efficiency as a percent of that slice. This is what drives both the “Eff XX%” label and the width of the top throughput bar, with a minimum width of 8 percent so you always see a sliver of activity even if you are doing terribly. The main loop runs on requestAnimationFrame, caps dt so physics do not explode if the tab lags, and handles spawn logic (SPAWN_MS and a max packet count) together with movement and cleanup. Visually, the card still feels like part of the site, with the same gradients, subtle orange glow, and rounded corners, but under the hood it is a self-contained simulation of routing, misroutes, and throughput that shows off some actual JavaScript and canvas skills instead of just being another static Figma export.
When I built this “Upload Runner” mini game, the goal was to turn the idea of “maturity insights over a year” into something you actually feel instead of just reading a slide. The widget sits inside a single mount div and replaces itself with a self-contained card that draws the whole game on a canvas. Up top you get a title, a throughput bar, and a simple stat line that starts at “0/12” and “Monthly Insights.” On the canvas you control a little runner who can single and double jump across a scrolling field of platforms, collecting glowing blue “insight” packets while dodging hazards like firewalls and spiky risk blobs. Each packet you grab increments the score toward 12, fills the bar via a scaleX transform, and moves the copy from generic “Monthly Insights” toward a satisfying “12/12 Monthly Insights - Year Complete.” If you hit a wall or a virus after the initial grace period, the run ends with a “Risk detected” state and you can click to try again.
Under the hood the script is built to drop into any page without stepping on other styles or scripts. It generates a unique token for each instance, wraps the game in a div with that id, and injects CSS that is fully namespaced to #token selectors. That prevents class collisions and lets you mount multiple copies if you ever wanted to. The canvas uses a device pixel ratio aware sizing function and a ResizeObserver watching the wrapper, so it automatically scales cleanly on retina displays and responds to layout changes without blurry scaling. A field() helper calculates the playable region inside the card, and everything positions itself relative to that, so the physics and visuals stay aligned no matter how wide the card is.
Gameplay is basically a stripped down endless runner tuned for short sessions in a marketing context. The player is a simple struct with x, y, width, height, vertical velocity, and a jump counter. Gravity is applied every frame, and there is a small platform landing check that only lets you stick to platforms when you are falling from above. The world scrolls by adjusting the x position of obstacles, packets, and platforms based on a scrollSpeed() that increases slightly with progress, so the game ramps up in difficulty as you collect more insights. There is a short safeTimer window after starting so the user is not instantly punished, and both spawn timers for packets and obstacles are shortened after reset and clamped down when you hit start so the first few objects arrive quickly and the card does not feel dead.
Collection and failure logic are handled with simple collision helpers. The player hitbox is shrunk by a HITBOX_SHRINK factor to make the game feel fair, so you do not die when you barely graze something. Packets are stored as small objects with a center point and size; when the player overlap test hits, the packet is removed, the score is incremented up to the TARGET of 12, progress is updated as score / TARGET, and the throughput bar’s transform is updated in one line. Hazards are split into rectangle “walls” and circular “virus” enemies, and the collision routines use rectangle overlap or circle-rectangle distance checks accordingly. Once you hit 12, the script flips into a gameOver state, stops stepping physics, swaps the overlay to a “year complete” button, and lets you restart with Enter or a click. All of it runs inside a requestAnimationFrame loop with a capped dt so physics stay stable even if the tab stutters, and every frame redraws the background rails, parallax streaks, platforms, packets, hazards, and the stick figure runner animation that is driven by a phase based on performance.now(). The result is a tiny, self-contained JavaScript and canvas experience that makes “monthly insights” feel like something you chase and dodge in real time, rather than just a line on a dashboard.