MoreRSS

site iconLimboy修改

80 后,曾经热衷于 iOS 开发,推动了响应式编程和组件化开发在国内的发展。曾就职于知乎、花瓣、蘑菇街和字节跳动。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Limboy的 RSS 预览

去喀什旅行

2024-12-01 08:00:00

媳妇儿在小红书上种草了长龙航空的随心飞,于是怂恿我一起买了这个服务。然后就开始寻找目的地,本着第一趟就要赚回本的理念,选择了距离杭州近 5000 公里,中国最西部的城市:喀什。

我对这个城市只停留在「听说过」的阶段,对于当地的美食、美景、风土人情、历史典故等毫无概念,但既然媳妇儿选择了这里,就只能陪着一起去了。当时的心情没什么波动,甚至有点排斥,因为一想到要坐那么久的飞机(我对坐飞机这事有较大的心理障碍,确切来说是「高空」,所以摩天轮也不是我的菜),还要离开熟悉的地方一段时间,就会怀疑这么折腾到底值不值。

结果是,非常值。我跟媳妇儿都已年近 40,没有孩子,平时也都是各忙各的,交集主要是生活上的一些事。当缺少比较强的 hub 来连接彼此时,两人之间的连接感就容易变弱,而旅行是一个很好的可以加强连接、增进友谊的契机。

目的地的选择很重要,最好是双方都不太熟悉的。如果这个地方给两人带来的新奇感程度不一,就不容易有「共振」的体验,而「共同的情绪体验」是亲密关系中很重要的一部分。比如手抓饭,如果都是第一次吃,就能分享这道美食带来的惊艳。还有就是「弱攻略依赖」,也就是不用事先花大力气做好功课,也能有不错的体验,不会有太大的坑。

喀什是个很好的目的地,一方面是这里的美食通常是我们没怎么接触过的,而且确实很不错(印象最深的是石榴,榨成汁后不仅好喝,还营养丰富),另一方面喀什古城很好逛(虽然是淡季,很多店面都关门了,但古城的底蕴还在,在其间溜达还是挺舒适的,尤其是太阳照常上班的日子),还有就是这里的风土人情跟东南沿海差异很大,这种差异也是一个很好的切入点,成为两人茶余饭后的聊天话题。这里的人通常有自己的小买卖,比如开个饭馆、卖当地特产、烤肉等等,有些硬需求常年不变,就会出现从爷爷辈甚至爷爷的爷爷传下来的手艺,比如「爷爷的爷爷的爸爸的囊」、「祖传兄弟凉粉」。

临走的前一天,我们去「爷爷囊」那里,买了四个香菜囊,不远万里(literally),从喀什带到了杭州,算是对这趟旅行的一些回味😂。

独立开发之路:在不确定中寻找确定性

2024-11-11 08:00:00

去年,看了一本印象颇深的书:北方的空地。这本书讲的是一个叫杨柳松的人,推着一辆自行车(交通工具兼载货工具),历经 77 天,独自穿越羌塘无人区的故事。旅途非常艰险,一点小小的意外就可能导致极严重的后果(比如帐篷的地钉被吹走)。但体验独特,风景绝美。看完后,印象最深的除了他的那份胆识、勇气和乐观外,还有那非常严谨的准备工作,让看起来几乎不可能完成的任务成为可能。

然后我就想到了独立开发者,他们也像杨柳松一样,独自走进羌塘,面对诸多的不确定性和艰困的环境,试图从中找到一条出路。我目前还不是一个合格的独立开发者,思考上肯定会有所欠缺,但还是写下来,作为进入这个领域的前期准备工作吧。

理解独立开发的本质

说到独立开发,很多人的第一反应是「自己做一个产品」。但实际上,它是一种特殊形式的创业。特殊在哪里?你需要在极其有限的资源下(通常是一个人、有限的时间和资金),找到一个可持续的商业模式。

这就像是你决定开一家小饭店。不同的是,你不仅要当老板,还要同时担任设计师、厨师、服务员、采购、营销…所有角色。这听起来很累?确实如此。但这种方式也有独特的优势:决策快、运营成本低、方向调整灵活。

寻找适合的战场

在我观察到的案例中,成功的独立开发者往往都很擅长选择合适的战场。这里的”合适”,不是指最大或最热门的市场,而是要找到:

  1. 市场规模适中(足够养活个人/小团队)。
  2. 用户需求明确(愿意付费解决问题)。
  3. 大公司不感兴趣(或者应对不够灵活)。
  4. 技术门槛适中(能做出差异化但又不至于无法实现)。

