go home

2026-08-17 - website and blog updates

i spent the past 2 days making some updates to my html/gemini blog. and i have a fun journey to share. besides a few question marks on kagi, there were no llms or gen-ai involved in this process.

i wrote a simple backup utility last year that stopped working when i switched from a framework 13 to a framework 12 laptop. the problem was that i copied the backup utility, but not the systemd service/timer.

framework 12 is awesome

so after i got my backup utility working again, i wanted to make a new blog post to explain it, because it is a very cool/minimal idea compared to enterprise subscriptions. however the best way to show it off is through a demo. i'm running this site frugally and through git, so i don't want to host any videos. i decided my blog needed to have an easy way embed self-hosted asciinema videos.

asciinema homepage

asciinema is awesome. i have used it off and on over the years. but since i first used it, it has been ported from python to rust and the default behavior is to store files locally vs uploading asciinema.org. no idea why this wasn't the default behavior before, but this is a much better default.

the problem with getting asciinema embedded on this blog is that before today the http server was actually just an on-the-fly proxy of the gemini server using a tool called kineto.

link to kineto

http and gemini hosting choices

kineto had served me great for the past ~5 years. i decided that rather than proxying the website, i just want static gemini and html files to serve with an http and gemini server. my gemini server didn't change. this will continue to be agate. agate has been stable for me.

agate, a gemini server

and really any http server would do, because the ssl portion is handled by nginx and certbot. i found a fast/simple server called "http" or "httplz". it is meant to just host files you have in a directory, usually you would use this as a localhost development tool, but for this server it works fine.

host these things please (http or httplz)

the project seems to officially be called "http" which seems like a bad name for a project. the arch linux repositories renamed it to "httplz". so there is some confusion. also the readme has a crossed out comment that reads:

I̶t̶'̶s̶ ̶n̶o̶t̶ ̶g̶o̶i̶n̶g̶ ̶t̶o̶ ̶b̶e̶ ̶a̶ ̶'̶p̶r̶o̶d̶u̶c̶t̶i̶o̶n̶ ̶r̶e̶a̶d̶y̶'̶ ̶t̶o̶o̶l̶,̶ ̶i̶t̶'̶s̶ ̶a̶ ̶q̶u̶i̶c̶k̶ ̶a̶n̶d̶ ̶d̶i̶r̶t̶y̶ ̶w̶a̶y̶ ̶o̶f̶ ̶h̶o̶s̶t̶i̶n̶g̶ ̶a̶ ̶f̶o̶l̶d̶e̶r̶,̶ ̶s̶o̶ ̶w̶h̶i̶l̶s̶t̶ ̶I̶'̶l̶l̶ ̶t̶r̶y̶ ̶t̶o̶ ̶m̶a̶k̶e̶ ̶i̶t̶ ̶s̶e̶c̶u̶r̶e̶,̶ ̶i̶t̶ ̶i̶s̶ ̶n̶o̶t̶ ̶g̶o̶i̶n̶g̶ ̶t̶o̶ ̶b̶e̶ ̶a̶ ̶s̶e̶r̶i̶o̶u̶s̶ ̶g̶o̶a̶l̶.̶

so maybe the author considers it a production ready tool, who knows. in the future if i need quick local server, i'm using this tool rather than the python builtin i would use previously.

static compilation

i've already been writing my blog posts in modified gemtext and using a hacky script to convert it to real gemtext to keep things DRY. so yesterday i spent some time modifying kineto and my shell script to generate static files for both gemini and html. then i further modified kineto to embed asciinema. and finally i got everything working and life felt good.

now whenever i create a gemtext codeblock with an "asciinema" label containing base64, the static html shows an asciinema video and the static gemtext becomes a link pointing to the html page. i think this is a clever solution. here is an example of what these code blocks look like in my repo:

and here is a terminal recording of how i generated the above base64:

that's right, i'm meta. i recorded asciinema within asciinema.

anyways this whole endeavour was a difficult quest. i didn't want extra files, so the html literally converts these asciinema blocks to hidden div tags with base64 in the body. i parse out that base64 with javascript and pass it into the asciinema player. one learning was that javascript uses utf-16, so if you just use the builtin btoa (binary to ascii) function, your terminal recording looks mostly fine until you start displaying non-ascii characters, then everything gets messed up.

ranting about javascript utf-16 learning

also the asciinema player really wants you to store your asciinema recording in a separate file. after digging through the source code and through trial and error, i found a data parameter that lets you bypass that. but i had to pass the data as a response rather than data, otherwise the old file format is assumed. it's all a huge hack and i forgot how much i don't like javascript. but i'm done and hoping i will never have to touch this again.

asciinema player codebase

conclusion

while working on all this, this server's namecheap domain name expired and the server was down for i'm guessing 12 hours. so i had to renew that and wait for dns to play catchup. also while making updates, i accidentally deleted the self-signed gemini cert, so gemini clients need to TOFU again.

i also made tweaks to the homepage and about me pages, so you can check those out if you want. i had a full resume page before and now it's merged with the about me page and much less serious. i'm very proud of these new changes too.

if i were like most programmers today, i would have vibe coded all this in a few hours and ended up with a much more bloated design or solution. i also wouldn't have had a story to share or knowledge gained.

anyways, the whole point of this exercise was to make a blogpost about my backup utility, but i need a break today and the rest of this week is looking busy. so stay tuned for that next blogpost. or don't. smell ya later!