App Launcher
← All apps
D2R Inventory Image screenshot
Live

D2R Inventory Image

Auto-generated Diablo II item showcase images

Go Gin image/draw Prometheus Grafana Google Sheets

What it is

A fun side project for Diablo II: Resurrected. It reads a curated list of items from a Google Sheet and renders a clean, shareable “inventory” image — handy for showing off finds in trade communities.

How it’s built

A small Go service (Gin for routing) composites the image from first principles using only the standard library — no ImageMagick, no headless browser. It draws a sprite sheet onto a canvas with image/draw, renders the item rows with a bitmap font from golang.org/x/image/font, and encodes the result with image/png.

Google Sheet published CSV
Go service image/draw
Browser / share
A published Sheet is the CMS; the service renders + serves the PNG

Engineering highlights

  • Spreadsheet as a CMS — the source of truth is a Google Sheet published as CSV, fetched over plain HTTP with no API keys or service accounts. Anyone non-technical can update the item list with zero deploy.
  • Dynamic canvas sizing — the image width is computed from the longest row and the height from the row count, so output never clips or hardcodes dimensions.
  • Stateless rendering — each regeneration is a full, deterministic redraw cached to disk; no incremental-update bugs, and the service can be restarted or scaled freely.
  • Observability from day one — Prometheus counters and latency histograms (image generation, CSV fetch) are exposed at /metrics, scraped by Grafana Alloy into Grafana Cloud dashboards for request volume, errors, and timing.

Infrastructure

Served behind nginx with Let’s Encrypt TLS; metrics scraped by a Grafana Alloy agent. The whole thing is a single lightweight Go binary with a tiny footprint.

What I learned

Treating Google Sheets as a lightweight CMS is a surprisingly pragmatic pattern for small projects where the content owner isn’t a developer — and writing the image compositor by hand was a good reminder of how much you can do with Go’s standard library alone.