Conceptual compression means beginners don’t need to know SQL — hallelujah!


It used to be a fundamental requirement that you learned an extensive amount of SQL before you were able to start working on database-backed applications. It was taken as self-evident that you needed to speak the native language of the database before you were qualified to use it. And better yet, you really ought to understand and care about your particular brand of database engine.

This is no longer so. That fact has snuck up upon us, but it’s none the less true — and that’s amazing.

Through advances in leaky abstractions, we’ve managed to compress the conceptual overhead of the database so much that it needn’t feature in the introduction material for making database-backed applications. In Rails, we call that abstraction Active Record, and it falls into the category of object-relational mappers (ORM).

The ORM was long derided by programmers as an unreliable, even harmful, aid of the lazy or the weak. Something Real Programmers shouldn’t expect to lean on, as it was likely to break down if not immediately, then certainly soon thereafter. And then you’d better know all your relational theory!

That’s the past.

Basecamp 3 has about 42,000 lines of code, and not a single fully formed SQL statement as part of application logic! It serves millions of people. It not only leans on the ORM abstraction, it hardly even thinks about it the vast majority of the time.

Do you know what else application programmers rarely need to think about any more either? Memory management and garbage collection. It used to be just as foundational to know your pointers, your destructors, your mallocs, and all the other conceptual overhead needed to deal with manually managing memory. Now it isn’t.

Our abstraction of SQL isn’t quite yet to the point of our abstraction of memory management, and certain frameworks and environments are further ahead than others, but it’s getting closer. The first version of Basecamp had a bunch of #find_by_sql calls, the latest have none. That’s progress.

It’s not that knowledge of SQL isn’t nice to have. It’s good to know a lot of things. Just like it’s helpful to have a strong conceptual model of how computers deal with memory management. It’s just that you no longer need to know these things to start making applications, and that’s a wonderful thing.

SQL, like memory management, is a concept you can unpack when you need to. Further down the line of your career. Then after you learn it, you can compress it back down again and spend more of your mental capacity on other things most of the time. I used to write SQL statements every day. Now maybe I do so once a month? Less? And that’s against a major application that’s reached a scale that most beginner apps never will.

Some programmers will scoff at this notion instinctively. That it’s simply irresponsible for programmers to start writing code until they know these historical fundamentals. I suppose it’s natural to think that all the hard work you spent learning the basic concepts — that indeed were required when you got started — should still be taught to all on day one. This is one of the key pitfalls of experience. Falling in love with the trials and tribulations you had to suffer, rather than rejoicing in the fact that the next generation doesn’t have to endure them.

The relational database is a glorious invention, but for most programmers it doesn’t need to be more than an appliance. Sure, take the time to learn how the drying tumbler machine works, it may well save you a service call to a specialized technician one day. But it’s hardly a requirement for living with such a device and getting your clothes dry.

The relegation to “appliance status” isn’t a dig, but an honor. It means we’ve finally made the technology and the abstraction so good that many, if not most, programmers don’t even have to think about it on a daily basis.

It also means it’s become a commodity. At Basecamp we happen to use MySQL, but to be honest, it’s basically only for historical and operational reasons. We could switch to PostgreSQL tomorrow, and I wouldn’t really give a damn. We have nothing in the application that relies on a particular brand of the database appliance.

Building stuff with computers means building on top of abstractions. CPUs, 1s and 0s, assembler, C compilers, database drivers, memory management, and a million other concepts are required to make our applications work. But as we progress as an industry, fewer people need to know all of them, and thank heavens for that.

It takes hard work to improve the conceptual compression algorithms that alleviate application programmers from having to worry about the underpinnings most of the time, but it’s incredibly rewarding work. The more effectively we compress the concepts of yesterday, the lower the barriers to entry become. And we need low barriers if we are to get more people started making applications.

SQL is perhaps the brightest example of conceptual compression over the past decade or so, but application work is full of other examples. And we need such conceptual compression more than ever to starve off specialization, and to preserve the power of individual generalists to make complete applications.

We’re currently living through an explosion of conceptual expansion and experimentation on the client-side in the web application world. That’s really exciting! Lots of new ideas and approaches churning rapidly. But it’s also needlessly intimidating in many ways. We don’t all need to spend hours or days learning how to configure build pipelines. Some day our leaky abstractions will be good enough that the conceptual compression will relegate such tooling to appliance status as well. That will be a good day.