举几个具体的例子:

沉浸式翻译

沉浸式翻译 是我很喜欢的一款翻译工具,使用几天后,就安利给了周围的朋友。作者 Owen一期访谈中提到,他在看王小波的沉默的大多数时,看到书中有提到萧伯纳的芭巴拉少校 很值得一看,然后他就找到了这本书,书中的中英文排版浏览体验给了他很大的惊喜和启发,最终促成了沉浸式翻译这款工具的诞生。

Pinboard

Pinboard 是一个简单、高效的社交书签服务,由 Maciej Ceglowski 创立。Maciej 的初衷是为用户提供一种可靠的方式保存和组织网络链接,专注于简洁和隐私保护:

  • 现有的书签服务往往过于复杂或充斥广告,Pinboard 选择了简化功能,提供最基础但最实用的书签管理。
  • 目标用户是那些希望高效保存并稍后查找链接的人,尤其是注重隐私的用户。
  • 相较于社交化的书签平台,Pinboard 更专注于个人化的链接管理,用户可以自由选择是否分享。
  • 通过付费订阅模式保持了平台的独立性和清爽的用户体验。

这两款作品的作者都是独立开发,他们找到了合适的战场,其中很重要的一点就是「做自己产品的第一个用户」。

做自己产品的第一个用户

Paul Graham 在 How to Start a Startup 中有提到:

No matter what kind of startup you start, it will probably be a stretch for you, the founders, to understand what users want. The only kind of software you can build without studying users is the sort for which you are the typical user.

无论你启动什么类型的初创公司,对于创始人来说,理解用户的需求可能都是一个挑战。你唯一可以不研究用户就能构建的软件,就是那种你本身就是典型用户的那种。

Pieter LevelsNomad List 的创始人)也说过:「最好的产品灵感来自于解决自己的问题」。当你是自己产品的目标用户时,会获得几个关键优势:

1. 对问题的深刻理解

你不需要想象用户的痛点,因为你就是那个每天都在经历这个问题的人,这种第一手经验无比珍贵。

2. 持续的动力

创业路上最重要的不是灵感乍现的那一刻,而是持续的投入。当你在解决自己的问题时,这种动力会更持久。因为即使项目还没有其他用户,你自己就是受益者。

3. 产品方向的把控

很多决策不需要漫长的讨论和市场调研,因为你对目标场景太熟悉了。这种直觉判断虽然不一定完全准确,但往往能抓住重点。

4. 口碑传播的基础

当你真的解决了自己的问题,你会很自然地想要分享给同样有这个问题的人。这种发自内心的推荐很容易引起共鸣。

快速验证,大胆放弃

即使你吃自己的狗粮,结果仍然可能不如意,比如需求提炼不够精确,产品不够惊艳,缺少推广途径等等。NVIDIA CEO 黄仁勋在早年的一次分享中有提到:

If you want to be successful, I would encourage you to develop a tolerance for failure. However, there’s something crucial about failure: if you fail often enough, you might actually become a failure, which is fundamentally different from being successful. So the real question becomes: how do you teach someone to fail, but fail quickly, and change course the moment they recognize a dead end?

The way to approach this is through what we call “intellectual honesty.” This means continuously assessing whether something makes sense, and if it’s the wrong decision, being willing to change your mind.

To achieve this, you have to nurture a tolerance for risk-taking and teach people how to fail—quickly and with minimal cost. Innovation demands a bit of experimentation; experimentation requires exploration, and exploration inevitably involves failure. Without a tolerance for failure, you’d never experiment; without experimentation, you’d never innovate; and without innovation, you’ll never succeed. Otherwise, you’ll just end up being, well… a dweeb.

如果你想成功,我会鼓励你培养对失败的容忍度。然而,关于失败有一个关键点:如果你经常失败,你实际上可能变成一个失败者,这与成功是根本不同的。所以真正的问题变成了:你如何教会一个人快速失败,并在他们意识到死胡同的那一刻改变方向?

解决这个问题的方法是“诚实”。这意味着持续评估某件事是否合理,如果是错误的决定,愿意改变主意。

要实现这一点,你必须培养对冒险的容忍度,并教会人们如何快速且以最小成本失败。创新需要一点实验;实验需要探索,而探索不可避免地会涉及失败。如果没有对失败的容忍度,你就永远不会实验;没有实验,你就永远不会创新;而没有创新,你就永远不会成功。否则,你只会变成,嗯……一个傻瓜。

