Most security dashboards are locked inside the tool that generated them. Splunk, Grafana, whatever — useful internally, invisible externally. I wanted something different: a public-facing quarterly report, built from real honeypot data, that I could update in an hour and ship to production with a single git push.
This is how I built it.
The problem with static content
My website is static HTML. Fast, secure, no CMS to patch. But “static” traditionally means “manually updated” — and manually updated means it doesn’t get updated.
The insight is that static doesn’t have to mean frozen. If your content pipeline ends in a git push, you get versioned, auditable, deployable content — without a CMS, without a build system, without a server that needs babysitting.
The pipeline
The source of truth is Splunk, running on a low-spec VM on my home network. Every quarter I run a shell script that queries the Splunk REST API, exports CSVs for each dataset — protocols, countries, credentials, attack patterns — and drops them into a data/ folder in a GitHub repository.
The report itself is a single HTML file. No frameworks. Chart.js for visualisation, CSS for layout, the data baked in at build time. It scrolls like a presentation, reads like a report, and works offline once loaded.
The deployment is Caddy serving a directory that’s a git pull away from production. Pull the repo on the server, the new report is live.
Why this works
The key decision was separating data collection from presentation. The Splunk queries are versioned in the repo alongside the HTML. When I run the export script next quarter, I get new CSVs. I update the data in the HTML, commit, push, pull on the server. The whole update cycle takes about an hour.
It also means the report is reproducible. Anyone can see exactly which queries produced which numbers. The data, the queries, and the presentation are all in the same repository.
What’s next
The next step is automating the data injection — parsing the CSVs and writing the JavaScript data arrays directly, so the HTML update is also scripted. A quarterly cron job on the export, a script that patches the HTML, a commit and push. The human step becomes review and publish, not data entry.
The broader principle applies to anything with a regular cadence: monthly digests, annual reviews, any report you currently update by hand. If the data lives somewhere queryable and the output is HTML, this pipeline works.
The Q2 2026 report: https://sc.toce.ch/2026q2
