Fancy Curl Sites
Fancy Curl Sites
Fancy Curl Sites 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.)
Fancy Curl Sites 2026年3月18日(更新于2026年10月14日)。很久以前,我为我的网站添加了一个有趣的 curl 版本,旨在供终端查看。尝试运行这些命令!curl nytpu.com/gemlog/2026-03-18 # 或者 curl nytpu.com(抱歉 Windows 用户,ANSI 转义码在 cmd.exe 中默认被禁用不是我的错。而且在 Powershell 中必须使用 curl.exe 而不是 curl,因为 Powershell 莫名其妙地将其别名为 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.)
我在 Fediverse 上简单发过相关内容,但除此之外没有多做解释,因为我觉得这相当直观。不过,已经有几个人问我具体是怎么做的,所以我决定写一篇关于实现过程的文章(……虽然晚了七个月)。我需要说明的是,这个想法源自 trinkey (curl trinkey.com) 和 strongsand (curl proot.party) 的 curl 站点,并非我原创。尽管我的实现方式与他们大不相同,但这个绝妙点子的所有功劳都归他们。(更新:遗憾的是,截至 2026 年 10 月 14 日,他们的 curl 版本都已无法使用。)
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[—1 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.
首先,这是更有趣的部分:实际生成发送给客户端的 ANSI 标记文件。我完全手写了索引页面和关于页面。请注意,我相信 trinkey 和 strongsand 是使用 ratatui 库(或类似工具)即时生成它们的,这可能更方便;但对我来说,手写似乎更快捷。我将主要的转义码 ESC[(即 \x1b[)保存在 Vim 寄存器中以便需要时轻松粘贴,并打开了维基百科关于主要图形代码的页面以参考特定的转义码。是的,就是这样。我通过实验确定了自己喜欢的统一风格,并在制作标记化的 curl 页面时参考了我网站的 Gopher 版本。
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.
我的版本值得注意的地方在于,我拥有整个博客的 curl 版本,而不仅仅是一两个页面可用。这完全归功于一个巧合:四年多前,我在自己博客使用的自定义标记语言 Gemroff 中实现了 ANSI 标记纯文本的输出。最初这只是为了方便在写作时于终端预览草稿;但将其接入我的静态网站生成器以立即生成 Curl 版本非常简单。我确实手动编写了一个博客文章的包装模板,以及一个列出文章的索引页面模板,但除此之外,只需在静态网站生成器中增加几行代码即可完成连接。
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.
这就是为什么很难说它“简单”的主要原因!因为对我来说简单,仅仅是因为我使用了完全自定义的标记语言和静态网站生成器,而且我几年前恰好做出了正确的设计选择——例如,我的 SSG 恰好已经支持多种模块化输出格式,而不是像其他 SSG 那样仅支持 HTML,因为我的网站同时托管在 HTTP、Gemini 和 Gopher 上。然而,仅仅为了好玩而提供几个手写页面,对于建立这样的网站来说也是完全可以接受的方式,因为它只是一个巧妙的噱头,没人会真正使用它浏览超过几分钟。
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!
最后一步是将网站的 Curl 版本呈现给任何包含 curl 的用户代理,对我来说,这只是对 Nginx 配置做了一些修改,对于其他服务器,想必也同样简单。我想要的主要功能是一个覆盖头(X-Original: true),这样你仍然可以像随意运行 Curl 的人可能想要的那样获得未修改的 HTTP 响应,而且我希望所有内容仍然以静态方式提供。而且……真的就是这样!正如我所说,当我第一次设置它时,我觉得它相当直观,但它与人们通常使用 Web 服务器或 ANSI 转义码的方式非常不一致,所以我能理解人们的好奇心/困惑从何而来。如果能看到更多网站使用这种技巧会很棒!
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! ↩︎
破折号!人工智能生成的!事实上,我要告诉你,我的标记语言自 2022 年 11 月起就有了用于破折号的显式标记元素。信不信由你:大语言模型是根据从真实作者那里复制的内容训练出来的,所以如果人类作品中没有使用破折号,大语言模型就不会使用它们。还有,难道我要避免在一段话里写二十个括号,以至于我觉得需要用破折号来变换一下吗?不可思议!↩︎