clehaxze.tw, my new hybird Gemini/HTTP website

I decided to rewirite both my personal website and my Gemini capsule into a single service... Whoah.. that is so not UNIX. I should have just kept separate servers doing their own thing. But I have (I hope) good reasons to go the other way. Namely

  • Automated Gemlog index
  • Atom feed support
  • I want my Gemlogs be viewable over HTTP. Without the hacker style pages that is the Gemini proxies

I want Atom feed because I want to explore how Atom works. Instead of depending on the shaky Gemsub[1] mechanism - Which IMO is really a hack that the protocol devlopers make because they know not everyone is gonna implement Atom. Running my gemlog on a proper backend is the first step to getting Atom support. I can now generate Atom feeds by walking the gemlog.

And my original website is way overdue to be rewritten. It does run on C++. But it's basically a static website that shows nothing cool (in developer terms). The gemlogs I have written are good contents that I can build upon. Besides I've been getting tired from the Wordpress site I used to write my blog. It's bloated, full of trackers and just bad editing experience. I have a much better time writing gemtext instead (And I'll spare you the 10K bugs in their editor).

Converting Gemini to reasonable looking HTML

Serving both HTTP and Gemini is something Dremini[2] can just do easily. And it also includes a converter from Gemini to HTML. Nice that I don't need special code to bridge the two. Formating gemtext to look good is another challenge. First that I don't have much art neurons. Then that gemtext is low in format information. Which to be fair is waht Gemini is designed for.

Turns out putting a profile section next to the gemtext is a good way to get the web page less visually boring. I also took some design inspiration from Vulpes[3] gemini/golpher proxy. I really like their approach of keeping the Gemini syntax while not being too verbose. Espically keeping the => and > in links and quotes. Though I have to forgo monospace fonts and the hash mark in titles. They ended up being too much.

Atom feed

Atom/RSS feeds are not as popular on the common web as they were. But they are very useful on Gemini. The alterantive is twtxt[4]. But it is not a standardized format. Besides, most browsers (at least Lagrange) does not support it.

Atom is much simpler than I thought. No wonder Gemini uses it as the feed format. I got it working in 20 minues. An endpoint /atom.xml is added on the new website/capsule. It spits out feeds depending the source protocol. The only sad part is Firefox removed Atom/RSS support back in 2018. And Lagrange's Atom page is not helpful when debugging my feed format.

Security and privacy

There's no way I'm gonna breach the privacy of anyone on my site. I'm very happy to share that I am able to (after a lot of head banging) build a HTML page that is responsive and is JS-free. You can turn No-Script all the way on and still get the same page. And there's no CDN on my page. Everything is downloaded from the server (with aggressive caching). I also connected it to Tor for the paranoids. No IP information is gonna be leaked.

C and C++ is known for their share of memory bugs. Causing security breaches. This is also covered. The server runs on the same security settings as TLGS does. With GrapheneOS's hardened_malloc, with low privileges and with systemd's sandboxing. Besides that, I'm able to bombard the server with bad requests without AddressSanitizer ever triggering. It's not a sure sign of security. But is good enough for me to put it on the internet.

Welp, let me know if you find any bugs. I'll fix them ASAP. And get them upstream if applicable.

Author's profile. Photo taken in VRChat by my friend Tast+
Martin Chang
Systems software, HPC, GPGPU and AI. I mostly write stupid C++ code. Sometimes does AI research. Chronic VRChat addict

I run TLGS, a major search engine on Gemini. Used by Buran by default.


  • marty1885 \at protonmail.com
  • Matrix: @clehaxze:matrix.clehaxze.tw
  • Jami: a72b62ac04a958ca57739247aa1ed4fe0d11d2df