这是用户在 2024-3-18 12:54 为 https://www.devas.life/tech-choices-for-continuing-indie-development-for-over-7-years/ 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?

Tech stack lessons from my 7+ year indie dev journey
我 7 年多的独立开发之旅中的技术堆栈经验教训

Tech stack lessons from my 7+ year indie dev journey
A dog trying to adapt to technological innovations

It's been 7 years since I've been developing Inkdrop, a Markdown note-taking app. Thanks to its sales, I've been able to make a living from it.
我开发 Markdown 笔记应用程序 Inkdrop 已有 7 年了。由于它的销售,我已经能够靠它谋生了。

In the past, I've written various things about how to sustain indie development from a business or mental perspective, such as "Get A Slow Tempo — Towards Becoming A Long-Running Product" and "I stopped setting a financial goal for my SaaS." This time, I'd like to share my thoughts on the technical aspect - how to keep developing sustainably over the years, focusing on the technology side.
过去,我写过各种关于如何从业务或心理角度维持独立开发的文章,例如“放慢节奏——成为长期运行的产品”和“我不再为我的 SaaS 设定财务目标” ”。这次我想分享一下我对技术方面的想法——这些年来如何持续发展,重点是技术方面。

TL;DR 长话短说

  • Initially, aim to release as fast as possible when choosing a tech stack
  • When in doubt, choose what "sparks joy"
  • Cut it off at a reasonable point and proceed with development
  • Be prepared for your modules to become deprecated/obsolete
  • Old doesn't necessarily mean bad
  • Simplify 简化
  • Learn longevity secrets from long-standing companies called 'Shinise'
  • You can't fully eliminate the element of luck

Initially, aim to release as fast as possible when choosing a tech stack

Development plans and business plans are inseparable. It seems that many solo developers become so engrossed in coding that they fall into perfectionism and end up unable to release, abandoning the project. I understand the desire to create something perfect from the start to amaze everyone. But let's give that up. If you want to make a living through solo development, you must first achieve PMF (Product Market Fit).

PMF essentially means confirming whether your app can make money or adjusting its direction to make it profitable. To achieve PMF, you must release first; otherwise, nothing will start. Just thinking about it won't lead to monetization.

To release as quickly as possible, don't be afraid to adopt the programming language you're familiar with, convenient libraries, frameworks, or templates you already have. Don't worry now whether it's the best long-term choice. The top priority is to create an MVP (Minimum Viable Product) and ship it to the world.
为了尽快发布,不要害怕采用您熟悉的编程语言、方便的库、框架或已有的模板。现在不用担心这是否是最佳的长期选择。首要任务是创建 MVP(最小可行产品)并将其推向世界。

The early days of Stripe (Source: Quora)
Stripe 的早期(来源:Quora)

The first version of Stripe was very rough, and MailChimp v1.0 was also extremely simple. That's fine. Inkdrop's initial version didn't even have a proper settings screen, as I wanted to release it quickly. So I postponed implementing payments and posted on Hacker News to announce a closed beta to recruit testers and gauge reactions.
Stripe 的第一个版本非常粗糙,MailChimp v1.0 也极其简单。没关系。 Inkdrop 的初始版本甚至没有适当的设置屏幕,因为我想快速发布它。因此,我推迟了付款的实施,并在黑客新闻上发布了一个封闭测试版,以招募测试人员并评估反应。

I'm not saying to make something sloppy. Your app should solve a problem. I'm saying to create the minimum necessary to solve that problem.

Ask yourself 问你自己

  • What problem does your app aim to solve?
  • What's the quickest way to implement a solution to that problem?
  • Is what you're currently doing related to solving the problem?
  • Are you spending time impressing others instead of solving the core issue?
  • Do you really need to refactor right now?
  • Are you procrastinating on releasing out of fear?

When in doubt, choose what "sparks joy"

Especially in the early stages, development is a continuous series of choices on which tech stack components to adopt. You may often find yourself struggling with these choices.

I'm frequently asked, "Which is the best, A or B?" For example, "React Native or Flutter?", "Vim or VS Code?", "React or Vue?", etc. These questions often seem to come from beginners, posed without any context or requirements.
经常有人问我:“A 和 B 哪个最好?”例如,“React Native 还是 Flutter?”、“Vim 还是 VS Code?”、“React 还是 Vue?”等等。这些问题似乎通常来自初学者,没有任何背景或要求。