「创业最大的风险不是失败,而是在一个错误的方向上消耗太久」。这句话对独立开发者尤其重要。

如何做到快速验证?

确定最小验证集

不是最小可用产品(MVP),而是验证核心假设的最小功能集。比如:

  • 如果你假设用户愿意为更好的翻译体验付费,那么先做一个简单的浏览器插件。
  • 如果你假设开发者需要某个开发工具,可以先写一个命令行版本。
  • 如果你想验证市场需求,甚至可以先用 Notion 页面或者 Excel 表格来模拟(多抓鱼就是从一个微信群和 Excel 开始的)。

设定清晰的指标

在开始前就要明确:什么算成功,什么算失败?例如:

  • 首周激活率 > 30%。
  • 次月留存率 > 40%。
  • 14 天内有 10 个付费用户。

严格控制时间投入

  • 第一个版本控制在 1-2 个月内。
  • 设定明确的评估节点,比如每两周回顾一次。
  • 定期问自己:如果现在不是我在做这个项目,我会建议继续吗?

关于放弃

放弃一个项目往往比坚持更需要勇气。以下是一些值得注意的「放弃信号」:

  • 连续三个月没有明显进展。
  • 用户反馈总是很礼貌但不热情。
  • 每天都在解决技术问题,但产品价值没有提升。
  • 开始觉得这个项目是负担而不是机会。

放弃一个项目不等于前期投入都白费了。过程中获得的经验、技能提升、用户洞察等等,这些都是宝贵的资产。

持续构建护城河

独立开发最大的挑战之一是:如何在资源有限的情况下,建立起竞争优势?答案可能是:持续积累。

个人品牌建设

比如 Tony Dinh

  • 通过博客分享独立开发经历。
  • 在 Twitter 上记录每日进展。
  • 定期发布产品更新和思考。
  • 参与技术社区讨论。

这些持续的输出帮助他:

  • 建立了个人影响力。
  • 吸引了种子用户。
  • 获得了社区反馈。
  • 结识了潜在合作者。

国内的同学可能更加熟悉的 KevinTualatrixBaye,也都非常注重个人品牌建设。曾经 Baye 和小护士的故事,则是另一段佳话了 😂。

知识资产沉淀

每做一个项目,都要注意积累可复用的资源:

  • 技术组件库。
  • 设计系统。
  • 文档模板。
  • 营销材料。
  • 用户研究方法。
  • 定价策略经验。

这些资产会让你的下一个项目启动更快、质量更高。

用户关系

独立开发者最宝贵的资产之一是忠实用户群体:

  • 建立用户社群(Discord、Telegram、微信、小红书等)。
  • 维护邮件列表(国外比较常见)。
  • 建立产品反馈机制。

这些用户不仅会持续给你建议,还会成为你的产品传播者。

构建能力矩阵

独立开发要求多面手,但这不意味着你要样样精通。可以把能力分为 Essential(核心能力) 和 Plus(增强能力):

核心能力

开发能力

  • 至少精通一个技术栈
  • 熟悉常用的开发工具
  • 了解基本的系统架构

产品思维

  • 需求分析能力
  • 用户体验设计
  • 产品规划和迭代

设计能力

  • 了解设计原则
  • 能做出清晰、友好的界面
  • 掌握基本的设计工具

增强能力

市场分析

  • 竞品研究
  • 市场机会判断
  • 用户画像描述

市场营销

  • 内容营销
  • 社群运营
  • 增长策略

商业分析

  • 基础财务知识
  • 定价策略
  • 商业模式设计

常见陷阱及应对

在独立开发的路上,有一些常见的陷阱需要警惕:

过度追求完美

表现:

  • 总觉得还差一点才能发布。
  • 反复修改已经可用的功能。
  • 纠结于细节优化。

解决方案:

  • 设定明确的发布日期。
  • 列出「最小功能集」清单。
  • 告诉自己:发布后还可以继续改进。

技术栈选择困难症

表现:

  • 总觉得现有技术栈不够好。
  • 被新技术吸引注意力。
  • 花太多时间在技术选型上。

解决方案:

  • 优先选择你最熟悉的技术栈。
  • 把新技术放在非核心功能上尝试。
  • 告诉自己:技术只是工具,不是目的。

闭门造车