You can’t learn everything. You can’t hold every concept fully expanded in your head. And moreover, you shouldn’t. As we compress formerly fundamental concepts, we make room for new, grander abstractions. These are the leaps of progress it’ll take to continue to make us more efficient and ultimately more effective.

But I get that it’s hard to break habits. Like the stereotype of an old person complaining about the price of gas or a gallon of milk because their frame of reference is anchored in a time past. Broad-based progress sometimes need that generational churn to really happen (and that’s not about your physical age, rather the years of experience).

Don’t be a fogey. Don’t fight the conceptual compression. Help make it happen.

Highrise is back with Basecamp

Welcome home!

In 2014, Highrise was spun off as a separate (but wholly-owned) company from Basecamp. Last year it celebrated its tenth anniversary in business. And this year it’s moving back in with Basecamp.

In some ways, it’s like it never left. While Highrise operated as an independent company under Nathan Kontny as CEO, Basecamp’s technical operations team continued to run servers and systems. Our support team still has a lot of people who used to answer customers when Highrise was a direct part of our suite of products. And almost all the members of the original product team for Highrise are still with Basecamp.

In other ways, this is indeed a change. Nathan Kontny had built a team of seven to lead new development, and they made a lot of improvements over the years. We want to thank the team for all their work and wish them all the very best.

Spinning Highrise off into a separate company with a separate team and CEO was always a bit of an experiment. While that experiment had a bunch of highlights, we ultimate decided it was time to try something different on both the product and business side after a thorough review was conducted some time ago.

For customers of Highrise, we at Basecamp are committed to supporting the product until the end of the internet! Highrise is home to over 10,000 customers who’ve trusted their data and their business to us. We are grateful for the trust and will continue to operate Highrise to the same high standards as Basecamp.

In short, this transition back to the Basecamp team is going to be nearly invisible to Highrise customers. Highrise is returning to the team that originally built the software, and it’s being operated on the technical side by the same team that always did so.

We’ve also begun exploring a range of new directions for the product’s future. We’re not yet ready to share where this is going, but will do so as soon as there’s a final path set.

Thank you to all our Highrise customers whether you’ve been with us for 10 days or 10 years! ❤️

– Jason & David

You’re not changing the world


I mean, in the widest possible sense, you are. Your mere existence is bound to change some of it somewhat. But that’s not what the unironic use of the phrase — WE ARE CHANGING THE WORLD — is meant to convey in Silicon Valley. They’re actually serious.

And look, some of them do end up changing the world. The world is different now that, say, Twitter is here, and the president of the United States can threaten nuclear war from the comfort of his golden shitcan. Seriously, that is different!

But let’s just say that most companies that actually end up changing the world rarely set out with that as the explicit mission. Twitter started as a way of telling your drinking buddies by SMS which dive bar you were hanging out at. Facebook started as a way for Zuckerberg to lure “dumb fucks” into giving him their private information. Modest beginnings!

The odds are that whatever you’re doing is never going to amount to any of the global significance that either Twitter or Facebook has bestowed upon the world. And thank god for that! If everyone in Silicon Valley who proclaimed to be on a mission to change the world actually did, our collective regret would be far deeper.

So ponder this example from HealthIQ’s career page from yesterday (since changed*):


I like to peek beneath the surface of such delusions of grandeur. What on earth would prompt someone hawking life insurance — LIFE INSURANCE! — to posture, and quite possibly believe, that they’re Changing The World™ (or, as here, Healing The World)? Such delusions seem farcical on their face. An Onion piece a little too on the nose. But there we are.


HealthIQ’s former career page was full of Onion-worthy proclamations

My pet theory is that it’s really an existential cry for help. If you’re going to toil your life away on a literal treadmill with meetings at 9pm every night, you’re going to need to tell yourself something different than “I do this such that I can save privileged joggers and kale eaters 10% on life insurance”. Because such a mission just doesn’t warrant the sacrifices proposed.

But the cognitive dissonance between “I sell life insurance” and “I believe I’m healing the world” is so loud that it invites intervention. Someone to slap you across the face, shake you violently, and yell “snap out of it, mate! Snap out of it!!!”. The absurdity of the juxtaposition is the subconsciousness wailing in distress.

Usually the script isn’t this unbelievable, though. But it still follows the same arc. The idea that work isn’t worth living unless it entails the prospect of upsetting the world order. That work can’t just be about making the existing world a bit better, a bit smoother, a bit cheaper, or a bit more joyful. It has to rearrange the cosmos to warrant our time.