Just as there's no single best life choice for everyone, there's no universally best technology choice either. It's like asking, "Which country (or city) is best to live in?" If someone insists, "You absolutely MUST use XXX!", be wary of their vested interests.

So what criteria should you use to choose? In my opinion, it's whatever "sparks joy" for you. Go with whichever option feels "fun," "enjoyable," or "satisfying" to use, or has a good community vibe, a cool website - anything that intuitively makes you think, "This is great."

Motivation is crucial for solo development. You won't have teammates to encourage you. Conversely, you're free to choose without having to care about the team's opinions. Since you're doing solo development, you might as well pick the option that excites you - it'll be easier to keep going with that momentum. The choice that allows you to keep developing and maintaining your app is, I think, the "best" for you.
动机对于个人发展至关重要。你不会有队友来鼓励你。相反,你可以自由选择,不必关心团队的意见。由于您正在进行单独开发,因此您不妨选择让您兴奋的选项 - 保持这种势头会更容易。我认为,允许您继续开发和维护应用程序的选择对您来说是“最好的”。

Spark Joy? I Don't Understand. Any concrete comparison criteria?

That said, there may be people who don't seek "excitement" from technologies or have never felt excited about them (though I question whether such people are well-suited for indie development). Let me list some relatively objective criteria for comparison:

  1. Quality of official documentation
    • No matter how new or trendy something seems, it's useless if there's no documentation to refer to when you're stuck.
    • Action: Get in the habit of reading official documentation.
  1. Constructive nature of the community
    • Skim through GitHub Issues, forums, and the author's activity on X (Twitter), etc.
      浏览 GitHub Issues、论坛以及作者在 X (Twitter) 上的活动等。
    • Avoid projects where bug reports have been ignored for ages or discussions derail into irrelevant topics.
    • Action: When you encounter issues, get in the habit of checking the official Issues and the author's recent activity.
  1. Activeness of development
    • Dismiss modules whose repositories haven't been updated in six months to a year.
    • Check the 'Insights > Contributors' tab to get a timeline of commit activity and contributor churn (e.g., React Native).
      检查“见解 > 贡献者”选项卡以获取提交活动和贡献者流失的时间表(例如,React Native)。
    • Action: Technology ultimately comes down to people. Focus on the people.

The number of stars tends to reflect novelty or trendiness rather than sustainability, so don't rely on that.

Still, you ultimately can't be sure. Maintainers could get fired or change jobs and no longer have time for their OSS projects. Natural disasters or wars could also impact things. What started out simple could become overly complex and buggy through version upgrades. Your Pull Requests could be ignored. On the other hand, some exceptional people like Evan You or Marijn Haverbeke may defy all negative expectations.
不过,您最终还是无法确定。维护人员可能会被解雇或换工作,并且不再有时间进行他们的开源软件项目。自然灾害或战争也可能产生影响。通过版本升级,一开始简单的事情可能会变得过于复杂和错误。您的拉取请求可能会被忽略。另一方面,一些杰出的人,如 Evan You 或 Marijn Haverbeke,可能会辜负所有的负面期望。

So even after checking the above, it'll only improve your odds by around 5-10% at most. Just keep that in mind.
因此,即使检查完上述内容,最多也只能将您的胜算提高 5-10% 左右。要时刻铭记在心。

Cut it off at a reasonable point and proceed with development

The more you research this stuff, the more confused you can get. You could try out all the candidate stacks one by one and write up Pros & Cons, only to conclude, "Well, there's no 'best' after all..." and end up even more uncertain.

It's better to just make a rough evaluation, go with your gut feeling, and proceed with implementation. The time spent learning by doing will benefit both you and your users more. Sometimes, ignorance can be a driving force. Don't be afraid to not know everything. It's better to "learn by trying" rather than "learn before trying."
最好只是进行粗略的评估,跟随你的直觉,然后继续实施。边做边学的时间将使您和您的用户受益更多。有时,无知可以成为推动力。不要害怕不知道一切。 “通过尝试学习”比“在尝试之前学习”更好。