表现:

  • 很少与用户交流。
  • 凭感觉判断需求。
  • 害怕展示不完善的产品。

解决方案:

  • 建立持续的用户反馈渠道。
  • 加入相关的社群。
  • 勇于展示早期版本。

忽视商业模式

表现:

  • 过于专注技术实现。
  • 没有清晰的变现计划。
  • 对定价犹豫不决。

解决方案:

  • 早期就考虑商业模式。
  • 研究竞品的定价策略。
  • 大胆测试不同的定价方案。

结语

独立开发是一条充满挑战的道路,但也充满机遇和乐趣。关键是要:

  • 选择合适的战场。
  • 持续构建护城河。
  • 持续学习。
  • 做好风险控制。

这道题,没有标准答案,每个人有适合自己的节奏。重要的是在实践中不断学习和调整,直到找到那个真正适合你的机会。

独立开发不是终点,而是一种生活方式的选择。在这条路上,希望你也能找到属于自己的节奏和乐趣。

附注

独立开发产品类型维度对比表

产品类型 维护压力 技术复杂度 运营需求 美感要求 特点说明
实时通讯类 - 需要保证服务稳定性
- 需要处理大量并发
- 用户体验要求高
在线协作工具 - 需要确保数据同步
- 需要处理多人协作场景
- 稳定性要求高
支付相关服务 - 安全性要求极高
- 需要专业资质
- 责任风险大
SaaS工具 - 需要定期更新维护
- 需要处理客户支持
- 相对稳定的收入
社区类产品 - 需要持续运营维护
- 内容管理要求高
- 用户增长是关键
单机游戏 中~高 - 开发周期较长
- 发布后维护较少
- 营销很重要
效率工具 低~中 - 功能性为主
- 用户体验重要
- 竞品较多
开发者工具 - 技术门槛高
- 用户群体专业
- 变现相对容易
设计类工具 - 视觉体验重要
- 专业用户群体
- 需要持续更新
内容平台 - 内容运营重要
- 用户留存是关键
- 需要持续产出
生活工具类 - 界面设计重要
- 功能相对简单
- 用户基数大
数据分析工具 - 专业性要求高
- 准确性要求高
- 需要持续优化
教育类应用 - 内容质量重要
- 需要持续更新
- 用户服务要求高
自动化工具 - 技术门槛高
- 稳定性要求高
- 用户群体专业
主题/模板 - 设计质量重要
- 更新频率低
- 竞争激烈

对于希望进入到独立开发领域的同学,建议从工具类型入手,因为运营成本相对较低,用户需求明确,技术门槛适中,更容易找到自己的节奏。

修改记录

  • 2024/11/13: 添加「独立开发产品类型维度对比表」,帮助更好地选择适合自己的产品类型。

自行车棚效应:我们为什么在小事上纠结,却对大事视而不见?

2024-11-08 08:00:00

想象有一个金融委员会会议,讨论三点议程,要点如下:

  1. 耗资 1000 万英镑建设核电站的提案
  2. 价值 350 英镑的自行车棚提案
  3. 年度咖啡预算 21 英镑的提案

会发生什么?委员会最终在很短的时间内就通过了核电站提案。它太高级了,谁都无法真正深入研究细节,而且大多数成员对这个主题了解不多。即使有人了解,解释起来也非常困难。

讨论很快就转移到自行车棚上。在这个议题上,委员会成员可以更轻松地表达自己的意见。他们都知道什么是自行车棚以及它是什么样子。一些成员开始就屋顶的最佳材料展开激烈辩论,权衡可能的选择。他们讨论自行车棚的时间远远长于讨论发电厂的时间。

最后,委员会讨论第三项:咖啡预算。突然间,每个人都是专家。他们都了解咖啡,并且对其成本和价值有强烈的认识。在人们意识到发生了什么之前,他们讨论 21 英镑咖啡预算的时间比发电厂和自行车棚加起来的时间还要长!最后,委员会没有时间了,决定再次开会来完成分析。每个人离开时都感到满意,为谈话做出了贡献。

这个故事是帕金森在 50 年代提出来的,被称为「帕金森琐事定律」或「自行车棚效应」。其要点是:话题越简单,发表意见的人越多,讨论也越深入。而对超出我们能力范围的事,例如核电站,甚至不会尝试表达意见。总结一句:人们更愿花时间在简单的小事上,而在重大复杂的问题前草草了事。

系统一与系统二:我们的大脑喜欢简单任务