Partly, I blame Steve Jobs for this. I know it isn’t kind to speak ill of the dead, but when he asked Scully to take over as CEO of Apple, it was with this grand pitch: “Do you really want to sell sugar water for the rest of your life?”. And as many larger-than-life characters of history, his words have echoed through time, but also ended up distorted after having bounced around enough to be heard by the next generation.

It’s not that “selling sugar water” is a noble quest, and Apple really has changed the world, so Jobs was right. It was more the idea that we all need to think about changing the world all the time, lest our life is bereft of meaning.

For the vast majority of people on earth, including the vast majority of people working in Silicon Valley, existence will not be justified through their work alone. There will be no monuments, no valedictorian speeches, no Harvard Business School case studies. This isn’t cause for despair but for celebration!

Carrying the weight of Changing The World on your shoulders is a tremendous burden. Look at the characters who actually managed it. Most of them weren’t exactly living envious lives outside the scope of their work. Why are you so keen to follow in their footsteps?

I think more people in Silicon Valley would be better served by embracing the mundane. Do you know what, life insurance is a perfectly honorable thing to be selling on its own merits. And if you found a way that makes that transaction a little better for some small subset of companies or consumers, hell, good on you. It doesn’t have to be anymore glamorous than that.

Well, except that you raised $82 million off the hook that you were Changing The World with Big Data, and not on the more earthly promise that you were going to be a bit better at insurance brokering.

I have no illusions that my time in this world is going to be remembered through the ages. When it’s over, I’ll be so fortunate as to have left an impression on my friends, my family, and a few colleagues in the industry. And those impressions will fade quickly, so they aren’t even worth elevating much.

Look. You can’t outrun existential angst. Even if you put actual fucking treadmills in the middle of your office. Eventually the delusions are going to crack, and the more you’re invested in them, the harder you will shatter. And for what reasonable purpose?

Set out to do good work. Set out to be fair in your dealings with customers, employees, and reality. Leave a lasting impressions on the people you touch, and worry less (or not at all!) about changing the world. Chances are you won’t, and if you do, it’s not going to be because you said you would.


*HealthIQ did change its career page last night after the Twitter mob came carrying pitchforks. I think they deserve kudos for that. Although it remains to be seen whether it’s just a matter of changing appearances or actually provoked a real conversation within the company around its values and practices. They still seem oddly focused on banning critical internal feedback (no devil’s advocate allowed!), which is probably how they ended up with that terrible career page in the first place. No way everyone at the company read that and thought AWESOME! SHIP IT!

On Writing Software Well


I’ve begun a new YouTube series called On Writing Software Well where I explore the real Basecamp codebase in search of interesting programming topics. It’s less “here’s how to do it” and more “here’s what I was thinking when we made this choice or took this direction”. And it’s intimately grounded in real, production code that’s been used by millions of people.

It’s partly a reaction to the endless debates we tend involve ourselves in as software writers without looking at real code. When you debate without code, you’re likely to get sucked into illusions of disagreement. You argue from your experiences with codebase A, I argue from my experiences with codebase B, and we clash because A isn’t B. That’s just silly.

Yet somehow arguments grounded in production code are rare. Few people seem willing to lift the curtain on such codebases, which is a damn shame. Because that’s where the real wisdom is buried. That’s where people have been forced to make actual trade-offs between competing patterns and practices. It’s those trade-offs and the circumstances around them that are valuable.

Programming arguments based in example code is most often stylized and idealized. It’s Platonic shadows on the cave wall. So easy to dig in and defend a technique when you don’t actually have to worry about guarding the flanks, setting up camp, and getting your supply lines in order. You know, like in real life.

So that’s my mission: To take you into the trenches and have you fight by my side in the battle against complexity and in the search for beautiful code.

Yes, the code is all Ruby and Rails, but the principles should travel reasonably well. So even if you don’t do Ruby on Rails, I’d be surprised if there wasn’t something to in there to pique your interest and rattle your convinctions.

Here are the first five episodes:

Conflicts are rarely just about the cards on the table


Most disagreements aren’t just about the cards on the table. They’re just as much about who’s at the table. What time the game is being played. The last fifty games before this one. And about all the other people the current participants ever played with as well.

So it’s no wonder the game ends up making little sense to folks who think everything they need to know to make the winning argument is reading the cards facing up.

