May 10, 2025
When I first created my homepage a few weeks ago, I wanted to display some server
metrics on the site, but it was a bit too big of a project for me to bite off at that
point. But this week, I was ready to take a proper swing at it. I had heard of
FastAPI
as a simple and powerful Python module for HTTP APIs, so I decided
to use that to make Prometheus query results available to my webpage. I also found out
about htmx
in my reading, which is a javascript library that extends html
and makes it possible to have individual elements of a page complete recurring GET
requests (i.e. "auto-refresh" of queries). And I also selected Chart.JS for rendering
chart-view metrics, as opposed to just simple single-value metrics.
For the first cut of the page, I picked a few basic metrics for CPU and Memory Usage,
Disk Space, and Network Rx. I copied the queries for these from my Grafana dashboard.
The first piece of the puzzle was to make the Prometheus queries available to HTML (or
htmx, in my case). That's where FastAPI came in. I built a simple app with endpoints
like /queries/cpu
and /queries/memory
. The definition for each
endpoint was to query data from prometheus, and then return it. Originally, I thought
that I could just return the raw data and then render it in higher-level html, but it
turns out that for htmx queries, it expects the response to already be an HTML document,
not just a raw value, so I added a simple template to help render the value of each
endpoint into a "widget". Once I had the widgets defined, I also needed a top-level html
page (at /
) that displayed the widgets and automatically refreshed their
values. I had ChatGPT cook up a simple template, but realized that I wanted to pull in
the same CSS I was using for my homepage site.
Since I was building the dashboard as it's own top-level directory and application, it
was a little complicated to have shared CSS with my main homepage. I originally hoped to
just symlink the files, but that doesn't work with docker very well. So I moved the
common files (main.css
as well as the icon files for the site) into a
top-level shared-assets
directory and then built a simple
sync_assets.sh
script that copies those files from the shared directory
into all child directories (right now, just homepage/
and
dashboard/
). I figure this will be useful in the future when I build more
top-level apps that want to use the same style as my other pages.
With this, I had the first iteration of my dashboard built! It was pretty cool, but kinda boring with just singular numbers for each metric. So I had ChatGPT help me build some charts based on the same metrics using Chart.JS. The rendering is a bit clunky and I definitely need to do some more reading because I'm a total JS noob, but I at least got them in and working which was cool! After some more tweaking of the look and feel of the site, I was happy enough with it that I connected it into my main homepage, replacing (and deleting) the old "fake metrics" page I had put together as a placeholder lol.
While I was in there, I also added links to all of my services that host their own
dashboards: in addition to Grafana (which was already there), I added in
traefik
, prometheus
, and whoami
. I'm really happy
with how the page is coming together, and I think I'm almost ready to share it more
publicly (LinkedIn, resumé, etc).