花式卷曲网站
Fancy Curl Sites

原始链接: https://nytpu.com/gemlog/2026-03-18

作者描述了自己如何为网站创建一个对 curl 友好的版本,以便在终端中查看,灵感来自 trinkey 和 strongsand。他们使用 ANSI 转义码手写了首页和关于页面。整个博客也提供 curl 形式,因为他们的自定义标记语言 Gemroff 已经会为草稿预览生成带 ANSI 标记的纯文本;将其接入静态网站生成器只需要包装模板和几行代码。当用户代理包含 “curl” 时,Nginx 会提供 curl 版本;可用 X-Original: true 标头覆盖,以接收普通 HTTP。他们指出,这之所以容易,仅仅是因为他们有自定义的多输出设置,但几个手写页面也会是不错的替代方案。文章已更新,指出两个灵感来源网站的 curl 版本都已无法使用。作者以对长破折号的玩笑式辩护结尾。

一个 Hacker News 帖子讨论了“花哨的 Curl 网站”:它们向 curl/wget 提供适合终端的 ANSI 输出,而浏览器收到普通 HTML。评论者分享了例子:作品集网站、天气(wthr.dev)、音乐/书籍 feed,以及 curl|sh 多语言脚本。一种技术把 ANSI 转义码嵌入 HTML 注释,并切换终端缓冲区,从而避免 User-Agent 检查。其他人建议通过 Accept 头进行内容协商——浏览器用 `Accept: text/html`,curl 用 `text/x-ansi`——而不是像 `X-Original` 这样的自定义头。该帖将此与电子邮件的 multipart/alternative 相比,指出它可在 Windows Terminal(不是 PowerShell)中工作,并争论对代理的可访问性。其他评论提到 wttr.in、Finger、最近的 curl/libcurl CVE,以及使用 GNU IceCat/LibreJS 浏览。总体而言,这是对极简、可用命令行浏览的网页内容的一次有趣复兴。
相关文章

原文

March 18, 2026 (Updated: October 14, 2026)

So a good while ago I added a fun curl version of my site, meant for viewing in the terminal. Try running these commands!

curl nytpu.com/gemlog/2026-03-18
# or
curl nytpu.com

(sorry Windows users, not my fault that ANSI escape codes are disabled-by-default in cmd.exe. And not my fault that in Powershell you have to use curl.exe instead of curl because Powershell inexplicably aliases that to Invoke-WebRequest.)

I posted about it a bit on the Fediverse, but otherwise didn't elaborate much on it becuase I figured it was fairly self-explanatory. But I've had a handful of people ask me how I did it, so I decided it might actually be worth it to write a post about how I did it (…like seven months late).

I should note this idea came from trinkey's (curl trinkey.com) and strongsand's (curl proot.party) curl sites, I didn't come up with it myself. Even though I did go about it quite a bit differently from them, all credit for the very cool idea goes to them. (UPDATE: unfortunately neither of their curl versions are functional anymore as of 2026-10-14.)

First, since it's the more interesting part, actually generating the ANSI-marked-up files to send to the clients. I entirely hand-wrote the index page and about page.

Note that I believe trinkey and strongsand generate theirs on-the-fly with the ratatui library (or similar), which is probably more convenient; hand-writing it seemed more expedient to me though.

I had the main escape code—ESC[, i.e. \x1b[— in a Vim register to easily paste when needed, and then the Wikipedia page for the main graphics codes open to reference the specific escape codes. And, yeah, that's about it. I experimented to decide on consistent styling I liked, and just referenced the Gopher version of my pages when crafting the marked-up curl pages.

Now, the notable thing about my version is that I have curl versions of the entirety of my blog, rather than just one or two pages being available. This is entirely due to a convenient coincidence: over four years ago I implemented outputting ANSI-marked-up plaintext in my custom markup language I use for my blog, Gemroff. Originally it was just to allow convenient previewing of drafts in the terminal while writing; but it was trivial to plug into my static site generator to immediately get Curl versions generated.

I did manually write a wrapper template for blog posts, as well as a template for the index page listing posts, but that plus a few extra lines in my static site generator was all that was needed to wire it up.

This is the main thing that makes it hard to say it's easy! since it was only easy for me because I use an entirely custom markup language and static site generator and I happened to make the right design choices years ago—e.g. my SSG also happened to already have support for multiple, modular output formats instead of solely HTML like other SSGs, since I tri-host my site on HTTP, Gemini, and Gopher.

However, offering nothing but a few hand-written pages for fun is a completely acceptable way to set up a site like this anyways, since it's just a neat gimmick and no one's likely to actually use it more than a few minutes of browsing.

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.

And… that's really it! As I said, when I first set it up it seemed fairly self-explanatory to me, but it is very non-orthogonal to what people normally do with either web servers or ANSI escape codes so I can see where people's curiosity/confusion came from. It would be neat to see more sites doing this trick around!


  1. EMDASH! AI-GENERATED! acksually I'll have you know that my markup language has had an explicit markup element for emdashes since November 2022. And believe it nor not: LLMs are trained on shit copied from actual authors, so LLMs wouldn't be using emdashes if they weren't already used in human-written works.

    And what, am I supposed to avoid having twenty parentheticals a paragraph, to where I feel the need to use emdashes to vary it up? Unthinkable!

联系我们 contact @ memedata.com