One good way to tell how much a conflict is about those cards, or about something else, is to gauge the temperature of the tone. If it’s unreasonably, disproportionately hot, then it’s probably not just about the current specifics. There are very few specific situations and details that’ll make people hit the red zone on the account of those alone.

People get worked up by compounding circumstances and repeating dynamics. Like, why does he always have to say it like this! Or, can’t she see how this is just yet another example of this other thing we’ve talking about so many times?

It’s not at all uncommon for the context to dwarf the particulars. But it’s exceedingly common for people to be oblivious to the fact. And before you know it, the argument ends up boiling over, while a proxy war of disagreement is waged.

This is one of the reasons why it’s so rare for online arguments between strangers to go anywhere productive. Unless the topic of discussion can be reduced to purely logic points — and really, what topic can? — you’re going to have to engaged with all the extracurriculars. But how can you, if you don’t know what they are, because you don’t know the other person’s circumstances or experiences?

At least if you’re invested in the other person, like if you work, live, or play together, you can spend the time to learn their circumstances and examine their experiences. Once you learn the context, the where-are-they-coming-from, you can start to make progress together on that hot topic. And by the time you’ve bothered to dive that deep, the whole thing has probably cooled off enough for gentle hands to touch.

The world needs more modest, linear growth companies. Please make some.

14 years of linear growth at Basecamp.

Exponential growth gets all the glory. Every startup story that lands on the cover of a magazine has a hockey-stick chart to flaunt. Yes, disruption is driven by such violent expansion, and the world needs some disruption some of the time. But for the other 360 days out of the year, what it also needs is some modest, linear growth.

Linear growth is what happens in domains that aren’t animated by network effects (and when no artificial growth hormones are injected!). It’s the simplicity of good products sold at reasonable prices that find happy customers. These customers talk to friends and colleagues in other businesses, and over time that word of mouth spreads the good vibes, which turns the business up.

But the limelight has no patience with such simple, slow methods as word of mouth. It’s not infectious enough. Not exponential enough. That’s a shame.

Because the world is full of problems that needs solving by people who are willing to put in the work for the long haul. I’m not talking about the freakish 120-hour/week, seven-year death marches, but the patient, sustainable work that might last a lifetime. Problems that yield better to people sticking with it.

These problems rarely provide the world with more platforms, but the world has enough platforms. If everyone wants to be the foundation, then there’s nobody left to serve as the beams or cladding or tiles. That’s a recipe for a concrete and corporate wasteland.

It’s also a recipe for monoculture. Network effects have given us spectacular stories of unfathomable growth, but it’s also given us monopolistic conglomerates that poison the market and its variety.

I’m no particular fan of advertisement, but it’s still clear as day that the world is much worse off for having all the value of that trade captured solely by Facebook and Google. Yeah, that’s disruption, and no, it’s not the kind that makes the world better off. It’s creative destruction without creative regeneration. More black hole, less forest-fire cleanse.

Capitalism as a system is prone to all manners of dysfunction, but few are as fatal as that of monopolies backed by exponential growth. Markets as a force for good quickly break down and get perverted when only a few power players remain to call all the shots.

Maybe such concentration is “natural” in a few domains, but that doesn’t mean we should stand idle by and let it corrupt both business and society. In an era past, trust busters knew how to protect the common good by opposing the behemoths of industry with antitrust fights and laws. AT&T had a “natural” monopoly, and it still deserved to be broken up. Such memories are unnecessarily quaint now, and even when brought up, it’s through a myopic literal lens (Facebook + Google aren’t causing “higher prices”, therefore they’re not bad monopolies. Bullshit).

But the discussion of whether the regulators will once more mount up shouldn’t distract us from doing what we can today. Which is to inspire a new generation of entrepreneurs to nobler goals than simply to become caliph instead of the caliph.

Which is pretty much all the business press and other spectators (and speculators) are obsessed with these days. Who’s going to be the next Google? The next Facebook? The next Apple? These are interesting questions, but they’re not the only questions, and by posing them over and over again ad nauseum, we’re restricting the conversation and constricting our imagination.

What if the next NEXT THING wasn’t a supplementation of an existing network-effect megacorp, but a proliferation of a thousand or million smaller businesses that were given the time and place to breathe and thrive?

But for that to happen, it needs not only to be seen as feasible, but desirable. That to eschew the exponential demands of investors is a sign of strength, not a mark of weakness. That to be content with linear growth is streak of independence, not absence of vision.

