教育产品:第一个月
一句话总结
我要重新拾起我的博客课程了。
要点
- 我正在重启我 2020 年的博客课程。
- htmx 相当不错,但并非我心目中完美的样子。
- 我正在为 Is It Keto 寻找买家,那是我以前做的生酮饮食网站。
重启 Hit the Front Page
2020 年,我做了一个关于博客的视频课程,名为 “Hit the Front Page of Hacker News”。我对课程内容很自豪,也收到了学员的正面反馈,但我总觉得没有给它应有的重视。
课程发布时,TinyPilot 正在快速增长,我没有时间推广课程或打磨内容。
在上一篇博文中,我调查了读者希望我接下来做什么。在那些表示想看我教点东西的人当中,结果如下:

上一篇博文中读者调查的结果
对这份数据可以有不同的解读,但我的结论是,人们对让我教授写作技巧尤其感兴趣。让我意外的是,“刻意练习(deliberate practice)”也是热门答案之一,只是热情略低一些。
我决定,既然现有课程已经接近完成,而且按不同算法排名第二或第三,我应该把这套材料翻出来,重新发布一个 2024 年的更新版。
寻找试点班学员
Rob Fitzpatrick 的书 Write Useful Books(《写出有用的书》)深刻影响了我做教育产品的思路。他认为,在发布书籍或视频课程之前,你应该先进行直播教学,因为你要根据真实学生的反馈来迭代。
我和妻子预计八月底迎来我们的第一个孩子,到那时我打算消失几个月陪伴家人。在我考虑这件事的时候,距离预产期大约还有 10 周,而课程为期六周,所以缓冲时间不多。
我写了一段课程简介,发邮件给我的博客订阅者,请有兴趣的人填写一份简短的申请表。有人填完申请后,我会针对他们申请中的内容发送个性化回复,并把付款链接发给他们以锁定名额。
结果如下:
- 1,944 名订阅者收到了关于课程的邮件。
- 11 人填写了调查表表达兴趣。
- 7 人购买了课程。
- 在填写调查表后未报名的 4 人中,有 3 人是因为时间段冲突。
寻找视频平台
我惊讶地发现,视频通话方面其实没有什么能真正替代 Zoom 的可行选择。自从 Zoom 被发现谎报其安全性以来,我就一直避开它,但对于直播课程来说,它似乎是唯一的选择。
过去几年我在工作会议中使用 Jitsi Meet,体验大体不错,但我注意到参加 Zoom 会议时质量更好。我曾希望能找到 Jitsi Meet 的付费版本,但他们所有付费选项的定价都是“联系我们”,这很可能意味着每月至少 1000 美元。
所以,Jitsi 还行,虽然有点笨拙。它不支持录制,所以我的变通办法是:
- 在我的笔记本电脑上主持课堂视频通话。
- 从我的台式机加入通话。
- 在台式机上用普通的屏幕录制软件录制通话。
- 把视频上传到 PicoShare。
- 把 PicoShare 链接通过邮件发给全班。
这比我想要的要复杂,但有个附带好处:我可以看着台式机显示器看到每个人的脸,即使我演示的幻灯片占满了笔记本的整个屏幕。
如果你知道比 Jitsi Meet 更好的替代品,请告诉我。
我是否应该放弃 Hacker News 这个方向?
报名课程的学生中约有一半说他们对 Hacker News 并不特别感兴趣。他们只是喜欢我的写作,想更多地了解我的流程,所以才不顾课程聚焦于 Hacker News 而报了名。
回顾调查数据,人们对写作本身的兴趣似乎大于对写博客的兴趣。而且没有人特别提到 Hacker News。
所以,我在想是否应该放弃 Hacker News 这个方向,转向更宽泛的主题。
我对放弃 Hacker News 的担忧是会失去我的独特优势。有无数人在教博客写作,我觉得自己无法在那个人群中脱颖而出。如果我专门教 Hacker News,我就是这个领域世界上最好的老师,因为没有别人在做这件事。
放弃 Hacker News 方向的另一个问题是,我博客成功的大部分证据都围绕 Hacker News。在个人博主中,我在 Hacker News 上取得了不同寻常的成功。如果我去教一门更泛化的写作课,我的资历就没那么亮眼了。我的博客不赚钱,也没有庞大的订阅数可以炫耀。
与此同时,我认为购买我课程的大多数人是先认识了我这个人,然后才发现我的课程。他们大概不会去搜索“Hacker News 领域的世界顶级专家”。
也许启示是,我不必太担心与一大群人竞争,因为无论如何,通往我课程的路径很可能都是通过我本人或者口碑传播。
这门课按最初的 Hacker News 形式已经完成了 95%,所以我打算先发布这个聚焦 Hacker News 的版本。完成之后,我再把材料改编成更泛化的课程。
学习 htmx
过去两年里,htmx 越来越频繁地出现在我的视野中。我的朋友 Cory Zue 在使用 htmx,这引起了我的兴趣。
很长时间以来,最大的障碍就是我搞不懂 htmx 到底有什么意义。
htmx 官网首页的开头有一句话:“为什么只有 <a> 和 <form> 能发起 HTTP 请求?”读到这句话时,我的反应是:“是啊,那样挺好,但 JavaScript 可以让任何 HTML 元素发出任何类型的请求。难道为了省几行 JavaScript,我就得采用一整套新方法吗?”
最终让 htmx 对我说通了的是《Hypermedia Systems》这本书。它由 htmx 的作者撰写,解释了 htmx 的设计动机,并详细讲解了几个可以使用它的场景。
如果要向四年前的我自己推销 htmx,我会这么说。
我对过去的自己推销 htmx 的说辞
还记得你刚学做网站的时候,是这样写 HTML 的吗?
<form action="/users" method="POST">
<input name="first-name" placeholder="First name" />
<input name="last-name" placeholder="Last name" />
<input type="submit" value="Add user" />
</form>如今你不会这么写了,因为你不想在用户提交表单时重新加载整个页面。整页刷新既慢又让人迷失方向,尤其是当你只想显示一条“用户添加成功”的消息时。而且当服务器拒绝输入时,你也不想清空用户已填的所有内容。
于是,你会转而使用 JavaScript,写成这样:
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("form").addEventListener("submit", (evt) => {
evt.preventDefault(); // Block default submit.
fetch(`/users`, {
method: "POST",
credentials: "include",
headers: {
Accept: "application/json",
},
body: JSON.stringify({
firstName: document.querySelector("[name='first-name']"),
lastName: document.querySelector("[name='last-name']"),
}),
})
.then((response) => {
if (response.ok) {
return response.json();
}
// TODO: Handle errors too.
})
.then((result) => {
// TODO: Handle success.
});
});
});JavaScript 不算多,但每次需要表单都得重写一遍。你可以重构这些重复代码,但那会把 UI 逻辑分散到多个文件中。客户端与服务器的每一次交互都要多一层摩擦。
或者你会转向 React 或 Vue 这样的重型框架,于是你的代码和浏览器呈现的内容之间隔着数不清的 JavaScript 抽象层。
htmx 承诺的,是回归你初学网页制作时的那种简单。你不用再写 HTML 然后把所有逻辑交给 React 或手写的事件处理器,而是把 htmx 引入应用,然后这样写表单:
<form hx-post="/users" hx-target="this">
<input name="first-name" placeholder="First name" />
<input name="last-name" placeholder="Last name" />
<input type="submit" value="Add user" />
</form>然后 htmx 让一切自动运转,无需你编写任何自定义 JavaScript。
到目前为止我对 htmx 的体验
为了试用 htmx,我一直在用 htmx 重写 ScreenJournal 的部分功能。ScreenJournal 是我的开源影评应用。它就像电影版的 Goodreads,或者说像 letterboxd,但是开源的,而且丑。