I believe the "power of ignorance" can sometimes be useful because knowing too much can paralyze you. Not knowing isn't inherently bad.

So pick something exciting, try it out, gain expertise through trial and error, and reevaluate your choice if needed based on that experience.

Be prepared for your modules to become deprecated/obsolete

Once you've released your app, confirmed it's likely to make money, and settled on a direction, it's time to improve quality. At this stage, there's a good chance the libraries and frameworks that were fresh when you started developing have already become obsolete. Or the framework you're using may have had a major version upgrade that broke backward compatibility. In other words, you're already saddled with technical debt. From my experience, this is unavoidable.

Here, trying to find technologies that will "absolutely never become obsolete" is a mistake. Unfortunately, no one can predict the future. For example, the Atom Editor was incredibly popular 7 years ago, but no one foresaw it being discontinued. Inkdrop was based on Atom's internal modules, so I've had to gradually replace them with alternatives (still not done).
在这里,试图寻找“绝对不会过时”的技术是一个错误。不幸的是,没有人能够预测未来。例如,Atom Editor 在 7 年前非常受欢迎,但没有人预见到它会停产。 Inkdrop 基于 Atom 的内部模块,因此我不得不逐渐用替代方案替换它们(尚未完成)。

Conversely, React Native was called an "absurd framework" when it launched, met with skepticism. But now it's adopted by Meta, Microsoft, Amazon, Shopify, Discord, and others. Still, no one can say for sure if it'll never become obsolete.
相反,React Native 在推出时被称为“荒谬的框架”,遭到质疑。但现在它被 Meta、微软、亚马逊、Shopify、Discord 等公司采用。尽管如此,没有人能肯定地说它是否永远不会过时。

You should first acknowledge this reality.

Old doesn't necessarily mean bad

Even old, withering libraries can sometimes keep getting maintained, like jQuery. Or a library might have reached a point of completion and no longer needs maintenance, like Semantic UI. It's wrong to assume everything old should be replaced just because it's old. If it's not actually causing issues, keep using it.
即使是老旧的、日渐枯萎的库有时也可以继续得到维护,比如 jQuery。或者一个库可能已经达到完成点并且不再需要维护,例如语义 UI。仅仅因为旧的东西就认为旧的东西就应该被更换,这是错误的。如果它实际上没有引起问题,请继续使用它。

For example, Inkdrop uses Semantic UI as the UI framework, and some of its components depended on jQuery. As a note-taking app that needs to be highly functional yet lightweight, I needed to reduce such redundant dependencies. So I replaced only the jQuery-dependent parts with my own minimal React implementations. Since it didn't cause any functional issues, it was a very low priority - mostly just self-satisfaction.
例如,Inkdrop使用Semantic UI作为UI框架,并且它的一些组件依赖于jQuery。作为一个需要功能强大且轻量级的笔记应用程序,我需要减少这种冗余的依赖关系。所以我只用我自己的最小 React 实现替换了依赖 jQuery 的部分。由于它没有引起任何功能问题,因此它的优先级非常低 - 主要只是自我满足。

You should avoid reinventing the wheel as much as possible. It's tricky, as you can unconsciously start doing it. After reading the source code of projects like Headless UIRadix UI, and React Aria, I strongly realized that if I casually started reimplementing something like "Just another dropdown," I'd inevitably fall into a bottomless pit. I'd want to punch myself.
您应该尽可能避免重新发明轮子。这很棘手,因为你可能会无意识地开始这样做。在阅读了 Headless UI、Radix UI 和 React Aria 等项目的源代码后,我强烈意识到,如果我不经意地开始重新实现“Just another dropdown”之类的东西,我将不可避免地陷入无底洞。我真想打自己一拳。

Simplify 简化

Products made with a focus on rapid release and speed of feature addition will inevitably end up with redundancies and bloat everywhere. However, once you've achieved PMF and confirmed the business is viable, start refactoring to strip away anything unnecessary. I don't recommend spending too much time on refactoring before achieving PMF - that's not the core issue. Also, around this time, performance will start to matter, and you may receive complaints from users. Consolidate duplicate dependencies across versions, remove unused modules, and understand the internals of libraries you'd previously treated as black boxes to eliminate wasteful processing.
注重快速发布和功能添加速度的产品将不可避免地最终导致到处都是冗余和臃肿。然而,一旦您实现了 PMF 并确认业务可行,就开始重构以去除任何不必要的东西。我不建议在实现 PMF 之前花太多时间进行重构——这不是核心问题。此外,在这个时候,性能将开始变得重要,并且您可能会收到用户的投诉。跨版本整合重复的依赖关系,删除未使用的模块,并了解以前视为黑匣子的库的内部结构,以消除浪费的处理。

