2024-11-11 08:00:00
去年,看了一本印象颇深的书:北方的空地。这本书讲的是一个叫杨柳松的人,推着一辆自行车(交通工具兼载货工具),历经 77 天,独自穿越羌塘无人区的故事。旅途非常艰险,一点小小的意外就可能导致极严重的后果(比如帐篷的地钉被吹走)。但体验独特,风景绝美。看完后,印象最深的除了他的那份胆识、勇气和乐观外,还有那非常严谨的准备工作,让看起来几乎不可能完成的任务成为可能。
然后我就想到了独立开发者,他们也像杨柳松一样,独自走进羌塘,面对诸多的不确定性和艰困的环境,试图从中找到一条出路。我目前还不是一个合格的独立开发者,思考上肯定会有所欠缺,但还是写下来,作为进入这个领域的前期准备工作吧。
说到独立开发,很多人的第一反应是「自己做一个产品」。但实际上,它是一种特殊形式的创业。特殊在哪里?你需要在极其有限的资源下(通常是一个人、有限的时间和资金),找到一个可持续的商业模式。
这就像是你决定开一家小饭店。不同的是,你不仅要当老板,还要同时担任设计师、厨师、服务员、采购、营销…所有角色。这听起来很累?确实如此。但这种方式也有独特的优势:决策快、运营成本低、方向调整灵活。
在我观察到的案例中,成功的独立开发者往往都很擅长选择合适的战场。这里的”合适”,不是指最大或最热门的市场,而是要找到:
举几个具体的例子:
沉浸式翻译 是我很喜欢的一款翻译工具,使用几天后,就安利给了周围的朋友。作者 Owen 在一期访谈中提到,他在看王小波的沉默的大多数时,看到书中有提到萧伯纳的芭巴拉少校 很值得一看,然后他就找到了这本书,书中的中英文排版浏览体验给了他很大的惊喜和启发,最终促成了沉浸式翻译这款工具的诞生。
Pinboard 是一个简单、高效的社交书签服务,由 Maciej Ceglowski 创立。Maciej 的初衷是为用户提供一种可靠的方式保存和组织网络链接,专注于简洁和隐私保护:
这两款作品的作者都是独立开发,他们找到了合适的战场,其中很重要的一点就是「做自己产品的第一个用户」。
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 Levels(Nomad List 的创始人)也说过:「最好的产品灵感来自于解决自己的问题」。当你是自己产品的目标用户时,会获得几个关键优势:
你不需要想象用户的痛点,因为你就是那个每天都在经历这个问题的人,这种第一手经验无比珍贵。
创业路上最重要的不是灵感乍现的那一刻,而是持续的投入。当你在解决自己的问题时,这种动力会更持久。因为即使项目还没有其他用户,你自己就是受益者。
很多决策不需要漫长的讨论和市场调研,因为你对目标场景太熟悉了。这种直觉判断虽然不一定完全准确,但往往能抓住重点。
当你真的解决了自己的问题,你会很自然地想要分享给同样有这个问题的人。这种发自内心的推荐很容易引起共鸣。
即使你吃自己的狗粮,结果仍然可能不如意,比如需求提炼不够精确,产品不够惊艳,缺少推广途径等等。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),而是验证核心假设的最小功能集。比如:
在开始前就要明确:什么算成功,什么算失败?例如:
放弃一个项目往往比坚持更需要勇气。以下是一些值得注意的「放弃信号」:
放弃一个项目不等于前期投入都白费了。过程中获得的经验、技能提升、用户洞察等等,这些都是宝贵的资产。
独立开发最大的挑战之一是:如何在资源有限的情况下,建立起竞争优势?答案可能是:持续积累。
比如 Tony Dinh
这些持续的输出帮助他:
国内的同学可能更加熟悉的 Kevin、Tualatrix、Baye,也都非常注重个人品牌建设。曾经 Baye 和小护士的故事,则是另一段佳话了 😂。
每做一个项目,都要注意积累可复用的资源:
这些资产会让你的下一个项目启动更快、质量更高。
独立开发者最宝贵的资产之一是忠实用户群体:
这些用户不仅会持续给你建议,还会成为你的产品传播者。
独立开发要求多面手,但这不意味着你要样样精通。可以把能力分为 Essential(核心能力) 和 Plus(增强能力):
在独立开发的路上,有一些常见的陷阱需要警惕:
表现:
解决方案:
表现:
解决方案:
表现:
解决方案:
表现:
解决方案:
独立开发是一条充满挑战的道路,但也充满机遇和乐趣。关键是要:
这道题,没有标准答案,每个人有适合自己的节奏。重要的是在实践中不断学习和调整,直到找到那个真正适合你的机会。
独立开发不是终点,而是一种生活方式的选择。在这条路上,希望你也能找到属于自己的节奏和乐趣。
产品类型 | 维护压力 | 技术复杂度 | 运营需求 | 美感要求 | 特点说明 |
---|---|---|---|---|---|
实时通讯类 | 高 | 高 | 高 | 中 | - 需要保证服务稳定性 - 需要处理大量并发 - 用户体验要求高 |
在线协作工具 | 高 | 高 | 中 | 中 | - 需要确保数据同步 - 需要处理多人协作场景 - 稳定性要求高 |
支付相关服务 | 高 | 高 | 中 | 低 | - 安全性要求极高 - 需要专业资质 - 责任风险大 |
SaaS工具 | 中 | 中 | 中 | 中 | - 需要定期更新维护 - 需要处理客户支持 - 相对稳定的收入 |
社区类产品 | 中 | 中 | 高 | 中 | - 需要持续运营维护 - 内容管理要求高 - 用户增长是关键 |
单机游戏 | 低 | 中~高 | 低 | 高 | - 开发周期较长 - 发布后维护较少 - 营销很重要 |
效率工具 | 低 | 低~中 | 低 | 高 | - 功能性为主 - 用户体验重要 - 竞品较多 |
开发者工具 | 低 | 高 | 低 | 低 | - 技术门槛高 - 用户群体专业 - 变现相对容易 |
设计类工具 | 低 | 中 | 低 | 高 | - 视觉体验重要 - 专业用户群体 - 需要持续更新 |
内容平台 | 中 | 中 | 高 | 中 | - 内容运营重要 - 用户留存是关键 - 需要持续产出 |
生活工具类 | 低 | 低 | 低 | 高 | - 界面设计重要 - 功能相对简单 - 用户基数大 |
数据分析工具 | 中 | 高 | 中 | 中 | - 专业性要求高 - 准确性要求高 - 需要持续优化 |
教育类应用 | 中 | 中 | 高 | 中 | - 内容质量重要 - 需要持续更新 - 用户服务要求高 |
自动化工具 | 低 | 高 | 低 | 低 | - 技术门槛高 - 稳定性要求高 - 用户群体专业 |
主题/模板 | 低 | 低 | 低 | 高 | - 设计质量重要 - 更新频率低 - 竞争激烈 |
对于希望进入到独立开发领域的同学,建议从工具类型入手,因为运营成本相对较低,用户需求明确,技术门槛适中,更容易找到自己的节奏。
2024-11-08 08:00:00
想象有一个金融委员会会议,讨论三点议程,要点如下:
会发生什么?委员会最终在很短的时间内就通过了核电站提案。它太高级了,谁都无法真正深入研究细节,而且大多数成员对这个主题了解不多。即使有人了解,解释起来也非常困难。
讨论很快就转移到自行车棚上。在这个议题上,委员会成员可以更轻松地表达自己的意见。他们都知道什么是自行车棚以及它是什么样子。一些成员开始就屋顶的最佳材料展开激烈辩论,权衡可能的选择。他们讨论自行车棚的时间远远长于讨论发电厂的时间。
最后,委员会讨论第三项:咖啡预算。突然间,每个人都是专家。他们都了解咖啡,并且对其成本和价值有强烈的认识。在人们意识到发生了什么之前,他们讨论 21 英镑咖啡预算的时间比发电厂和自行车棚加起来的时间还要长!最后,委员会没有时间了,决定再次开会来完成分析。每个人离开时都感到满意,为谈话做出了贡献。
这个故事是帕金森在 50 年代提出来的,被称为「帕金森琐事定律」或「自行车棚效应」。其要点是:话题越简单,发表意见的人越多,讨论也越深入。而对超出我们能力范围的事,例如核电站,甚至不会尝试表达意见。总结一句:人们更愿花时间在简单的小事上,而在重大复杂的问题前草草了事。
《思考,快与慢》一书中的「系统一」和「系统二」可以很好地解释这种心理。系统一是我们大脑中的自动模式,擅长快速、直觉反应,不费脑力。它是帮我们处理琐事的好帮手,却不适合深思熟虑。相比之下,系统二则负责理性思考和逻辑分析,但它启动起来费时费力,不是我们“下意识”就会用的。
自行车棚的问题之所以那么吸引人,是因为它简单,人人都有话说,系统一完全能胜任。但真正重大的项目,比如一栋楼的整体预算、结构安全这些问题,太复杂,系统一根本应付不来。于是,大脑下意识地选择“避重就轻”,将精力转移到自行车棚这类小事上。小事有一种假装参与感的安慰——我们觉得自己有所贡献了,哪怕实际作用微乎其微。
究其原因,是因为自行车棚代表了一种心理上的“安全区”。在会议中讨论一个自行车棚的建设方式、颜色,参与者可以迅速提供意见,获得一种控制感和掌控力。这种参与感有一种立即的满足,它让人觉得:我可以主导这个细节,我的意见是重要的。反观那些需要系统二深度分析的复杂问题,听上去就容易让人感到无力,甚至恐惧。大脑自然会倾向于选择让人舒服、轻松的领域,而避开那些让人头疼的大事。
与此同时,自行车棚效应也揭示了我们的“从众心理”。在一个群体中,小事讨论容易形成共识——你说黑色好,我觉得灰色也不错,很快大家就能找到一个共同点,觉得“和谐”。但一旦讨论涉及到真正影响全局的重大决策,必然会产生争议,往往谁都不想打破这种“和谐”。于是,为了避免可能出现的冲突和不适,大家更乐于在细枝末节上“和和气气”地交流,而忽视大局。
不仅是在会议中,我们日常生活中的许多行为模式也在强化自行车棚效应。现代 App、社交媒体、游戏,甚至新闻都在迎合我们的系统一。它们通过即时反馈、情绪化内容和算法推荐,让我们沉迷于短期的、简单的信息。刷社交网络时,我们倾向于关注那些轻松、引人注目的内容,而对真正重要的信息或深度思考敬而远之。久而久之,我们的大脑适应了这种“快餐式消费”,开始习惯性地规避复杂问题,随之而来的,就是对小事的无限纠结和讨论。
在这种环境下,自行车棚效应被放大了。面对短暂的成就感、娱乐化的内容,我们的大脑越来越少地启用系统二,更难在重要的问题上花费精力。许多讨论度极高的热点话题,其实本质上只是一些无关痛痒的小事,但我们却乐此不疲地卷入讨论,忽视了那些真正值得关注的议题。
为了减少对系统一的依赖,我们可以采取一些强化系统二、弱化系统一的行为和习惯,比如:
既然自行车棚效应源于人们对小事的关注,我们不妨反其道而行之,将其转化为一种积极的工具。毕竟,如果我们可以利用“对小事的投入”来完成一些困难的、有价值的事情,那这个效应就能为我们所用。
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:一个低优进程(比如备份),总是被高优进程排挤,结果就是一直没得到运行的机会,一直处于饥饿状态。而洗澡为这些低优进程提供了运行条件,让它们不再挨饿。
2024-09-06 08:00:00
This site previously used Zola as its blog engine (you can read here for more details), along with:
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:
After some investigation, I decided on Astro as my new site engine.
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.
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.
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.
.astro
context. Thanks to the Container API (experimental), I nailed it..astro
component, but it was hard to rebind elements to JS functions. I ended up just using React.
<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)..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.
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.
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.
2024-07-22 08:00:00
这篇文章是我与 AI(Claude 3.5 Sonnet) 共创的结果,我贡献了最初的思考,AI 对它进行了完善和补充。以后这种共创模式应该会更加普遍吧。
如果我们把 AI 的发展拆分为三个阶段,就能看到 AI 可能带来的影响。
把这个场景拓展到其他领域,就会发现人在其中的参与度和重要性会越来越弱。此时人与人的差异会越来越小,毕竟如果 80% 的事都是 AI 完成的,人与人之间的那些差异实在可以忽略不计。
那么最重要的问题就只剩下两个:
我对 AI 说的第一个 Prompt 是:
以下是我对 AI 的一些思考,你看看有什么地方可以改进或补充的?
[思考内容]
AI 给出了它觉得可以完善的点。然后我让它结合这些点,再重新书写一遍。内容很全面,包含了社会结构变革、伦理道德等。
我让它就「人在 AI 时代应该做什么」这一点展开讲讲。
你能够就「人在 AI 时代应该做什么」这一点展开讲讲么(比如哪些技能是最重要,最优先的)?最好附上一些例子
它罗列出了 6 个点,最后我让它从这些点中挑选最重要、最核心的几个能力。再结合之前的内容,去掉一些不相关的内容,最后的成文如下。
如果我们把AI的发展拆分为几个阶段并类比于汽车的发展,我们就能更清晰地看到AI可能带来的深远影响。
基础工具阶段:类比于不具备智能的汽车。此时人类操作者极其重要,因为不仅要掌握操作技能,还要具备专业知识。在AI领域,这相当于早期的计算机程序,需要专业人员编写和操作。
辅助决策阶段:类比于自带导航的汽车。AI开始在特定领域提供决策支持,但人类仍然控制最终决策。人类的经验和判断力仍然至关重要。
部分自主阶段:这是一个过渡阶段,类比于高级辅助驾驶系统。AI可以在某些情况下自主运作,但人类需要随时准备接管。在更广泛的AI应用中,这可能表现为AI能够处理常规任务,但复杂或异常情况仍需人工干预。
全面自主阶段:类比于完全自动驾驶的汽车。在这个阶段,AI系统能够在大多数领域独立运作,人类的角色转变为高层次的决策者和系统管理者。
随着AI的发展,人类的角色正在发生质的变化:
虽然在某些方面人与人之间的差异可能会减小,但新的差异维度可能会出现:
这位 YC tech founder 就是个很好的例子。