ScreenJournal 是我用于影评的业余项目 Web 应用。
重写的一个好例子是用 htmx 重新实现通知偏好设置页面。我有一个页面允许用户指定想接收哪些邮件:

ScrenJournal 上控制通知的页面
通知页面原本需要大量自定义 JavaScript 来实现以下功能:
- 通过
fetch提交表单内容而不是重新加载页面。 - 请求进行中时禁用表单输入。
- 请求进行中时显示状态转圈动画。
- 请求失败时显示错误信息。
下面是从原生 JavaScript 迁移到 htmx 的对比:
总代码行数减少了,JavaScript 行数更是大幅减少。它把逻辑从前端移到了后端,这正是我喜欢的,因为我觉得后端代码比 UI 代码更容易测试。
以下是我目前使用 htmx 的一些心得:
htmx 增加了一层抽象,但它很直观
- 用 Vue 和 Angular 时,我完全不知道它们是如何把我的代码变成 Web 应用的。
- 用 htmx 时,它的行为直观到我大概可以根据观察到的运行方式自己重新实现一遍 htmx。
htmx 的错误处理不尽如人意
- htmx 的模型假设你向服务器发送一个请求,然后把服务器的响应放进页面的单个元素中。
- 问题在于,成功时我想替换整个 HTML 表单,但出错时我想保持表单原样,并在表单下方显示错误信息。
- htmx 给出的答案是让服务器直接用用户的全部输入重新渲染 HTML 表单,但我不喜欢这样,因为它是在从头重新渲染本来已经存在的东西,还扩大了 XSS 漏洞的攻击面。
- 我可以通过编写自己的事件处理器来绕过这个问题,但到了那个地步,感觉就有点在和框架较劲了。
htmx 会削弱内容安全策略(CSP)
- 我喜欢把 CSP 作为防止跨站脚本攻击(XSS)的最后一道防线。
- htmx 与 CSP 大体兼容,但由于 htmx 功能太多,攻击者一旦获得写入自定义 HTML 的能力,实际上等同于获得了写入任意 JavaScript 的能力。
- 例如
<form action=/delete-account" method="post" onload="this.submit()">- CSP 会阻止这段代码执行。
<form hx-post="/delete-account" hx-trigger="load">- CSP 会允许这段等效代码执行。
- 用 htmx 仍然可以写出安全的应用,但它确实会让 CSP 无法再作为抵御 XSS 的可靠最后防线。
出售 Is It Keto
我这周注意到,Amazon 某个时候改变了联盟链接的做法,导致 Is It Keto 上 90% 的联盟链接失效了。网站仍能从 Google AdSense 赚钱,但我已经没时间维护它了。
我在寻找愿意购买这个网站的人,如果有其他独立开发者或有志创业者给出不错的报价,我会以低于市场价的价格出售。
收尾
完成了什么?
- 我开始向一小批学员讲授我的博客课程。
- 我把 ScreenJournal 的很多部分移植到 htmx,以此学习了 htmx。
- 我录制了课程的第一份附加内容。
经验教训
- 我对课程绑定 Hacker News 角度的程度没有想象中那么深。
- 如果人们要上我的课,多半是因为喜欢我写的东西,而不是因为课程在 Hacker News 上的表现,所以我应该更多思考这类客户是什么样的。
下个月的目标
- 录制课程中四节课的可发布版本。
- 开始销售新版课程。
求助事项
视频通话平台
如果你有符合以下条件的视频通话平台建议,请告诉我:
- 必须:支持最多 10 名参会者进行 90 分钟的通话。
- 必须:允许参与者无需创建新账号或在设备上安装软件即可加入通话。
- 必须:费用不超过每月 80 美元。
- 最好能有:允许我录制视频通话。
课程平台的使用经验
如果你曾在 Maven 或 Udacity 这类课程平台上担任讲师或学员,欢迎分享你的经验。
随机一篇博客