On the other hand, dedicating time to refactoring will inevitably slow down your perceived development speed from the outside. You may get scolded, "I can't wait any longer!" Out of a sense of customer service, you might be tempted to hastily tack on shiny new features, but resist that urge. As frustrating as it feels, don't forget to prioritize making your existing happy customers even happier over acquiring new users. Adding features exponentially increases complexity. Are you prepared to keep dealing with that complexity?

Each time you increase the amount of code, your software grows exponentially more complicated.

– DHH, Getting Real – DHH,变得真实

Once you add a feature, it's difficult to walk it back. From here on, you'll need a good sense of balance between maintaining existing implementations and adding new features.

Ask yourself: Would you prefer an app that's feature-rich but slow and unstable, or one that's simple yet lightweight, stable, and snappy?

Learn longevity secrets from long-standing companies called 'Shinise'

As Inkdrop's development surpassed 7 years, I experienced the deprecation of various libraries, and my thinking gradually became more conservative. However, I was unsure if this approach was really okay, so I decided to learn from predecessors who had tackled similar challenges.

By the way, about 90 percent of all businesses worldwide that are more than 100 years old are Japanese. Venerable shops and companies must have overcome the kinds of issues I'm facing now. So to sustain my solo development efforts long-term, I read the following Japanese book:
顺便说一句,全球历史超过 100 年的企业中,约 90% 是日本企业。值得尊敬的商店和公司一定已经解决了我现在面临的各种问题。因此,为了长期维持我的独立开发努力,我阅读了以下日语书籍:

Gekkeikan (月桂冠) is a renowned Japanese sake brewery founded in 1637. While sake breweries may have an image of being rigid and conservative, that's not the case:
月桂冠是日本著名的清酒酿酒厂,成立于 1637 年。虽然清酒酿酒厂可能给人一种刻板保守的印象,但事实并非如此:

In the Meiji era, they introduced science and technology into sake brewing. At a time when barrel aging was prevalent, they developed non-preservative bottled sake, the first in Japan. They also pioneered a year-round, four-season brewing system. In recent years, they've operated a sake brewery in America to spread Japanese sake worldwide, combining steadfastness with innovation - a company embodying both aspects.

You can see their attitude of preserving tradition while continuously embracing technological innovation. Having survived over 300 years, they've lived through both the Industrial and Information Revolutions. Amazing.
你可以看到他们在保留传统的同时不断拥抱技术创新的态度。他们已经生存了 300 多年,经历了工业革命和信息革命。惊人的。

Yamato Intec, a manufacturer of engine and automotive components, was founded in 1584.
Yamato Intec 是一家发动机和汽车零部件制造商,成立于 1584 年。

After joining the company, all employees, including those hired for sales, must experience the casting manufacturing process for five years. This instills in everyone an unparalleled passion for casting and a family-like bond - something I heard repeatedly from many employees in interviews: "a passion for casting" and "a love for casting." It's proof that a dedication to casting is deeply rooted in the company culture.

While fearlessly taking on technological innovations, they never abandon their commitment to casting - this seems to be the secret to their longevity.

It is not the most intellectual of the species that survives; it is not the strongest that survives; but the species that survives is the one that is able best to adapt and adjust to the changing environment in which it finds itself

– Charles Darwin - 查尔斯·达尔文

In evolutionary theory, it's said that organisms capable of adapting to change survive.

Drawing from the wisdom of these predecessors, it seems crucial not to be stuck in conservatism while also boldly embracing technological innovation without losing sight of your core value.

More recently, generative AI has seen remarkable progress. However, change is still happening too quickly, with new developments sprouting up constantly. The emergence of new platforms like Apple Vision Pro is also noteworthy. We must maintain an appropriate distance from such nearby technological advancements while adapting accordingly.
最近,生成式人工智能取得了显着的进展。然而,变化仍然发生得太快,新的发展不断涌现。 Apple Vision Pro 等新平台的出现也值得注意。我们必须与这些邻近的技术进步保持适当的距离,同时做出相应的调整。