《思考,快与慢》一书中的「系统一」和「系统二」可以很好地解释这种心理。系统一是我们大脑中的自动模式,擅长快速、直觉反应,不费脑力。它是帮我们处理琐事的好帮手,却不适合深思熟虑。相比之下,系统二则负责理性思考和逻辑分析,但它启动起来费时费力,不是我们“下意识”就会用的。

自行车棚的问题之所以那么吸引人,是因为它简单,人人都有话说,系统一完全能胜任。但真正重大的项目,比如一栋楼的整体预算、结构安全这些问题,太复杂,系统一根本应付不来。于是,大脑下意识地选择“避重就轻”,将精力转移到自行车棚这类小事上。小事有一种假装参与感的安慰——我们觉得自己有所贡献了,哪怕实际作用微乎其微。

为什么「自行车棚」让我们痴迷?

究其原因,是因为自行车棚代表了一种心理上的“安全区”。在会议中讨论一个自行车棚的建设方式、颜色,参与者可以迅速提供意见,获得一种控制感和掌控力。这种参与感有一种立即的满足,它让人觉得:我可以主导这个细节,我的意见是重要的。反观那些需要系统二深度分析的复杂问题,听上去就容易让人感到无力,甚至恐惧。大脑自然会倾向于选择让人舒服、轻松的领域,而避开那些让人头疼的大事。

与此同时,自行车棚效应也揭示了我们的“从众心理”。在一个群体中,小事讨论容易形成共识——你说黑色好,我觉得灰色也不错,很快大家就能找到一个共同点,觉得“和谐”。但一旦讨论涉及到真正影响全局的重大决策,必然会产生争议,往往谁都不想打破这种“和谐”。于是,为了避免可能出现的冲突和不适,大家更乐于在细枝末节上“和和气气”地交流,而忽视大局。

我们的 App 和社交媒体如何放大了这种效应?

不仅是在会议中,我们日常生活中的许多行为模式也在强化自行车棚效应。现代 App、社交媒体、游戏,甚至新闻都在迎合我们的系统一。它们通过即时反馈、情绪化内容和算法推荐,让我们沉迷于短期的、简单的信息。刷社交网络时,我们倾向于关注那些轻松、引人注目的内容,而对真正重要的信息或深度思考敬而远之。久而久之,我们的大脑适应了这种“快餐式消费”,开始习惯性地规避复杂问题,随之而来的,就是对小事的无限纠结和讨论。

在这种环境下,自行车棚效应被放大了。面对短暂的成就感、娱乐化的内容,我们的大脑越来越少地启用系统二,更难在重要的问题上花费精力。许多讨论度极高的热点话题,其实本质上只是一些无关痛痒的小事,但我们却乐此不疲地卷入讨论,忽视了那些真正值得关注的议题。

强化系统二,弱化系统一

为了减少对系统一的依赖,我们可以采取一些强化系统二、弱化系统一的行为和习惯,比如:

  • 冥想和正念练习:通过冥想训练自己对当下的关注,有助于减少自动化的反应,增强系统二的控制力。
  • 刻意练习批判性思维:在日常生活中,刻意对各种信息进行分析和质疑,以增强系统二的理性思考能力。
  • 设置延迟决策机制:在面对需要快速做出的决定时,刻意设置一个短暂的等待时间,让系统二有时间介入,避免系统一的冲动反应。比如要去拿手机时,等 3 秒,看是真的需要,还是一个下意识的行为。
  • 学习新技能:学习需要逻辑和分析的新技能,比如编程、复杂数学问题等,可以有效锻炼系统二的能力,提升对复杂问题的处理效率。

如何逆向利用自行车棚效应,让它服务于我们的目标?

既然自行车棚效应源于人们对小事的关注,我们不妨反其道而行之,将其转化为一种积极的工具。毕竟,如果我们可以利用“对小事的投入”来完成一些困难的、有价值的事情,那这个效应就能为我们所用。

1. 将大任务拆解成“小自行车棚”:面对复杂的任务,我们可以把它分解成多个小目标。让自己每次只专注于一个具体的小事,这样既能启动系统一,增强完成感,同时又让系统二有机会在需要时参与进来,理性分析。

2. 利用小成就感,积累完成动力:当我们完成了一个个“小自行车棚”任务时,系统一的“即时成就感”会帮我们维持动力,而系统二则可以在长远规划上给予支持。比如,学习一项新技能时,每天完成一点小目标,逐渐构建整个知识框架,最终达成难以企及的成就。

