{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":"app","path":"app","contentType":"directory"},{"name":"build","path":"build","contentType":"directory"},{"name":"scripts","path":"scripts","contentType":"directory"},{"name":"tests","path":"tests","contentType":"directory"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".eslintrc","path":".eslintrc","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"SECURITY.md","path":"SECURITY.md","contentType":"file"},{"name":"appveyor.yml","path":"appveyor.yml","contentType":"file"},{"name":"archive-notice.md","path":"archive-notice.md","contentType":"file"},{"name":"build-notes.md","path":"build-notes.md","contentType":"file"},{"name":"screenshot.png","path":"screenshot.png","contentType":"file"}],"totalCount":17}},"fileTreeProcessingTime":3.033917,"foldersToFetch":[],"repo":{"id":59700207,"defaultBranch":"master","name":"beaker","ownerLogin":"beakerbrowser","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2016-05-25T21:51:48.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/22504804?v=4","public":true,"private":false,"isOrgOwned":true},"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"master","listCacheKey":"v0:1672177469.071583","canEdit":false,"refType":"branch","currentOid":"764bdefeeed9558dbf10aec77df262a896f57236"},"path":"archive-notice.md","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/beakerbrowser/beaker/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"archive-notice.md","displayUrl":"https://github.com/beakerbrowser/beaker/blob/master/archive-notice.md?raw=true","headerInfo":{"blobSize":"16.4 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"be86959","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fbeakerbrowser%2Fbeaker%2Fblob%2Fmaster%2Farchive-notice.md","isCSV":false,"isRichtext":true,"toc":[{"level":1,"text":"Beaker Browser is now archived","anchor":"beaker-browser-is-now-archived","htmlText":"Beaker Browser is now archived"},{"level":2,"text":"The story","anchor":"the-story","htmlText":"The story"},{"level":2,"text":"Lessons learned","anchor":"lessons-learned","htmlText":"Lessons learned"},{"level":2,"text":"Other thoughts","anchor":"other-thoughts","htmlText":"Other thoughts"},{"level":2,"text":"Farewell, Beaker","anchor":"farewell-beaker","htmlText":"Farewell, Beaker"}],"lineInfo":{"truncatedLoc":"107","truncatedSloc":"59"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/beakerbrowser/beaker/blob/master/archive-notice.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/beakerbrowser/beaker/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/beakerbrowser/beaker/raw/master/archive-notice.md","renderImageOrRaw":false,"richText":"

Beaker Browser is now archived

\n

Dec 27, 2022

\n

Hi friends! This won't come as a huge shock, but the time has finally come that I archive the Beaker Browser repo. In 2022 I moved on to working at Bluesky, and, while the Beaker project is coming to an official end, the heart of Beaker continues with Bluesky. I hope the work we do will make Beaker's end a little less painful in the long run.

\n

I'm going to share a post-mortem in this doc, but first I want to thank everybody for the years of incredible support, kindness, and generosity. It was truly overwhelming, and at times I felt it was much more than I deserved. This includes all of the OpenCollective and Patreon donors and the handful of angel investors who put their faith in this project. Again, I hope the future work with Bluesky helps repay your faith and support.

\n

In particular, I want to thank:

\n\n

I almost hesitate to try to enumerate these special callouts because you all deserve to be named. Needless to say, I'm in your debt and am always available if you want to reach out.

\n

The story

\n

The backstory to Beaker starts with Secure Scuttlebutt (SSB). I had been working on applications for SSB for about two years (2014-2016) and really getting my feet wet with decentralized tech. A number of exciting \"bittorrent-variant\" protocols were coming about at that time, including IPFS and Dat (eventually renamed Hypercore), and we were all working on how to make these protocols really shine.

\n

The broad mission was to decentralize the Web. With SSB, we had made a social-networking protocol that was local first (meaning it ran mostly on-device) and was therefore extremely hackable. We wanted it to be very easy for people to build upon it.

\n

The problem as I saw it was that app-distribution was too hard. Most of the SSB clients at the time were built on Electron or were local-hosted web servers. I wanted apps to be as easy to load as websites.

\n

This is how the idea for Beaker started. If apps could be distributed with one of these bittorrent-variants, I figured, and then run within a safe sandbox, then we'd be able to create a flourishing ecosystem of apps on shared decentralized network. That was the big premise.

\n

Electron was beginning to mature, and I figured it would help accelerate the development of a niche browser like Beaker, and it did. I was able to produce a demo of Beaker hosting websites via dat/hypercore within 2 weeks. This got a positive response from folks (because it is pretty cool) and so I continued from there. I built in tools for building the websites in-browser. \"One click to make a website\" was the premise, and it worked great. It gave great demos at talks, and pretty soon I was able to convince Tara to cofound a company with me around the project.

\n

People gave very positive feedback to the demo, but since this isn't a success story you can probably guess what happened next: actual usage stalled. We would produce updates that improved the polish and usability of the browser, and there'd be a small bump, but no stickiness. I indulged in fun features like a web-based commandline in the browser which was certainly cool but did nothing to make the browser useful to people. Many of these features lived in a perpetually half-finished state, and we could never quite solve the stickiness problem.

\n

This feature churn ultimately landed Beaker an entry in Liron Shapira's \"Bloated MVP\" blog, and give that a read because I think Liron is pretty spot-on with his analysis. It was a classic product dilemma; we were failing to give users something they wanted, and the flailing was just adding bloat instead of solving the real problem: that Beaker didn't solve a problem for people.

\n

To our credit, we weren't completely blind to the issues. We had a gordian knot of problems that each fed into each other:

\n\n

The first three items were intractable given the resources we had, so I decided to focus on the fourth: API tooling. I figured if we could give a compelling dev experience on desktop, we could create a foothold niche that could help us gain the resources needed to tackle the other problems. In the four years of active development on Beaker, the last 2 were spent focused on those APIs.

\n

On the APIs, I quite simply failed. The pure P2P model gives you a set of really great wins - no backend/frontend separation, local data, offline-first, easily-forked apps, and so on - but then hits you with a cavalcade of challenges. Without some logically centralized repository of data or router of messages, you struggle with discovery and delivery. Users don't stay consistently online and connections will randomly fail, so you stuggle with availability and performance. Initial connections and thus time-to-first-paints are slow, which is very bad news for web browsing. Debugging is quite hard. Managing resource usage on the device is hard. Scaling a user's view of the network past (say) 100k users is pretty much out the window because you're not sharing indexes; rather, you're having each device build the indexes locally. I'm probably forgetting some things, but you get the idea.

\n

Another huge challenge is producing Web APIs that users are comfortable with. People are extremely protective of the Web platform. When you start injecting these novel APIs, there's a sense that the APIs have to really be right because we might soon be stuck with them. That's a tough target to hit, and we suffered some design churn because of it. I was maybe too hesitant to commit heresies.

\n

We went through at least two very significant API designs that never got released. Both of them were modeled as a local \"crawling indexer\" which would gather views of data published in hyper sites (via json and md) and then could be queried by apps. They were a neat idea; it was like putting a structured-data search engine in the browser. However I was never satisfied with the results because they couldn't patch over the core problems I listed above, and I tanked the releases. Eventually that tanked my collaborative's morale too, and by 2021 Beaker was pretty dead.

\n

I always knew were were trying to steer the Web as outsiders, but what I didn't expect was how fundamentally hard it is to tweak how the Web works. We would try things like making dat/hyper sites double as social profiles, but then needed some way to display that profile UI when you visited the site. We tried all kinds of things -- toolbars, sidepanels that popped up, little buttons in the location bar -- and never really found something that people would notice but which didn't intrude on the browsing experience. The Web is really a light client for applications at this point, and while I won't say it's impossible to add \"thick client\" behaviors, I can certainly say I never liked the results of my work on it.

\n

After I ran out of ideas for making Beaker work, I decided to give a p2p + servers hybrid a shot with a project called CTZN, another stab at a social network. The smartest thing I did there was live stream every day of development, which helped build another wonderful community and keep me sane during the pandemic. That live-stream ultimately caught the attention of Jay Graber as she was forming the Bluesky team, and at the start of 2022 I began working with Bluesky. It was a life changing turn of events and quickly became -- and continues to be -- my dream job.

\n

Beaker is now becoming another archived repo, but I'm incredibly fortunate to carry the heart of its mission with this new team. It was a wonderful and sometimes painful five years, but it gave me the skills I needed to contribute to Bluesky, and I wouldn't trade those five years for anything. Mistakes were made, and thank goodness they were.

\n

Lessons learned

\n

The entrepreneurs reading this may recognize a common failure pattern here: we got to a really great demo fast, and then hit a cliff that we couldn't surmount. Rather than taking the L and re-evaluating, I slammed my head into the cliff hoping I could break through via force of will, but the tech just wasn't there, and the product wasn't either.

\n

In hindsight, Beaker's MVP was a tool for making static websites. That's it. That's what the product did. If Beaker was going to succeed, that MVP needed to be sticky for people.

\n

Knowing that, the right next move might've been to get dat/hypercore adopted in more browsers and available on mobile -- if p2p static sites were a strong value prop. However, by 2016, that was a pretty dubious value prop to people, and that's ignoring the bad time-to-first-paint and variable uptime. Ironically, the only demographic that Beaker actually helped was teachers on a LAN with students learning how to make websites. It was a shockingly ideal tool for them. Unfortunately that's a small market and wasn't the mission I wanted to pursue.

\n

The way I eventually digested what happened with Beaker was with the \"Percent Easy\" framework, a somewhat silly premise that I'll try to explain. See, I first started putzing with decentralization around 2012 or 2013, and I made a couple projects that completely bounced for people. They were weird and useless and nobody wanted them. When I had the good sense to follow Dominic Tarr's lead on SSB, things got a little easier for me. More people took interest and a great community formed, but it was still a very hard project to pitch to non-technical people. Then, when the Beaker project started it felt smoother than ever before. The demo was good! The feedback was good! I thought Beaker must be a winner for sure with all the positive feedback it received, so when things started to get hard, I was disoriented.

\n

Eventually I started taking a wider view of what success really means: the magical product-market-fit. Getting PMF is darn hard, so what I ask when I start working on a project is, what % feels easy? Do I get to MVP quickly? Do people love the MVP? Do users stick? Do they start ripping updates out of my hands? Do they ignore the warts? And then do they continue to stick for months or even years? Each of these milestones is a chunk of percentage points that tally up to 100%. If I've got a good project then most of that 100% is going to feel \"easy.\" The higher the percentage that feels easy, the better the odds that the project will succeed.

\n

The trick, you see, is that every % that isn't \"easy\" is not just difficult: it's hard. Bashing-your-head-through-the-cliff hard. The way I see it, you can maybe get 20% of the way there through sheer effort. That means a project needs to feel 80-90% easy to actually succeed, and frankly I'd caution against anything that's not \"90% easy.\" It's not laziness. It's just acceptance that each % that isn't \"easy\" is very hard. You're not special and you're not superhuman. Creating successful software is hard.

\n

When I look at Beaker, I think it was probably 50% easy. The initial demo took 2 weeks: 20%. It was a full website editor in about 2 months: 30%. The feedback was great: 50%. The users didn't stick: 50%. We got invited to talks which increased exposure: 51%. A few niche communities took an interest: 53%. Folks liked it enough to donate via OpenCollective and Patreon: 54%. You get the idea. Notably absent is \"usage and retention went through the roof: 80%\" and then \"usage continued to grow for years: 100%.\"

\n

I'm speaking as a builder that hasn't hit PMF so take all this with the grain of salt, but I find this framework useful to evaluate projects because it forces me to recognize the scope of the work. Early successes can make me imagine future successes are likely. Optimism, determination, and mission can make it easy for me to ignore costs. I now know that I need the wind at my back to climb a mountain, so as I work I keep asking myself, what % easy is this? If the projection starts slipping below 80, then I know I have a problem. If a product sprint to fix $X won't get us to 80, then I know I have a problem.

\n

As decentralizers we may be pursuing a mission, but our work only wins in the market, and to win in the market we need to think like entrepreneurs. Ultimately, my lesson learned is that mission needs PMF.

\n

Other thoughts

\n

A smattering of additional lessons I learned over the years.

\n

Don't be too proud to follow people with inspiration. Every time things went better for me, it's because I followed someone who was already doing something great.

\n

Simplify aggressively. With Bluesky we've opted for using p2p structures (IPLD) on a federated network, giving us some of the key advantages of p2p like account portability while retaining the performance and reliability advantages of servers. The pure p2p tech out there still has a lot of potential, but I think it's a bad fit for large scale social networks and sticking with it for Bluesky would've been a mistake. I'm glad we approached AT Proto from first principles, and I'm very confident in the protocol at this stage, but if I have any concern it's that we may have kept complexity that ultimately doesn't prove its value. Time will tell.

\n

Never go negative with competiting projects. The decentralized Web community has been pretty great about staying \"coopetive\" (collaborative + competitive) meaning that we each play to win but we share ideas openly and speak well of each others' work. Stay focused on the shared mission if there is one. This is generally good advice, but it became specifically relevant to me: As I ended up more in the dat/hyper ecosystem, IPFS was often raised as a competing technology and I was frequently asked to comment on the differences. I never went negative, and thank goodness I didn't because one of my colleagues at Bluesky is a core contributor on IPFS, and we've become exceedingly good friends. Besides, going negative is a bad look.

\n

Build a network of talented friends. I've never succeeded by going it alone, and my biggest mistakes have been when I failed to do this. I'm extremely lucky to have the ones I have.

\n

This one came to me from a potential investor, and it was the best unprompted lesson I ever got: don't engage in transactional behavior. When you meet someone for the first time, build an actual relationship. If you don't have a good deal for them, then don't make a pitch. Get to know them. Develop trust. Even if you ultimately do have an ask, it'll work better if they like you -- and if they're not interested, accept the \"no\" and preserve the relationship. You can guess what I did that led the investor to explain this to me.

\n

Pay more attention to the market than I did. I had reasons for focusing on the Web and desktop, and none of them were the right call.

\n

Don't get too precious about the Web. It's a wonderful open platform, but it's settled into its purpose. Look for opportunities to create new open platforms that fit the moment.

\n

Also, don't bloat your MVP.

\n

Farewell, Beaker

\n

Beaker has left me with a lot of big memories. Speaking at JS Conf EU was a big one, and the relieved exhaustion that followed the talk. The many DWeb Summits and Camps that gave me a chance to meet TBL and Ted Nelson (!). The fun of giving talks at meetups and fielding questions. Getting to see Germany and Denmark on work trips. The many afternoons of jogging that often felt like a metaphor for my life.

\n

I've had the rare fortune of pursuing a creative mission, and it's because of everyone's support that I could. I can't thank you all enough. I'm disappointed I couldn't ultimately deliver this project to you, but I'm thankful for the friendships and the memories that came along the way.

\n

See you all on the next one.

\n\n
","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":2,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"Beaker Browser is now archived","kind":"section_1","ident_start":2,"ident_end":32,"extent_start":0,"extent_end":16794,"fully_qualified_name":"Beaker Browser is now archived","ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":32}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":107,"utf16_col":0}}},{"name":"The story","kind":"section_2","ident_start":1766,"ident_end":1775,"extent_start":1763,"extent_end":8929,"fully_qualified_name":"The story","ident_utf16":{"start":{"line_number":21,"utf16_col":3},"end":{"line_number":21,"utf16_col":12}},"extent_utf16":{"start":{"line_number":21,"utf16_col":0},"end":{"line_number":58,"utf16_col":0}}},{"name":"Lessons learned","kind":"section_2","ident_start":8932,"ident_end":8947,"extent_start":8929,"extent_end":13347,"fully_qualified_name":"Lessons learned","ident_utf16":{"start":{"line_number":58,"utf16_col":3},"end":{"line_number":58,"utf16_col":18}},"extent_utf16":{"start":{"line_number":58,"utf16_col":0},"end":{"line_number":78,"utf16_col":0}}},{"name":"Other thoughts","kind":"section_2","ident_start":13350,"ident_end":13364,"extent_start":13347,"extent_end":16039,"fully_qualified_name":"Other thoughts","ident_utf16":{"start":{"line_number":78,"utf16_col":3},"end":{"line_number":78,"utf16_col":17}},"extent_utf16":{"start":{"line_number":78,"utf16_col":0},"end":{"line_number":98,"utf16_col":0}}},{"name":"Farewell, Beaker","kind":"section_2","ident_start":16042,"ident_end":16058,"extent_start":16039,"extent_end":16794,"fully_qualified_name":"Farewell, Beaker","ident_utf16":{"start":{"line_number":98,"utf16_col":3},"end":{"line_number":98,"utf16_col":19}},"extent_utf16":{"start":{"line_number":98,"utf16_col":0},"end":{"line_number":107,"utf16_col":0}}}]}},"copilotInfo":null,"copilotAccessAllowed":false,"csrf_tokens":{"/beakerbrowser/beaker/branches":{"post":"ogDP0jAjNrssQ5aDTePHb0azYXA3Ge0aLl2fGfqeh2h89chW5bIaCz786f9JjO00M7DvrusKgOR206pLQ2TUHA"},"/repos/preferences":{"post":"6cC0fVDZvRqvG-MWyVBTOKYIZZ02SuWvdYyo8qHlsRyH-ygLTc_h1QvloHORbGth_2ooyLdqgruTAyZ25MlX3g"}}},"title":"beaker/archive-notice.md at master ยท beakerbrowser/beaker"}