• I do a simpler variant of this that works using some lovely accidents in Apache httpd’s content negotiation and (like the linked article) Gemini.

    https://alex.corcoles.net/notes/tech/how-this-site-works describes and demonstrates the trick.

    The key is here:

    Interestingly, when the request does not have an Accept header that selects a unique file, Apache replies with the smallest file, which frequently is the gemtext version. When using curl in a terminal, Apache replies with the gemtext version, which is nicer to read on a terminal.

    MultiViews is a wonderful feature. It’s a real shame that services that host static sites do not seem to configure this. It also enables “proper nice URLs”.

    Many sites use URLs such as https://example.com/my-article/ with a trailing slash, notably WordPress. This makes turning sites static quite annoying- you should create a directory per article and stick an index.html in each directory. If you use MultiViews, then you can just have my-article.html and use https://example.com/my-article without the trailing slash, which is much more convenient.

    (This also enables my main trick above- making a site that works across different formats and protocols much more easily.)

    I should run a static site hosting service that enables this trick and that allows dual Gemini+gemtext/HTTP+HTML sites. SourceHut pages is really close to this :(


    score 1 · canonical

  • I’ve skipped the show. curl tinthe.dev is HTML, don’t see why to mess with the default. Seems like a super rare use-case. Are there people who curl sites?

    Although, I did put in <link rel="alternate" type="text/markdown" href="/home.md" title="..."> as a hint for using Accept: text/markdown on the same URL. Or going to .md versions of pages. Did it a “sprint” of optimizing for other devices, screen readers, and LLMs. It is supported on the full page, posts included. Same point as the draft preview, less color.

    Not sure if the X-Original header is the bit to use though. How many users will be comfy with cURL and headers, while not being comfortable using something like Accept: text/html (which is the defacto standard). Poking at the implementation, seems like you ignore Accept headers entirely.

    Now I’m tempted to drop an invisible “instructions” block on top of curl, instructing for this alternate approach. But we’re approaching diminishing returns there, hah.


    score 1 · canonical

  • Finally, the last step is actually presenting the Curl version of your site to any user agent containing curl, which for me was just a few changes to my Nginx config, with other servers it’d presumably be equivalently simple. The main feature I wanted was an override header (X-Original: true) so you could still get an unmodified HTTP response like someone casually running Curl likely wanted, and I wanted everything to be served statically still.

    Isn’t this what the Accept-header is meant for? I.e. curl nytpu.com/gemlog/2026-03-18 -H "Accept: text/html".


    score 1 · canonical

  • One hiccup with this is that, if someone really did use curl to browse the Internet, they probably have curl piped to something that expects HTML, e.g. readability --text | less. But if you serve text with ANSI to curl, then it won’t parse as HTML and the page shows up as unreadable. Like LSP, the MxN problem of user agents and websites is usually solved by having one common format, HTML, and having each user agent adapt HTML to its idiom.


    score 1 · canonical