We are in dire need of such reprogramming of the entrepreneurial boot loader. So many faithful decisions are taking in the early stage of a business that locks its course for perpetuity. Very few ventures get to turn back the clock and have a do-over on their cap table. Epiphanies that come too late might as well not come at all.

You can’t move a tree by blowing at it softly once the roots are down. But you can radically change where a seed will land by doing the same.

I promise I’m not trying to make a lame plea for “children are the future”, although that’s both trite and true. New businesses are started by adults of all ages. Every single one of them have the power to pick how they’ll nurture their growth when it’s started. Choosing to chase the exponential is just that, a choice. Which also means that choosing the linear is a choice too.

Which I guess is really my chief argument here. Or appeal, even. That more people choose the path of linear growth. That they embrace it with vigor and pride. That they make no apologies for wanting a modest and sustainable business that can live in harmony with other shops of the same description.

The path of linear growth has been the trajectory of Basecamp for 14 years today. It’s brought beauty and warmth to millions of people who’ve used our product. It’s brought stability and a home to the fifty-odd people we employ at the company. And it’s brought the deepest of meanings and satisfaction to Jason and I for owning it.

May you make your own fortune as you take a swing at the same.


Does this tickle a fancy? Stroke a nagging? I’m sure you’d like my other writings on the topic, then. Start with RECONSIDER, then Exponential growth devours and corrupts, then maybe Enough. Well, my whole back catalogue is full of these kind of ideas, really. So do dive in.

Things are going so well we’re doing a hiring freeze


Business has never been better at Basecamp. Despite all the competition, all the noise, and all the changes since we launched 14 years ago, 2017 was the year we earned the most revenue ever.

While that alone is cause for some celebration, it’s hardly the most important thing for Jason and I, as the business owners. Sure, it’s nice to see numbers tick ever higher, but we passed enough many years ago. What matters far more than big numbers for us today is how the business feels.

And it’s really never felt better, in almost all the ways. Basecamp the product is the best its ever been. Tens of thousands of new businesses and teams continue to sign up every month. We keep hearing from customers about the profound changes to their organization, productivity, communication, and even sanity that Basecamp helps them realize. It’s deeply rewarding.

We’ve also kept up with our founding mission to out-teach and out-share rather than out-spend the competition.

Since shortly after the launch of Basecamp, we’ve been stewarding the Ruby on Rails movement. The latest major release has a brand new framework, Active Storage, that was extracted from Basecamp 3. So too was the last major new framework in Rails, Action Cable. And now we’ve shared our entire two-pack punch to front-end development with Stimulus and Turbolinks.

Jason and I are finishing our fourth book, extracted from the lessons running Basecamp. It’s called The Calm Company and will be released this year. And after a lovely run with The Distance podcast, we’ve launched a REWORK podcast to share ever more of our lessons and perspectives.

So. Things are good. Really good, actually. Which invariably invites the question I get asked so often: WHAT’S NEXT?! Which is really a question of WHAT’S MORE? What else are you going to do in addition to all the shit you’re already doing? It’s so ingrained in our entrepreneurial culture that you must always be on a conquest. Once a set of territories have been subdued, you’re honor-bound to push further north.

Thanks, but no thanks. Basecamp has never sought to conquer the world or the markets. We do not have to win a total victory from a total assault to be fulfilled. Which partly stems from the fact that we aren’t beholden to financiers, partly because the satisfaction of running Basecamp comes more from doing the work, less from owning the work.

It’s this focus on the satisfaction of doing the actual work that’s been driving our outlook since the inception of Basecamp. How can we structure the business in such a way that Jason and I are able to spend the bulk of our time doing our favorite things? Designing. Programming. Writing.

That’s harder than it sounds. The momentum of growth assumes control of the ship quickly, if you don’t dare wrestle back the wheel. It’s so easy to just go with the flow. Of course we’re going to hire more people! Of course we’re going to spend more money! Of course we’re going to build more features! Of course we’re…

Before you know it there’s no longer time to do your favorite things. Now all the things that simply have to be done fill first your weeks, then your months, and then finally the whole year. I keep the parable of the fisher man in my mind often not to forget this boiling pot.

At just around 50 people and no full-time managers, it feels like we’re just at this crucial break in the waves at Basecamp now. On the other side, the tide will pull us out further and further out to sea. And maybe there are ever-greater riches to be found out there, but we’d be lost and adrift. If we dare resist the pull, we can stay anchored and connected.