3. 把目光聚焦在核心小事上:我们可以让自行车棚效应集中在那些重要任务的小步骤上,而不是无关紧要的琐事上。这样可以在核心问题上逐步前进,确保每一步都为最终目标服务。

化繁为简,以小步成大成

人们总是倾向于轻松、简单的选择,这种倾向并非一无是处。它给我们提供了积极的参与感、即时满足和短期成就感,只是我们需要学会如何合理利用这种心理机制。通过有意识地把注意力从琐事转移到更具价值的小目标上,最终可以从“纠结小事”变为“步步为营”,以小步成大成。

下次你在纠结一件小事或对网上的争论上头时,不妨停下来问问自己:“这真的重要吗?” 或许,通过把“自行车棚效应”转化为有利的工具,你会发现自己更愿意投入到那些真正重要的事物中,最终让生活和工作变得更加充实有意义。

最后,还有一个小妙招,是很多年前我不知道在哪里遇到,一直留着的一段话:

朋友们,我的一点切身经验,,如果你觉得某个任务让你特别焦虑,压得你喘不过气来,那么最好的排解方法就是直接去做这事,什么都别管,就是使劲做,努力地推进其进度,这棘手的事情在进度上每发展一点,你的焦虑就会少一分,同时你的焦虑越少,推进的速度也就越快,只要咬紧牙关,不停地推进,总会有解脱的那一天,而且你每完成一个棘手的任务,你或多或少都会比之前牛逼强大那么一点,这件苦差事总是会改变你一些。

洗澡这件小事值得被认真对待

2024-09-24 08:00:00

今天早上(严格说来是近中午了,醒的晚😂)在洗澡的时候,忽然觉得应该将「每天早上洗澡」这件事纳入日程中,因为这是难得的一段不会被打扰,不会使用电子设备,完全属于自己的时间。可以用这段时间做一些微小但又重要的事。

反思昨天的表现

因为是发生不久的事,所以印象也还算深刻,可以回顾昨天哪些事做的比较好,哪些表现跟理想中的自己还有差距,应该如何改进。还可以回顾下昨天学到的一些知识点。

定期 Review 是一件很重要的事,因为生活中的很多决策(包括不决策,比如保持现状)是非理性的,可能是为了规避一些风险,或与身边的人保持同步,或满足一些人的诉求。定期 Review 在做的事,自己的状态,对于实现个人的最优解很有帮助。

‘If today were the last day of my life, would I want to do what I am about to do today?’ If the Answer is ‘no’ for too many days in a row, I know I need to change something.

— You know who

具像化目标

为什么这个目标对你来说很重要,达成路径是否有优化空间,想象实现这个目标后自己的状态,细节越丰富越好。这块我没有成功的经历,但直觉是可行的。Scott Adams 也是通过 Affirmation 取得了很多他自己都认为很不可思议的成就。

The idea behind affirmations is that you simply write down your goals 15 times a day and somehow, as if by magic, coincidences start to build until you achieve your objective against all odds.

过一遍今天要做的事

今天要做哪些事,可以先在脑海里过一遍,每件事大概会占用多长时间,心里也有个数。还可以想下为啥要做这些事,是否贴合自己的目标。

冥想

「冥想」在电子设备和算法统治的当下更具有重要性。它的原理不复杂,实践成本低(找个没人打扰的地方待 10 分钟),但因为正反馈不明显,所以很难长期坚持下来。洗澡时不妨也一并做了,时间可以短一些,比如 5 分钟。


上面这些小事,虽然不难,但也很难坚持下去,因为它们的优先级太低了,还没有 deadline,更没有手机好玩,这种状态用计算机术语描述就是 Starvation:一个低优进程(比如备份),总是被高优进程排挤,结果就是一直没得到运行的机会,一直处于饥饿状态。而洗澡为这些低优进程提供了运行条件,让它们不再挨饿。

Rebuilt this site for the next decade using Astro

2024-09-06 08:00:00

This site previously used Zola as its blog engine (you can read here for more details), along with:

  • Alpine.js: A lightweight Vue.js alternative.
  • Tailwind CSS: A utility-first CSS framework.
  • PocketBase: An open-source realtime backend in one file.
  • Deno: A modern runtime for JavaScript and TypeScript.

This architecture had been running for about 3 years. Mostly satisfied. Zola build fast, its functionality was basically adequate, with Deno, I could write API for frontend page. Using Alpine.js and Tailwind CSS, I could create frontend pages quickly.