Inkdrop's core value is its commitment to plain-text Markdown, offering an offline experience that's lightweight, snappy, and flexible for organizing notes. When adopting new technologies, I want to ensure they truly contribute to this core value. In terms of AI, I recently created video tutorials for the app, featuring a dog mascot as a companion generated through AI voice synthesis. These videos have received positive feedback, pioneering a new edutainment format that allows users to learn while being entertained.
Inkdrop 的核心价值是对纯文本 Markdown 的承诺,提供轻量级、快速且灵活的离线体验来组织笔记。在采用新技术时,我想确保它们真正为这一核心价值做出贡献。在人工智能方面,我最近为该应用程序创建了视频教程,其中以狗吉祥物作为通过人工智能语音合成生成的伴侣。这些视频获得了积极的反馈,开创了一种新的寓教于乐形式,让用户在娱乐的同时学习。

You can't fully eliminate the element of luck

Despite everything written here, no matter how carefully you evaluate, failures will happen. So choose technologies with the assumption that failure is possible.

I'll end by quoting a favorite line from Attack on Titan, courtesy of Levi:


Thank you for reading this far.

If you're looking for an app for technical notes, I'd be delighted if you check out Inkdrop.
如果您正在寻找一个用于技术笔记的应用程序,如果您查看 Inkdrop,我会很高兴。

Hope this article is helpful for your solo development journey!

Read more 阅读更多

A day in the life of an indie developer dad

A day in the life of an indie developer dad

Hi, it's Takuya. It's been a while since I've shared anything about my life, so I thought I'd take a moment to dive into that. I've been living off of my app called Inkdrop for over 7 years. Our child
嗨,我是拓哉。我已经有一段时间没有分享过我的生活了,所以我想我应该花点时间来深入探讨一下。我已经靠我的名为 Inkdrop 的应用程序生活了 7 年多。我们的孩子

By Takuya Matsuyama
My strategy to survive the generative AI era as an indie developer

My strategy to survive the generative AI era as an indie developer

Hi, this is Takuya. What's up? I've been considering a change in the pricing of my app, Inkdrop, and have decided to proceed with it. The new pricing will be increased from $4.9/month ($49.9/year) to $9.8 ($99.8/year), effective February
嗨,我是拓也。这是怎么回事?我一直在考虑更改我的应用程序 Inkdrop 的定价,并决定继续进行。新定价将从 2 月份生效,从 4.9 美元/月(49.9 美元/年)上涨至 9.8 美元(99.8 美元/年)

lock-1 By Takuya Matsuyama 作者:松山卓也
How to build a live email editor using MJML, Pug, and Gulp

How to build a live email editor using MJML, Pug, and Gulp
如何使用 MJML、Pug 和 Gulp 构建实时电子邮件编辑器

Hi, it's Takuya. I've been preparing onboarding newsletters for my app, Inkdrop. In order to achieve a nice-looking email design, I researched several email templates and ended up creating my own. Here is the result: Designing emails is hard because there are so many limitations that
嗨,我是拓哉。我一直在为我的应用程序 Inkdrop 准备入职新闻通讯。为了实现美观的电子邮件设计,我研究了几种电子邮件模板并最终创建了自己的电子邮件模板。结果如下:设计电子邮件很困难,因为有太多限制

By Takuya Matsuyama 作者:松山卓也
Effective Neovim setup for web development towards 2024

Effective Neovim setup for web development towards 2024
面向 2024 年 Web 开发的有效 Neovim 设置

🥳My wallpaper packs are now available! Check out serene imagery from my coding tutorials on the devaslife YouTube channel here: https://www.craftz.dog/wallpapers Hey, what's up? It's Takuya here. It's been a year since I last posted a video about my Neovim
🥳我的壁纸包现已推出!在 devaslife YouTube 频道上查看我的编码教程中的宁静图像:https://www.craftz.dog/wallpapers 嘿,怎么了?这里是拓哉。自从我上次发布有关 Neovim 的视频以来已经过去一年了

lock-1 By Takuya Matsuyama 作者:松山卓也