So we’ve decided to dare. To resist. And thus, in our celebration of BEST EVAH, we’re taking the unusual step to drop that anchor and freeze all hiring at Basecamp¹.

“Wait, what?”, I can imagine a few puzzled minds thinking. Hiring freezes are usually for companies that are struggling. Trying desperately to cut costs to stay afloat. And here we are, doing better than ever, pulling that same move? Yes.

We’ve always been great fans of constraints, and capping the headcount in the face of growth is perhaps the biggest constraint of all. Especially because we’re not at all about running faster. Squeezing out more productivity from fewer hands. Quite the contrary.

The constraint of having the same team means that you also only get to do the same amount of work. But you don’t have to do the same actual work, you can do different work. You can judo the work. You can say no to more work. You can focus on more effective work.

That’s the kind of environment that excites me.


¹ The sole exception may be support, which is the only department that doesn’t yield well to just “do less”. If there are more customers and they need help, you gotta help them. But we’re working on making sure that they both need less help and that we don’t take on excessive amounts of new customers.

Stimulus 1.0: A modest JavaScript framework for the HTML you already have

Modern JavaScript doesn’t have to mean single-page, client-side MVC apps.

We write a lot of JavaScript at Basecamp, but we don’t use it to create “JavaScript applications” in the contemporary sense. All our applications have server-side rendered HTML at their core, then add sprinkles of JavaScript to make them sparkle.

This is the way of the majestic monolith. Basecamp runs across half a dozen platforms, including native mobile apps, with a single set of controllers, views, and models created using Ruby on Rails. Having a single, shared interface that can be updated in a single place is key to being able to perform with a small team, despite the many platforms.

It allows us to party with productivity like days of yore. A throwback to when a single programmer could make rapacious progress without getting stuck in layers of indirection or distributed systems. A time before everyone thought the holy grail was to confine their server-side application to producing JSON for a JavaScript-based client application.

That’s not to say that there isn’t value in such an approach for some people, some of the time. Just that as a general approach to many applications, and certainly the likes of Basecamp, it’s a regression in overall simplicity and productivity.

And it’s also not to say that the proliferation of single-page JavaScript applications hasn’t brought real benefits. Chief amongst which has been faster, more fluid interfaces set free from the full-page refresh.

We wanted Basecamp to feel like that too. As though we had followed the herd and rewritten everything with client-side rendering or gone full-native on mobile.

This desire led us to a two-punch solution: Turbolinks and Stimulus.

Turbolinks up high, Stimulus down low

Before I get to Stimulus, our new modest JavaScript framework, allow me to recap the proposition of Turbolinks.

Turbolinks descends from an approach called pjax, developed at GitHub. The basic concept remains the same. The reason full-page refreshes often feel slow is not so much because the browser has to process a bunch of HTML sent from a server. Browsers are really good and really fast at that. And in most cases, the fact that an HTML payload tends to be larger than a JSON payload doesn’t matter either (especially with gzipping). No, the reason is that CSS and JavaScript has to be reinitialized and reapplied to the page again. Regardless of whether the files themselves are cached. This can be pretty slow if you have a fair amount of CSS and JavaScript.

To get around this reinitialization, Turbolinks maintains a persistent process, just like single-page applications do. But largely an invisible one. It intercepts links and loads new pages via Ajax. The server still returns fully-formed HTML documents.

This strategy alone can make most actions in most applications feel really fast (if they’re able to return server responses in 100–200ms, which is imminently possible with caching). For Basecamp, it sped up the page-to-page transition by ~3x. It gives the application that feel of responsiveness and fluidity that was a massive part of the appeal for single-page applications.

But Turbolinks alone is only half the story. The coarsely grained one. Below the grade of a full page change lies all the fine-grained fidelity within a single page. The behavior that shows and hides elements, copies content to a clipboard, adds a new todo to a list, and all the other interactions we associate with a modern web application.

Prior to Stimulus, Basecamp used a smattering of different styles and patterns to apply these sprinkles. Some code was just a pinch of jQuery, some code was a similarly sized pinch of vanilla JavaScript, and some again was larger object-oriented subsystems. They all usually worked off explicit event handling hanging off a data-behavior attribute.