However, it wasn’t perfect, mainly for these reasons:

  • My go-to frontend library is React, but it’s hard to combine React and Zola in an elegant way.
  • I want to handle HTTP server, Static Site Generation(SSG), and React in a unified way.
  • This tech stack lacked some features I wanted, such as Server Side Rendering and using Shiki as a code highlighter.

After some investigation, I decided on Astro as my new site engine.

  • It has all the features I wanted in a meta-framework.
  • I’ve seen more and more tech influencers mentioning it favorably.
  • It is listed in the ‘S’ tier in the State of JS 2023 survey.
  • Cloudflare Developers is built using Astro.

However, making this transition wasn’t easy. On one hand, I was familiar with the current tools and workflow. Though it was missing some features, but it was tolerable. On the other hand, it would take time to become familiar with new tools, build a new workflow, and transfer the content.

After a period of deliberation, I decided to make the switch.

Design

The new site is separated into 3 parts: essays, comments and stream. Essays are articles I write on specific topics, stream is mainly for life activities, like books, photos and thoughts. Kind of facebook homepage, but just for myself.

Essays are written in MDX and generated by Astro. Stream contents are stored in PocketBase and rendered dynamically via Astro’s SSR. These contents are created using PocketBase’s built-in GUI. Comments are also stored in PocketBase, using PocketBase’s API.

Development

Astro’s Developer Experience is really good. It may take some time to get familiar with its directory structure, design philosophy and API. But once you get through this stage, you gain power. Thanks to the well-written docs and GitHub issues, whenever I encountered a problem, there was usually a solution.

  • I wanted to provide a full-content RSS feed, but MDX files can only be fully rendered within .astro context. Thanks to the Container API (experimental), I nailed it.
  • I struggled for half a day trying to achieve swap HTML (from server) effects with an .astro component, but it was hard to rebind elements to JS functions. I ended up just using React.
    • You can’t bind js functions to jsx-like syntax, because they are not real DOM elements, and will be serialized, so js functions can’t survive.
    • <script is:inline> can make HTML and scripts stay together, but after you replace the HTML with the new content, old scripts won’t work (cause they were bound to the old DOM).
  • server islands are useful for non-server-related components. They work well for lists, or client-side interactions. When server contents are involved, DOM rebinding becomes an issue.
  • .astro pages are like PHP, but more frontend-friendly.
  • .astro components are handy for MDX.

It took me 5 days (working full-time) to design, develop, and transfer content. It wasn’t easy, but as the foundation for the next decade, it was worth the effort.

Deployment

This site is served on a VPS, so I chose Node as the adapter. In theory, it’s simple to deploy: just run pnpm build and node ./dist/server/entry.mjs, then make Nginx point the domain to the port. But reality taught me a lesson. When I ran pnpm build, it took nearly 8 minutes and failed, due to running out of memory.

My first thought was that it allocated too much memory when optimizing images, so I set limitInputPixels: 10000 (100x100) in astro.config.mjs to tell Sharp not to process large images. It didn’t work.

Then I found someone mentioning a command option --experimental-static-build that might fix this scenario, but still, it didn’t work.

When I only left 1 post for Astro to build, it worked, though it still took about 5 minutes.

I was kinda desperate then, even considering rolling back to Zola, which at least wouldn’t cause these issues. This thought lingered for a while before I decided to overcome the problem.

since it could build on my machine, why not just skip the build process on the server and use my machine’s build result? So I put the dist directory in git, and on the server side, I just ran node ./dist/server/entry.mjs. Guess what? it worked! Though it was a bit quirky.

Just as I thought the mission was complete, something else happened. I wanted to write some cache files to the local disk. So I created a .env file, set the cache path, then built and pushed to the server. Server crashed. After digging into the logs, it turned out the cache path was still my machine’s path instead of server’s path defined in the .env file.

The .env file is read at compile time, not runtime. I could remedy it by replacing all the env content before running, but it would be ugly and could lead to potential bugs.

Just when I was at my wit’s end, Bun saved me. Bun is known for its speed and efficiency, and Astro supports Bun, so I decided to give it a try. I ran bun install and bunx --bun astro build. Literally just these two commands, and it worked!

There were still some minor scenarios to handle (e.g. import.meta.env is different when using Bun), but the deployment section basically came to an end. Bun is not only fast but also resource-efficient. In the future, I will prefer Bun over Node.

