I've been working on Boutique and Bodega for much of the last three months, officially celebrating the launch of Boutique and Bodega v2 today. If you’d like to learn more about what's new you can read about it in this tweet storm, or read a quick rundown below 1. But this post isn't about Boutique and Bodega, it's about the process of building Boutique and Bodega.
If you'd asked me in April if I'd spend three months this year working on an open source project, I would have said no way. I left my job at Twitter to be an indie developer building apps that represent my vision of personal productivity, but life is funny sometimes. Life teaches the same lesson over and over again — you can't predict what'll be important to you at any point in time. I built something to answer my own question, "what does a good SwiftUI architecture would look like?” for my own apps, and that's what came to be Boutique. But Boutique has blossomed into much more than just a new architecture, it's become a whole new way to build persistence layers, SwiftUI apps, and for me its created a community of people who find my work valuable. Boutique has quickly become a key part of my present and future app development plans, while remaining simple and approachable through many iterations. I've already integrated Boutique into more than half a dozen of my own apps, notably without many issues or much work, and every day I hear from people about how they're using it as well.
I can't say it's all been ups though, there have been plenty of downs as well. I’m writing this post not with the intention of convincing you to build an open source project, nor am I trying to dissuade you from participating in open source. I'm aiming to provide a balanced perspective because I would like nothing more than to see you build something that's important to you, to leave your dent in the universe. If that dent takes the shape of open source project then it would be an honor to have provided a head start based on what I've learned, knowing better what to expect than I did.
"Running a successful open source project is just Good Will Hunting in reverse, where you start out as a respected genius and end up being a janitor who gets into fights."— Jens Axboe (@axboe) August 12, 2022
Quote attributed to @cra, and I don't think I've ever seen anything more true posted.
As Big Daddy Kane would say, open source ain't easy. The rapper was ahead of his time, it's hard to believe but he was actually talking about was me and my project planning-related difficulties.
When I started building Boutique it was a library just for me, something meant to provide a solution in the nascent and ambiguous space of SwiftUI app architecture. As I started to show Boutique to people in a private beta I was greeted with great ideas and improvements. I was able to implement their suggestions rather quickly, but nothing could prepare me for the amount of work that it takes to make something that works for the myriad of use cases that a general-purpose data storage library needs to support.
Boutique's public launch was greeted with a lot of praise, and even more ideas. Boutique is intentionally not prescriptive, but it does have a rigid and powerful API. It's meant to be an architectural piece of the puzzle, not something you interact with all the time, but that wasn't always clear to many people who checked it out. People are used to solutions matching their previous mental models, and so they would find clever ways to misuse an API I thought couldn't be misused.
Boutique’s goal is to be the only persistence library your app needs, something I emphasized heavily in every piece of documentation. Everything you need should be provided out the box, but I still saw people adding additional metadata to UserDefaults or their current database rather than building a model to represent additional information and storing it in Boutique. They weren’t wrong but I definitely wouldn’t say they were right, and I came to realize that a part of this confusion emerged from people leaning on old patterns and intuitions. I knew I had to fix that.
I believe that when someone doesn't understand something you’re trying to teach them it means you haven't yet brought them to where they need to be. I resolved to make the v2 API even clearer, sanding down rough edges and making it easier to compose functions, that way you would have less to learn and less to misuse. On top of that I wanted to provide a lot of documentation so people could develop a good mental model, have a lot of help getting started, and even developed step by step tutorials for common problems.
The quality of v2 is much higher, the library is more thought out, but this all took a lot of time and a lot of energy. What had started off as a six week project ballooned into three months of my life. We'll discuss why working on Boutique became emotionally overwhelming in Lesson 3, but it's worth noting that open source adds layers of stress. When you're trying to make something that has wide reach you have to account for answering support requests, writing documentation you don't personally need but will lower support volume, building features you won't use, and more. It will help you become a better developer as we discuss in Lesson 4, but it will absolutely require a lot more time than your intuition tells you it will.
I still have some open questions that I don't have answers for, but they're worth considering if you want to start your own open source project.
- When starting a project without a defined endpoint how do you make good estimates?
- Given the often amorphous nature of an open source project how do you measure progress?
- Knowing your energy and focus are finite resources, how do you choose what to work on?
- What's an ideal pace for you, how can you sustain your energy levels, and how do disconnect and recharge?
- How can you delegate tasks you don't want to do, the ones that may lead you to become a bottleneck?
- How do you get people’s help so you can delegate those tasks?
- How do you lean into your strengths to stay satisfied to avoid burn out?
I’ve been hinting at this for weeks, but the day’s finally arrived. Today I’m announcing not one, but five things. Model View Controller Store, Boutique, Bodega, a blog post, and a demo app that help you learn about all of these. Let’s thread this up! 🧵— ✨ Joe Fabisevich ✨ (@mergesort) June 22, 2022
I launched Boutique, Bodega, and a blog post explaining the idea of a Model View Controller Store architecture together with a tweet storm that went semi-viral. I'd expected to get in front of a few hundred people, but thanks to utility of my projects, the quality of my writing, and creating a compelling thread that showed people the value of my work, a lot of what I had created had resonated with the iOS development community. With the help of friends and community members who’d had watched me working tirelessly for weeks the project ended up reaching beyond my orbit, showing up in popular community newsletters, YouTube videos, and the GitHub team even reached out to me to setup a Twitter Space interview to discuss my open source work. (Scheduled for later this week).
Many things are launched on the internet never to be seen again, but I was committed to pushing Boutique forward knowing that this idea had the potential to change the way people build iOS and Mac apps. Over the coming weeks I leveraged my moderately sized Twitter following to keep people up to date with how v2 development was going. I would tweet about what developing an open source project looks like in real time, the good and the bad. I shared novel use cases for Boutique, people's positive testimonials about using the library, and even leveraged the opportunity to show people cool Swift features that I'd been working with that could help them in their day to day work. This is very aligned with my vision for building my business with a silly name (Red Panda Club). I want to build apps, sell products I genuinely believe will help people be better versions of themselves, and teach people along the way to show them how they too can build amazing things. This is a core belief of mine and a style of content marketing that suits and fulfills me, it's the reason I'm writing posts like this on build.ms.
I can say that the launch was incredibly positive, and I only have one regret. I created my GitHub Sponsors account about a week after the project went live, and that delay taught me that timing is everything. Boutique created a lot of value for people as evidenced by all of the people now using it in their apps, but I only managed to generate $17/month in recurring donations for all the work I’d done. While making money wasn’t my intention (and I honestly never expected random people on the internet to give me money), I wonder if I had pitched my GitHub Sponsors account at launch could I have ridden the wave of virality to build another revenue stream?
Working on Boutique felt very isolating, even with friends, family, and community members following along. I spent almost all of my waking hours working on a project by myself, and even when people asked me about my project there was a level of disconnect in terms of passion. That of course makes sense, this project was everything to me in the moment, and their only connection to Boutique is that they care about me. When you work at a company it really is all about the people. There's a shared sense of camaraderie, or at worst a shared sense of misery. While I would never want to be miserable with others, the only thing worse is being miserable by yourself.
Some personal context
I happened to be going through a lot at the time.
I was seeing doctors multiple times a week for an ongoing all-consuming neurological issue, and fighting with the insane American medical system to get the proper care I needed.
I left my job at Twitter a few months ago to work for myself as an indie developer to both focus on my health and happiness. While I've been very happy with the decision, there have had a lot of adjustments in my life because of that.
My girlfriend and I were looking for a place to move into together (cheers, we did it, I'm so excited. 🎉).
Life events that have made my friends less available, and it was hitting me quite hard emotionally.
To be completely transparent there were days where I was crying from the physical pain and the loneliness of not having time, energy, or emotional space for the people I care so much about. Thank you to my amazing partner for all the support, you are truly a one of a kind person, my one of a kind person.
I don't list all of those experiences because it's what you should expect when you work on an open source project, but you will no doubt have some amount of other responsibilities. And another personal aside, if I'm being completely honest, I'm still surprised by the fact that I was able to build a successful open source project despite all of those obstacles.
When I left my job, I expected to lean on community to fill the void of the meaningful goals and shared experience I used to get from my work. I'm lucky enough to be a member of many supportive communities, locally and online, but the reason I felt so lonely when I was working on Boutique was that community fulfills a different need than friendship, family, or a workplace where I felt very accepted. There aren't many feedback mechanisms in open source, in fact the feedback loop you have isn't very tight and the interactions you have can often feel impersonal in part because they have a transactional nature to them. This is true any time you work by yourself, but an open source project where you’re the only major contributor with no cross-functional counterparts seemed to amplify this feeling even more. I left my employed life so I could foster more connections with people who matter to me, and it stung over and over again to feel more disconnected from people while I worked on something those very same people were using.
Open source isn't designed to foster connection. For example, every time I received a GitHub Issue I felt like I was letting someone down. Without fail every time I responded to someone's questions or bug reports the interaction was incredibly positive, even complimentary of my response. But getting to a solution often required a lot of work, and there was no real tangible reward as the human brain is trained to expect. When you consider the vulnerable act of putting your work out into the world, adding a dash of anxious personality, with a hint of feeling low due to external factors, that's a recipe for negative feelings.
The community did throw me a life preserver when I needed it though. Boutique has been a solid investment into my business, but it also feels really special to hear how my code is being used in people's apps. Every few days someone tells me they've started to use Boutique, tells me about about a novel use case that was made easy thanks to Boutique, but one person left me feeling rather emotional. An iOS developer reached out to me about integrating Boutique into one of his apps. He was working with a physical therapist who's building an app for people dealing with nerve-related issues in their neck, incredibly similar to the neurological issues I've been dealing with. When I told my girlfriend she reminded me that having this kind of personal impact on people is rare, and the next time I'm feeling low I should remember that my code is helping people, sometimes even people who are going through the same struggles I am.
As always she was completely right (please don't use this against me in the future), and for every person who messages me there are others who I'll never hear from. The next time I'm beating myself up over a bug or a deadline I'll remember that there are people who are grateful for my work, and for me.
I believe that you shouldn't write code for the specific purpose of being testable, but that testable code often ends up having a better API surface due to the mindset of thinking about how some code can be tested. I have the same feelings about open source, you shouldn't write code with the intention of open sourcing it, but the practice of writing code as if it could be open sourced leads to higher quality code*** 2. Even if you never intend to open source a piece of code, writing it with the possibility in mind will lead to a well thought out API and a more modular structure. You will be forced to clean up your code, handle errors, and consider use cases that someone may want to layer atop your code.
Beyond the code, there's a lot of work that goes into maintaining a successful open source project. The project management aspect comes to mind, but there are also many technical skills to learn. I'd never used Apple's docc documentation library, but I learned the ins and outs to provide high quality documentation for Boutique v2. I automated the documentation updates by wiring up GitHub Actions, spending a couple of days to learn how to use the tool effectively. I even solidified my understanding of semantic versioning now that I had a wide-reaching project that people depended on, as compared to the devil may care attitude I had before.
There was also a lot to learn based on what Boutique's users were asking for. The first version of my library used files on the file system as a persistence layer, but that proved to be difficult to scale beyond storing a few thousand objects. That drove me to build a version of Boutique that was backed by SQLite, building a fully working prototype in only a few hours. I read everything I could find about SQLite over the next couple of days to optimize my solution, playing into my strength of curiosity and thirst for learning. This would have never arisen organically, and what I learned led to me building the
StorageEngine abstraction that underpins all of Boutique and Bodega now. With this I was able to build a pathway for people who are using databases like Core Data or Realm to use Boutique, a cornerstone of the v2 release. The library is much stronger because of the external feedback I received, including code reviews and contributions. All of this is something that never would have happened if I hadn't open sourced my code, code that is now essential infrastructure for my apps going forward.
I learned a lot over my three months of being an open source developer, and after going through all of that, the truth is I don't think I want to be an open source developer. I'll continue to open source code, but with much less of the commitment that I took upon myself for this project. Boutique and Bodega will continue to be supported, but I won’t be adding new features as the same pace. They don’t need a revolutionary amount of new work, so I’ll mostly focus on my use cases rather than the needs of others going forward. So much more than code goes into building a successful open source project, and while I enjoyed many parts of the project, I was ultimately left unfulfilled in the ways that I want to feel fulfilled as a person.
My love for solving problems and teaching is why I thought open source would be a great fit for me. I learned that there’s more to being an open source maintainer than sharing code and helping people, and unfortunately those other parts don’t motivate me. But that won’t deter me from continuing to open source code because open source is built upon the idea that putting something out in the world can help people in ways you never would have expected. If I come up with a novel idea in the process of building my apps or if I learn something new that I think will be valuable to others, you can be sure I’ll open source it.
For now I’ll go back to my true passion, building my beloved apps and products like Plinky — stay tuned for more on that.
The new version of Boutique brings
- UIKit and AppKit support!
- Two new property wrappers (
@AsyncStoredValue) to help you store individual values
- The ability to chain
.remove()operations, not only providing a simpler and clearer API but notable performance improvements.
- Even more performance gains thanks to Boutique now defaulting to storing items using SQLite. Boutique now has the ability to BYOD, bring your own database. You can now use whatever persistence layer you like, simply by conforming to Bodega's new
StorageEngineprotocol. Whether you’re using Core Data, Realm, or even remote storage solutions like CloudKit you can quickly build a
StorageEnginethat matches your schema and start using Boutique today.
A GIANT asterisk here, this is a completely subjective statement.↩
Joe Fabisevich is an indie developer creating software at Red Panda Club Inc. while writing about design, development, and building a company here at build.ms. Before all that he was working as an iOS developer on societal health issues @Twitter.
Like my writing? You can keep up with it in your favorite RSS reader, or get posts emailed in newsletter form. I promise to never spam you or send you anything other than my posts, it's just a way for you to read my writing wherever's most comfortable for you.
If you'd like to know more, wanna talk, or need some advice, feel free to sign up for office hours at no charge, I'm very friendly. 🙂