While it was easy to add new code like this, it wasn’t a comprehensive solution, and we had too many in-house styles and patterns coexisting. That made it hard to reuse code, and it made it hard for new developers to learn a consistent approach.

The three core concepts in Stimulus

Stimulus rolls up the best of those patterns into a modest, small framework revolving around just three main concepts: Controllers, actions, and targets.

It’s designed to read as a progressive enhancement when you look at the HTML it’s addressing. Such that you can look at a single template and know which behavior is acting upon it. Here’s an example:

<div data-controller="clipboard">
  PIN: <input data-target="clipboard.source" type="text" value="1234" readonly>
  <button data-action="clipboard#copy">Copy to Clipboard</button>
</div>

You can read that and have a pretty good idea of what’s going on. Even without knowing anything about Stimulus or looking at the controller code itself. It’s almost like pseudocode. That’s very different from reading a slice of HTML that has an external JavaScript file apply event handlers to it. It also maintains the separation of concerns that has been lost in many contemporary JavaScript frameworks.

As you can see, Stimulus doesn’t bother itself with creating the HTML. Rather, it attaches itself to an existing HTML document. The HTML is, in the majority of cases, rendered on the server on either on the page load (first hit or via Turbolinks) or via an Ajax request that changes the DOM.

Stimulus is concerned with manipulating this existing HTML document. Sometimes that means adding a CSS class that hides an element or animates it or highlights it. Sometimes it means rearranging elements in groupings. Sometimes it means manipulating the content of an element, like when we transform UTC times that can be cached into local times that can be displayed.

There are cases where you’d want Stimulus to create new DOM elements, and you’re definitely free to do that. We might even add some sugar to make it easier in the future. But it’s the minority use case. The focus is on manipulating, not creating elements.

How Stimulus differs from mainstream JavaScript frameworks

This makes Stimulus very different from the majority of contemporary JavaScript frameworks. Almost all are focused on turning JSON into DOM elements via a template language of some sort. Many use these frameworks to birth an empty page, which is then filled exclusively with elements created through this JSON-to-template rendering.

Stimulus also differs on the question of state. Most frameworks have ways of maintaining state within JavaScript objects, and then render HTML based on that state. Stimulus is the exact opposite. State is stored in the HTML, so that controllers can be discarded between page changes, but still reinitialize as they were when the cached HTML appears again.

It really is a remarkably different paradigm. One that I’m sure many veteran JavaScript developers who’ve been used to work with contemporary frameworks will scoff at. And hey, scoff away. If you’re happy with the complexity and effort it takes to maintain an application within the maelstrom of, say, React + Redux, then Turbolinks + Stimulus will not appeal to you.

If, on the other hand, you have nagging sense that what you’re working on does not warrant the intense complexity and application separation such contemporary techniques imply, then you’re likely to find refuge in our approach.

Stimulus and related ideas were extracted from the wild

At Basecamp, we’ve used this architecture across several different versions of Basecamp and other applications for years. GitHub has used a similar approach to great effect. This is not only a valid alternative to the mainstream understanding of what a “modern” web application looks like, it’s an incredibly compelling one.

In fact, it feels like the same kind of secret sauce we had at Basecamp when we developed Ruby on Rails. The sense that contemporary mainstream approaches are needlessly convoluted, and that we can do more, faster, with far less.

Furthermore, you don’t even have to choose. Stimulus and Turbolinks work great in conjunction with other, heavier approaches. If 80% of your application does not warrant the big rig, consider using our two-pack punch for that. Then roll out the heavy machinery for the part of your application that can really benefit from it.

At Basecamp, we have and do use several heavier-duty approaches when the occasion calls for it. Our calendars tend to use client-side rendering. Our text editor is Trix, a fully formed text processor that wouldn’t make sense as a set of Stimulus controllers.

This set of alternative frameworks is about avoiding the heavy lifting as much as possible. To stay within the request-response paradigm for all the many, many interactions that work well with that simple model. Then reaching for the expensive tooling when there’s a call for peak fidelity.

Above all, it’s a toolkit for small teams who want to compete on fidelity and reach with much larger teams using more laborious, mainstream approaches.

Give it a go.


Stimulus was envisioned during a two-week deep dive into the current state of JavaScript that I took about a year ago. I mined our patterns within the Basecamp 3 codebase, extracted an archetype, and used the latest-greatest JavaScript techniques to make it real. This deep dive first gave birth to Webpacker for Rails, but this framework couldn’t have happened without the incredible work by Sam Stephenson and Javan Makhmali. They took my rinky-dinky prototype of Stimulus and rewrote it from scratch in TypeScript. Just like they had done with Turbolinks 5. It’s a beautiful piece of code.