Conclusion

Astro as a meta-framework fully meets my requirements. PocketBase, combining data storage and CMS in a single file, is really convenient. I hope this new system can help me create more and better content in the future.

AI 不断发展的时代,人应该做什么

2024-07-22 08:00:00

这篇文章是我与 AI(Claude 3.5 Sonnet) 共创的结果,我贡献了最初的思考,AI 对它进行了完善和补充。以后这种共创模式应该会更加普遍吧。

我的思考

如果我们把 AI 的发展拆分为三个阶段,就能看到 AI 可能带来的影响。

  • 第一阶段:不具备智能的汽车。此时司机具有重要性,因为不仅要会开车,还要知道怎么走,换一个人来很可能就做不到。
  • 第二阶段:自带导航的汽车。此时司机具有一定的重要性,虽然不需要提前知道怎么走,但依然要会开车,多年来积累的行驶经验依然有意义。
  • 第三阶段:自带导航能够自动驾驶的汽车。此时司机不具有重要性,只要告诉它要去哪里就行。

把这个场景拓展到其他领域,就会发现人在其中的参与度和重要性会越来越弱。此时人与人的差异会越来越小,毕竟如果 80% 的事都是 AI 完成的,人与人之间的那些差异实在可以忽略不计。

那么最重要的问题就只剩下两个:

  1. 谁的 AI 更加强大。
  2. 谁的 AI 与自身的集成度更高。

经 AI 完善后的版本

我对 AI 说的第一个 Prompt 是:

以下是我对 AI 的一些思考,你看看有什么地方可以改进或补充的?

[思考内容]

AI 给出了它觉得可以完善的点。然后我让它结合这些点,再重新书写一遍。内容很全面,包含了社会结构变革、伦理道德等。

我让它就「人在 AI 时代应该做什么」这一点展开讲讲。

你能够就「人在 AI 时代应该做什么」这一点展开讲讲么(比如哪些技能是最重要,最优先的)?最好附上一些例子

它罗列出了 6 个点,最后我让它从这些点中挑选最重要、最核心的几个能力。再结合之前的内容,去掉一些不相关的内容,最后的成文如下。


如果我们把AI的发展拆分为几个阶段并类比于汽车的发展,我们就能更清晰地看到AI可能带来的深远影响。

AI发展的阶段

  1. 基础工具阶段:类比于不具备智能的汽车。此时人类操作者极其重要,因为不仅要掌握操作技能,还要具备专业知识。在AI领域,这相当于早期的计算机程序,需要专业人员编写和操作。

  2. 辅助决策阶段:类比于自带导航的汽车。AI开始在特定领域提供决策支持,但人类仍然控制最终决策。人类的经验和判断力仍然至关重要。

  3. 部分自主阶段:这是一个过渡阶段,类比于高级辅助驾驶系统。AI可以在某些情况下自主运作,但人类需要随时准备接管。在更广泛的AI应用中,这可能表现为AI能够处理常规任务,但复杂或异常情况仍需人工干预。

  4. 全面自主阶段:类比于完全自动驾驶的汽车。在这个阶段,AI系统能够在大多数领域独立运作,人类的角色转变为高层次的决策者和系统管理者。

人类角色的转变

随着AI的发展,人类的角色正在发生质的变化:

  • 从”操作者”到”管理者”:人类将更多地专注于制定策略、设定目标和管理AI系统。
  • 从”执行者”到”创造者”:人类将更多地投入到创新、创造性思维和解决复杂问题中。
  • 从”专家”到”通才”:跨学科知识和综合能力将变得更加重要,因为AI可以处理大部分专业性强的具体任务。

新的差异维度

虽然在某些方面人与人之间的差异可能会减小,但新的差异维度可能会出现:

  1. AI协作能力:谁更善于与AI系统协作和沟通。
  2. 创造力和批判性思维:这些人类特有的能力将变得更加珍贵(AI擅长处理已知模式和数据,但在创造全新概念和想法方面仍有局,限能够快速适应新环境和新技术的人将在职场中保持竞争力)。
  3. 适应性和学习能力:在快速变化的环境中,持续学习和适应新技术的能力至关重要(AI可以提供大量信息和初步分析,但人类需要批判性地评估这些信息)。
  4. 情商和人际交往能力:随着AI处理更多技术性任务,人类的软实力将更受重视。

这位 YC tech founder 就是个很好的例子。