0x00 前情提要
什么是 Twtxt?
Twtxt 是一种极简的纯文本微型博客服务,灵感来源于 Twitter,但完全由用户自主掌控数据,没有中心化的服务器或公司控制。它的设计哲学是简单、隐私优先和去中心化,适合喜欢技术自主性和对隐私敏感的用户。
Twtxt 通过简单的文本文件(称为「Feeds」)运行,每个文件包含一个用户的状态更新。这些文件通常由 Web 服务器提供,并通过 URL 访问。
尽管该项目标榜为网络服务,但实际使用时需要用户自行将程序部署到服务器环境中。名为 twtxt 的工具主要具备两大功能:其一,能够将用户的推文内容写入指定的 twtxt.txt 文本文件;其二,支持从互联网上的其他 twtxt.txt 文件(即其他用户的动态源)进行内容获取与阅读操作。
Twtxt 出现多久了?
Twtxt 最先由 @buckket 于 ~2016 年设计和开发,目前主流版本是 Twtxt v2,由社区驱动开发拓展。
Twtxt 的文件格式是怎么样的?
一个 Twtxt 源包含每行一个状态更新。每行以一个 RFC3339 日期时间字符串开头,后跟一个制表符(\t)将其与实际文本分开(建议将新的状态追加到文件末尾)。
该文件必须使用 UTF-8 编码,并使用 LF(\n)作为行分隔符。一个源通常以元数据开头,可能包括用户的昵称、头像和可选的描述。建议用空行将元数据与状态分开。
给个示例看看?
你可以在我 博客的 Twtxt Feed 找到一个合法的示例,也欢迎在你的 Twtxt 客户端订阅我的博客~
# nick = example
# url = https://example.com/twtxt.txt
# avatar = https://example.com/avatar.png
# description = An example feed
2024-09-29T13:30:00Z Hello World!
2024-09-29T13:40:00Z (#ohmmloa) Is anyone alive? 🤔
0x01 为博客添加一个 Twtxt
请注意:本部分内容因框架升级已过时,仅供参考,请以最新信息为准。
我的博客使用 Astro 构建,所以我需要在 /src/pages 下创建一个 twtxt.txt.ts 文件,在里面使用标准 API 构建我们的 Twtxt:
import { getCollection } from "astro:content";
import getSortedPosts from "@utils/getSortedPosts";
import { SITE } from "@config";
export async function GET() {
const posts = await getCollection("blog");
const sortedPosts = getSortedPosts(posts);
const twtxt = sortedPosts
.map(
({ data, slug }) =>
`${new Date(data.modDatetime ?? data.pubDatetime).toISOString()}\t${data.title} ${SITE.website}post/${slug}`
)
.join("\n");
return new Response(twtxt, {
headers: {
"Content-Type": "text/plain",
},
});
}
这是我的第一版代码,这会输出一个基本可用的框架(不过还没有任何的元数据,我们接下来会添加),接下来讲讲怎么在 Yarn 里订阅。
0x02 在 Yarn.social 里订阅博客
刷新博客缓存后,我们便可以在 Yarn.social 实例里订阅了,这里以 XMSL TwT 为例:

导航到 /feeds,在 Follow 框上输入我们的 Twtxt 地址:

随后回到主页,我们便可以查看到来自博客的文章了:

很棒,我们来为文章加点元数据吧:
0x03 优化我们的 Twtxt
废话不多说,我们直接上代码:
import { getCollection } from "astro:content";
import getSortedPosts from "@utils/getSortedPosts";
import { SITE } from "@config";
export async function GET() {
const posts = await getCollection("blog");
const sortedPosts = getSortedPosts(posts);
// 构建注释部分(以 # 开头)
const comments = [
"# Twtxt is an open, distributed microblogging platform that",
"# uses human-readable text files, common transport protocols,",
"# and free software.",
"#",
"# Learn more about twtxt at this links:",
"# * https://twtxt.readthedocs.io/en/stable/",
"# * https://twtxt.net",
"# * https://twtxt.dev",
"#",
`# nick = liuzhen932_blog`,
`# url = ${SITE.website}twtxt.txt`,
`# link = Website ${SITE.website}`,
`# avatar = ${SITE.website}favicon.png`,
`# description = ${SITE.desc}`,
`# type = rss`,
`# follow = liuzhen932 https://twt.xmsl.im/user/liuzhen932/twtxt.txt`,
"",
];
// 构建帖子内容部分
const postsContent = sortedPosts.map(({ data, slug }) => {
return `${new Date(data.modDatetime ?? data.pubDatetime).toISOString()}\t**${data.title}** ${data.description} ⌘ [Read more](${SITE.website}post/${slug})`;
});
// 合并注释和帖子内容
const twtxt = [...comments, ...postsContent].join("\n");
return new Response(twtxt, {
headers: {
"Content-Type": "text/plain",
},
});
}
这段代码通过 Astro Content API 动态生成符合 Twtxt 标准的文本文件(.txt),将博客文章以 Twtxt 格式输出。
元数据部分:定义 Twtxt 的身份与配置
const comments = [
"# nick = liuzhen932_blog",
`# url = ${SITE.website}twtxt.txt`,
`# avatar = ${SITE.website}favicon.png`,
`# description = ${SITE.desc}`,
`# follow = https://twt.xmsl.im/user/liuzhen932/twtxt.txt`,
"",
];
作用:
nick:你的 Twtxt 昵称,用于标识身份。url:Twtxt 文件的公开地址,供其他用户订阅。avatar:个人头像链接(需为公开可访问的 URL)。description:个人简介,展示在 Twtxt 客户端中。follow:你关注的其他 Twtxt 用户的链接(可添加多个)。
内容部分:将博客文章转换为 Twtxt 格式
const postsContent = sortedPosts.map(({ data, slug }) => {
const timestamp = new Date(
data.modDatetime ?? data.pubDatetime
).toISOString();
return `${timestamp}\t**${data.title}** ${data.description} ⌘ [Read more](${SITE.website}post/${slug})`;
});
响应生成:输出符合标准的文本文件
将元数据和文章内容拼接成一个纯文本字符串,通过 Response 对象返回文本内容,设置 Content-Type: text/plain 确保客户端能正确解析。
const twtxt = [...comments, ...postsContent].join("\n");
return new Response(twtxt, {
headers: {
"Content-Type": "text/plain",
},
});

0x04 总结
本文详细介绍了如何在个人博客中集成 Twtxt 这一去中心化微型博客系统。Twtxt 是一种基于纯文本文件的极简微博客格式,通过简单的文本文件实现自主可控的内容发布。作者以 Astro 框架为例,演示了如何通过动态生成 Twtxt 文本文件,将博客文章转化为 Twtxt 格式。此外,作者展示了如何在 Yarn.social 等平台订阅自己的 Twtxt feed,并优化内容呈现形式,例如添加文章标题、摘要及跳转链接。文章还强调了 Twtxt 的去中心化特性与隐私优势,通过元数据配置和内容格式化,实现了博客与 Twtxt 生态的无缝衔接。最终,用户可通过客户端实时查看博客更新,体现了 Twtxt 在技术自主性和内容分发上的灵活性。
好了,这就是今天的全部内容了,如果有任何内容欢迎留言反馈~ 我先去睡觉啦!