We decided to kill a feature to figure out how to make it better


Likes and hearts are all over collaboration and communication software today. Even Basecamp 3 has claps now. On the surface, that seems like a natural step forward: Make it easier to participate, provide encouragement, and create a sense of connection. But scratch that surface and there’s plenty of ambivalence below.

I first really noticed my ambivalence in our own product when reading through the daily updates of what people at Basecamp had been working on. We gather all those in a What did you work on today? automated check-in. (It’s one of my favorite features of Basecamp, and it makes it so much easier to keep up with what everyone is cooking without the constant nagging of a manager checking in.)

But as I read through the replies from the few dozen people who answered the question on any given day, I was faced with the dilemma of the clap. If I applauded an update from Sam yesterday, but don’t today, does that mean I’m expressing discontent with the most recent work? If I don’t applaud for Javan on the same day as I applaud for Sam, does that mean I’m parting favor of one over the other?

Frequently my answer to this question was: Applaud equally for everyone or no one. An easy out for anxiety, but not actually very helpful.

After reflecting on my own issues with minimal-effort encouragement, Jason and I discussed our options. No real immediate fixes came to mind. This is a fuzzy problem with lots of subtle trade-offs. So instead of trying ever-harder to think up the perfect solution, we grabbed the hammer instead and decided to whack the feature.

For our first 6-week cycle of the year, we’re doing without the power to clap for messages, comments, completed todos, or answers to automatic check-ins on our own account in Basecamp 3. No big discussion, no brainstorming, no endless contemplation. Just a big whack, and let’s see where this goes.

And go it went. When we announced the change internally, there was an outpouring of opinions. “Yes, I too have anxiety around the claps”, “Ugh, getting a daily report of applause is really annoying”, “I really use claps to say that I saw something”, “Hey, isn’t it interesting that we’re all commenting with a lot more depth now that the easy out of a clap isn’t there any more?”.

I don’t know what we’re ultimately going to do about applause in Basecamp 3, but I do know we’ll be much better informed by going without for a while on our own account. A foundation for making a better decision we wouldn’t have had if we had just kept talking about it.

When in doubt, give it a whack.

Growing apart and losing touch is human and healthy


I quit Facebook back in 2011 for a lot of reasons, but perhaps the most crucial was to rebel against its core mission: Connecting the world. I was over-connected with the world, acquaintances and friends from the past, and I wanted out.

Zuckerberg has repeatedly doubled down on the toxic idea that we should only have one self, one persona. That we should be the same person in all social circles, lest we be “frauds”.

I’m happy to be a fraud under that definition. I’m not the same person I was in high school. Not the same person I was at university. Not the same person I was with friends at age 15 as I was with a different group of friends at 21. I’m still not the same person with friends in programming as I am with friends in racing or with family or old mates from Denmark.

What allowed me to change and prosper was the freedom to grow apart and lose touch with people. It’s hard to change yourself if you’re stuck in the same social orbit. There’s a gravitational force that pulls you into repeating the same circular pattern over and over again. Breaking out of that takes tremendous force.

In real life, this force is mercifully thrust upon you at critical moments for self-discovery and evolution. You leave university, and you automatically lose touch with most of the people you knew there. It’s not an affront to anyone that this happens. It doesn’t take any effort. Everyone accepts that it’s a natural process.

But Facebook changed that. It stunted this natural, gentle process of growing apart and losing touch. Now the default is to stay connected with everyone you’ve ever friended forever. And to break that connection, you have to actively sever it. Something most people don’t like doing, and don’t like having done to them, so it generally doesn’t happen.

Knowing that everything you share will be seen by all these people from your past quietly. moderates what you actually share. Becoming someone else entails experimenting and failing with new styles and ideas. Not a lot of people are so keen to premiere such vulnerable stages of their evolution in front of an audience that expects them to be that same person they always were forever. I know I wasn’t.

Neither was I interested in constantly living in the past with images and sharing from people whom a natural process would have seen me lose that touch with. It felt suffocating on both a conscious and unconscious level. Connected in the sense that an anchor is to a boat. A literal drag.

So I pressed the red button and nuked all these synthetic connections from Facebook’s orbit in one go.

It was liberating.