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.
python -m http.server # <- you could type this
httplz # <- or this
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:
. ```asciinema
. eyJ2ZXJzaW9uIjozLCJ0ZXJtIjp7ImNvbHMiOjE5MSwicm93cyI6NDUsInR5cGUiOiJ4dGVybS0y
. NTZjb2xvciIsInZlcnNpb24iOiJ0bXV4IDMuN2IiLCJ0aGVtZSI6eyJmZyI6IiNmZmZmZmYiLCJi
. ZyI6IiMwMDAwMDAiLCJwYWxldHRlIjoiIzAwMDAwMDojZmY4MDU5OiM0NGJjNDQ6I2QwYmMwMDoj
. MmZhZmZmOiNmZWFjZDA6IzAwZDNkMDojYmZiZmJmOiM1OTU5NTk6I2VmOGI1MDojNzBiOTAwOiNj
. MGM1MzA6Izc5YThmZjojYjZhMGZmOiM2YWU0Yjk6I2ZmZmZmZiJ9fSwidGltZXN0YW1wIjoxNzg2
. OTY2NjAxLCJpZGxlX3RpbWVfbGltaXQiOjAuMjUsImVudiI6eyJTSEVMTCI6Ii9iaW4venNoIn19
. ClswLjA3MCwgIm8iLCAiXHUwMDFiWzFtXHUwMDFiWzdtJVx1MDAxYlsyN21cdTAwMWJbMW1cdTAw
. MWJbMG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICAgXHIgXHJcclx1MDAxYlswbVx1MDAxYlsyN21cdTAwMWJb
. MjRtXHUwMDFiW0pcdTAwMWJbMzNtPlx1MDAxYlszOW0gXHUwMDFiW0tcdTAwMWJbPzIwMDRoIl0K
. WzAuNzM0LCAibyIsICJlIl0KWzAuMDkxLCAibyIsICJcYmVjIl0KWzAuMDY4LCAibyIsICJoIl0K
. WzAuMDY5LCAibyIsICJvIl0KWzAuMDkwLCAibyIsICIgIl0KWzAuMDkwLCAibyIsICJoIl0KWzAu
. MDkwLCAibyIsICJpIl0KWzAuMTM2LCAibyIsICJcdTAwMWJbPzIwMDRsXHJcclxuIl0KWzAuMDA3
. LCAibyIsICJoaVxyXG5cdTAwMWJbMW1cdTAwMWJbN20lXHUwMDFiWzI3bVx1MDAxYlsxbVx1MDAx
. YlswbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
. ICAgICAgICAgICAgICAgICAgICAgICBcciBcclxyXHUwMDFiWzBtXHUwMDFiWzI3bVx1MDAxYlsy
. NG1cdTAwMWJbSlx1MDAxYlszM20+XHUwMDFiWzM5bSBcdTAwMWJbS1x1MDAxYls/MjAwNGgiXQpb
. MS4zNDgsICJvIiwgIlx1MDAxYls/MjAwNGxcclxyXG4iXQpbMC4wNzQsICJ4IiwgIjAiXQo=
. ```
and here is a terminal recording of how i generated the above base64:
eyJ2ZXJzaW9uIjozLCJ0ZXJtIjp7ImNvbHMiOjE5MSwicm93cyI6NDUsInR5cGUiOiJ4dGVybS0y
NTZjb2xvciIsInZlcnNpb24iOiJ0bXV4IDMuN2IiLCJ0aGVtZSI6eyJmZyI6IiNmZmZmZmYiLCJi
ZyI6IiMwMDAwMDAiLCJwYWxldHRlIjoiIzAwMDAwMDojZmY4MDU5OiM0NGJjNDQ6I2QwYmMwMDoj
MmZhZmZmOiNmZWFjZDA6IzAwZDNkMDojYmZiZmJmOiM1OTU5NTk6I2VmOGI1MDojNzBiOTAwOiNj
MGM1MzA6Izc5YThmZjojYjZhMGZmOiM2YWU0Yjk6I2ZmZmZmZiJ9fSwidGltZXN0YW1wIjoxNzg2
OTY2NTkwLCJpZGxlX3RpbWVfbGltaXQiOjAuMjUsImVudiI6eyJTSEVMTCI6Ii9iaW4venNoIn19
ClswLjA3NywgIm8iLCAiXHUwMDFiWzFtXHUwMDFiWzdtJVx1MDAxYlsyN21cdTAwMWJbMW1cdTAw
MWJbMG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgXHIgXHJcclx1MDAxYlswbVx1MDAxYlsyN21cdTAwMWJb
MjRtXHUwMDFiW0pcdTAwMWJbMzNtPlx1MDAxYlszOW0gXHUwMDFiW0tcdTAwMWJbPzIwMDRoIl0K
WzIuNDQxLCAibyIsICJhIl0KWzAuMTgwLCAibyIsICJcYmFzIl0KWzAuMDkxLCAibyIsICJjIl0K
WzAuMTU4LCAibyIsICJpIl0KWzAuMTU3LCAibyIsICJpIl0KWzAuMTEzLCAibyIsICJuIl0KWzAu
MTU3LCAibyIsICJlIl0KWzAuMTE0LCAibyIsICJtIl0KWzAuMTgxLCAibyIsICJhIl0KWzAuMjAz
LCAibyIsICIgIl0KWzAuMTU4LCAibyIsICJyIl0KWzAuMTEyLCAibyIsICJlIl0KWzAuMDkwLCAi
byIsICJjIl0KWzAuMTM2LCAibyIsICIgIl0KWzAuMTEyLCAibyIsICItIl0KWzAuMTE0LCAibyIs
ICJpIl0KWzAuMTU3LCAibyIsICIgIl0KWzAuMjI3LCAibyIsICIyIl0KWzAuMzI1LCAibyIsICJc
YiBcYiJdClswLjExNCwgIm8iLCAiLiJdClswLjIyNCwgIm8iLCAiMiJdClswLjE1OSwgIm8iLCAi
NSJdClswLjgzNiwgIm8iLCAiICJdClswLjE4MCwgIm8iLCAiLyJdClswLjEzNSwgIm8iLCAidCJd
ClswLjA5MCwgIm8iLCAibSJdClswLjQzOCwgIm8iLCAicCJdClswLjQ5MywgIm8iLCAiLyJdClsx
LjU2MiwgIm8iLCAieiJdClswLjgzOCwgIm8iLCAiXHUwMDFiWz8yMDA0bFxyXHJcbiJdClswLjAx
NywgIm8iLCAiXHUwMDFiWz4wcVx1MDAxYl0xMDs/XHUwMDA3XHUwMDFiXTExOz9cdTAwMDdcdTAw
MWJdNDswOz9cdTAwMDdcdTAwMWJdNDsxOz9cdTAwMDdcdTAwMWJdNDsyOz9cdTAwMDdcdTAwMWJd
NDszOz9cdTAwMDdcdTAwMWJdNDs0Oz9cdTAwMDdcdTAwMWJdNDs1Oz9cdTAwMDdcdTAwMWJdNDs2
Oz9cdTAwMDdcdTAwMWJdNDs3Oz9cdTAwMDdcdTAwMWJdNDs4Oz9cdTAwMDdcdTAwMWJdNDs5Oz9c
dTAwMDdcdTAwMWJdNDsxMDs/XHUwMDA3XHUwMDFiXTQ7MTE7P1x1MDAwN1x1MDAxYl00OzEyOz9c
dTAwMDdcdTAwMWJdNDsxMzs/XHUwMDA3XHUwMDFiXTQ7MTQ7P1x1MDAwN1x1MDAxYl00OzE1Oz9c
dTAwMDdcdTAwMWJbYyJdClswLjAwMiwgIm8iLCAiOjo6IGFzY2lpbmVtYSBzZXNzaW9uIHN0YXJ0
ZWRcclxuOjo6IFJlY29yZGluZyB0byAvdG1wL3pcclxuOjo6IFByZXNzIDxjdHJsK2Q+IG9yIHR5
cGUgJ2V4aXQnIHRvIGVuZFxyXG4iXQpbMC4wNzAsICJvIiwgIlx1MDAxYlsxbVx1MDAxYls3bSVc
dTAwMWJbMjdtXHUwMDFiWzFtXHUwMDFiWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxyIFxyXHJcdTAw
MWJbMG1cdTAwMWJbMjdtXHUwMDFiWzI0bVx1MDAxYltKXHUwMDFiWzMzbT5cdTAwMWJbMzltIFx1
MDAxYltLXHUwMDFiWz8yMDA0aCJdClswLjczNCwgIm8iLCAiZSJdClswLjA5MiwgIm8iLCAiXGJl
YyJdClswLjA2NywgIm8iLCAiaCJdClswLjA2OSwgIm8iLCAibyJdClswLjA5MCwgIm8iLCAiICJd
ClswLjA5MSwgIm8iLCAiaCJdClswLjA5MCwgIm8iLCAiaSJdClswLjEzNSwgIm8iLCAiXHUwMDFi
Wz8yMDA0bFxyXHJcbiJdClswLjAwNywgIm8iLCAiaGlcclxuXHUwMDFiWzFtXHUwMDFiWzdtJVx1
MDAxYlsyN21cdTAwMWJbMW1cdTAwMWJbMG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHIgXHJcclx1MDAx
YlswbVx1MDAxYlsyN21cdTAwMWJbMjRtXHUwMDFiW0pcdTAwMWJbMzNtPlx1MDAxYlszOW0gXHUw
MDFiW0tcdTAwMWJbPzIwMDRoIl0KWzEuMzQ4LCAibyIsICJcdTAwMWJbPzIwMDRsXHJcclxuIl0K
WzAuMDc0LCAibyIsICI6OjogYXNjaWluZW1hIHNlc3Npb24gZW5kZWRcclxuOjo6IFJlY29yZGVk
IHRvIC90bXAvelxyXG4iXQpbMC4wMDEsICJvIiwgIlx1MDAxYlsxbVx1MDAxYls3bSVcdTAwMWJb
MjdtXHUwMDFiWzFtXHUwMDFiWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxyIFxyXHJcdTAwMWJbMG1c
dTAwMWJbMjdtXHUwMDFiWzI0bVx1MDAxYltKXHUwMDFiWzMzbT5cdTAwMWJbMzltIFx1MDAxYltL
XHUwMDFiWz8yMDA0aCJdCls0Ljg5NywgIm8iLCAiYyJdClswLjA4OSwgIm8iLCAiXGJjYSJdClsw
LjEzNiwgIm8iLCAidCJdClsxLjY0NiwgIm8iLCAiICJdClsyLjM2MywgIm8iLCAiLyJdClswLjIy
NiwgIm8iLCAidCJdClswLjA4OSwgIm8iLCAibSJdClswLjEzNiwgIm8iLCAicCJdClswLjkyOSwg
Im8iLCAiLyJdClswLjQ2NSwgIm8iLCAieiJdClswLjkzMywgIm8iLCAiICJdClswLjI3MSwgIm8i
LCAifCJdClswLjEzNCwgIm8iLCAiICJdClswLjE4MiwgIm8iLCAiYiJdClswLjA5MCwgIm8iLCAi
YSJdClswLjA5MSwgIm8iLCAicyJdClswLjExMywgIm8iLCAiZSJdClswLjM5NCwgIm8iLCAiNiJd
ClswLjExMiwgIm8iLCAiNCJdClsyLjE1NywgIm8iLCAiXHUwMDFiWz8yMDA0bFxyXHJcbiJdClsw
LjAxNiwgIm8iLCAiZXlKMlpYSnphVzl1SWpvekxDSjBaWEp0SWpwN0ltTnZiSE1pT2pFNU1Td2lj
bTkzY3lJNk5EVXNJblI1Y0dVaU9pSjRkR1Z5YlMweVxyXG5OVFpqYjJ4dmNpSXNJblpsY25OcGIy
NGlPaUowYlhWNElETXVOMklpTENKMGFHVnRaU0k2ZXlKbVp5STZJaU5tWm1abVptWWlMQ0ppXHJc
blp5STZJaU13TURBd01EQWlMQ0p3WVd4bGRIUmxJam9pSXpBd01EQXdNRG9qWm1ZNE1EVTVPaU0w
TkdKak5EUTZJMlF3WW1Nd01Eb2pcclxuTW1aaFptWm1PaU5tWldGalpEQTZJekF3WkROa01Eb2pZ
bVppWm1KbU9pTTFPVFU1TlRrNkkyVm1PR0kxTURvak56QmlPVEF3T2lOalxyXG5NR00xTXpBNkl6
YzVZVGhtWmpvallqWmhNR1ptT2lNMllXVTBZams2STJabVptWm1aaUo5ZlN3aWRHbHRaWE4wWVcx
d0lqb3hOemcyXHJcbk9UWTJOakF4TENKcFpHeGxYM1JwYldWZmJHbHRhWFFpT2pBdU1qVXNJbVZ1
ZGlJNmV5SlRTRVZNVENJNklpOWlhVzR2ZW5Ob0luMTlcclxuQ2xzd0xqQTNNQ3dnSW04aUxDQWlY
SFV3TURGaVd6RnRYSFV3TURGaVd6ZHRKVngxTURBeFlsc3lOMjFjZFRBd01XSmJNVzFjZFRBd1xy
XG5NV0piTUcwZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNB
Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnXHJcbklDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0Fn
SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdcclxuSUNBZ0lDQWdJ
Q0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lD
QWdJQ0FnSUNBZ1xyXG5JQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1hISWdYSEpjY2x4
MU1EQXhZbHN3YlZ4MU1EQXhZbHN5TjIxY2RUQXdNV0piXHJcbk1qUnRYSFV3TURGaVcwcGNkVEF3
TVdKYk16TnRQbHgxTURBeFlsc3pPVzBnWEhVd01ERmlXMHRjZFRBd01XSmJQekl3TURSb0lsMEtc
clxuV3pBdU56TTBMQ0FpYnlJc0lDSmxJbDBLV3pBdU1Ea3hMQ0FpYnlJc0lDSmNZbVZqSWwwS1d6
QXVNRFk0TENBaWJ5SXNJQ0pvSWwwS1xyXG5XekF1TURZNUxDQWlieUlzSUNKdklsMEtXekF1TURr
d0xDQWlieUlzSUNJZ0lsMEtXekF1TURrd0xDQWlieUlzSUNKb0lsMEtXekF1XHJcbk1Ea3dMQ0Fp
YnlJc0lDSnBJbDBLV3pBdU1UTTJMQ0FpYnlJc0lDSmNkVEF3TVdKYlB6SXdNRFJzWEhKY2NseHVJ
bDBLV3pBdU1EQTNcclxuTENBaWJ5SXNJQ0pvYVZ4eVhHNWNkVEF3TVdKYk1XMWNkVEF3TVdKYk4y
MGxYSFV3TURGaVd6STNiVngxTURBeFlsc3hiVngxTURBeFxyXG5ZbHN3YlNBZ0lDQWdJQ0FnSUNB
Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0Fn
XHJcbklDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJ
Q0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdcclxuSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lD
QWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1xyXG5JQ0FnSUNB
Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCY2NpQmNjbHh5WEhVd01ERmlXekJ0WEhVd01ERmlXekkz
YlZ4MU1EQXhZbHN5XHJcbk5HMWNkVEF3TVdKYlNseDFNREF4WWxzek0yMCtYSFV3TURGaVd6TTVi
U0JjZFRBd01XSmJTMXgxTURBeFlscy9NakF3TkdnaVhRcGJcclxuTVM0ek5EZ3NJQ0p2SWl3Z0ls
eDFNREF4WWxzL01qQXdOR3hjY2x4eVhHNGlYUXBiTUM0d056UXNJQ0o0SWl3Z0lqQWlYUW89XHJc
biJdClswLjAwMSwgIm8iLCAiXHUwMDFiWzFtXHUwMDFiWzdtJVx1MDAxYlsyN21cdTAwMWJbMW1c
dTAwMWJbMG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgXHIgXHJcclx1MDAxYlswbVx1MDAxYlsyN21cdTAw
MWJbMjRtXHUwMDFiW0pcdTAwMWJbMzNtPlx1MDAxYlszOW0gXHUwMDFiW0siXQpbMC4wMDAsICJv
IiwgIlx1MDAxYls/MjAwNGgiXQpbOC45NjAsICJvIiwgIlx1MDAxYls/MjAwNGxcclxyXG4iXQpb
MC4wOTUsICJ4IiwgIjAiXQo=
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!