Boilerplates are bicycles, not cars

A developer in Porto bought a $299 SaaS starter, built three dead products on it, then wrote his own setup over a weekend. The fourth one worked. Here's why.

Rui Almeida lives in a fifth-floor walkup in Porto, two blocks from the Mercado do Bolhão. His desk faces a window that doesn't quite close, and when the tram passes on Rua de Sá da Bandeira the coffee in his cup shivers. On a Tuesday in March 2024 he bought a SaaS boilerplate for two hundred and ninety-nine dollars. The tram passed. The coffee shivered. He clicked.

He didn't tell his girlfriend. Not because she'd be upset — she's a product designer at a small studio near Aliados and she gets it — but because he'd told her, six months earlier, that he was going to stop buying tools and start finishing things. Two ninety-nine wasn't a lot of money. It was the principle. He'd bought a Notion template the previous summer. A Figma kit in January. A Tailwind component pack two weeks before that. None of them had shipped anything.

The boilerplate was different, he told himself. The boilerplate would skip the boring parts. Auth, Stripe, magic links, dashboard scaffolding, a settings page nobody enjoys writing twice. He'd been a backend engineer for nine years. He knew how to write all of this. He just didn't want to write it again for the fourth time on his own dime.

He pulled the repo down that night. The dev server came up on the first try, which he took as an omen. The login page was already wired. Stripe webhooks were there, commented helpfully. There was a tasteful pricing page he'd swap for his own copy. He sat back, drank the shivered coffee, and thought: this is the year.

Three projects later, on a Saturday in September 2025, he deleted the boilerplate folder, opened a blank Next app, and started typing. That one shipped. That one made money. This essay is about the eighteen months between.

The three corpses

The first project was a feedback tool for indie SaaS founders. He had the idea on a run along the Douro. The boilerplate let him have a landing page, login, and a working Stripe checkout in about nine hours. It felt incredible. He posted a teaser on X with the URL. Got eleven signups in two days, mostly from people he knew.

Then he had to build the actual feedback widget. Which meant deciding what a feedback widget even was. Was it embeddable? Hosted? Did it screenshot the DOM? Did it record video? Each of those questions had a different product underneath it. He picked the one that was easiest to bolt onto what the boilerplate already had, which turned out to be a Notion-style commenting interface, because the boilerplate already shipped with a rich text editor and a sidebar layout.

He shipped it in five weeks. Nobody used it. The eleven signups never came back. He told himself the market was crowded.

The second project, six months later, was a tool for newsletter writers to A/B test subject lines. Same boilerplate, same head-start, same first-week thrill. He got it in front of a few writers he'd met on a Discord. They were polite. One of them said the words I think about a lot when I read your stuff. Then nobody opened the app again.

The third was a CRM for solo consultants. He didn't even launch it. He got to week four, realized he was building yet another dashboard that looked exactly like the previous two — same sidebar, same settings page, same empty-state illustration he'd downloaded from the same pack — and felt physically nauseous. He closed the laptop and went for a long walk along the river. He did not open that repo again.

What the boilerplate actually did

Here's the part Rui only saw later, the way you only see a bad relationship clearly once you're out of it. The boilerplate didn't kill those three projects. The boilerplate did exactly what it advertised. Auth worked. Payments worked. The deploy pipeline was fine. He never lost a weekend to a webhook signature mismatch or a magic link in spam.

What killed them was what the boilerplate let him skip. Not the code. The thinking.

When you write auth from scratch, even badly, you have to decide things. Are sessions a thing here, or is everything stateless? Do users belong to organizations or just to themselves? Is there a free tier, and if so what does it actually give you? These questions sound like infrastructure. They're not. They're the product. By the time you've answered them you know what kind of company you're trying to build, because you've been forced to imagine the user three times in three different lights.

The boilerplate answered all of those questions for him with sensible defaults. Sensible for the boilerplate's author. Probably sensible for a hundred different products. Maybe not sensible for Rui's. He never noticed, because he never asked.

Bicycles, not cars

A car will take you somewhere even if you're half asleep. You point it down a road, hold the wheel loosely, and arrive. The road does most of the work. The car does the rest.

A bicycle won't. A bicycle removes friction from a journey you still have to steer. If you don't know where you're going, a bicycle just gets you lost faster than walking did. You'll cover more ground, sure. None of it in the right direction.

Boilerplates are bicycles. They are not, and have never been, cars. The marketing copy on most of them implies otherwise — ship your SaaS in a weekend, launch faster than your competitors, focus on what matters — and the implication is technically true. You will ship faster. You will launch faster. You'll just be launching something you haven't fully decided to build.

Rui rode his bicycle into a wall three times. Each time he assumed the bicycle was the problem and considered switching brands. He looked at a different boilerplate after the second corpse. He almost bought it. The only reason he didn't was that the demo video was too long and he got bored.

The decision tax

There's a tax you pay when you accept a default. Most of the time it's small. Sometimes it's load-bearing for your business and you don't find out until month four, when you're trying to do the one thing your product actually needs to do and the boilerplate has quietly made it impossible.

Rui's CRM was meant to support multiple workspaces — a consultant juggling three client engagements wanted to keep them separate. The boilerplate had a single-tenant user model. To retrofit organizations into it was three weeks of work touching forty files. He didn't do the three weeks. He shipped without workspaces, told himself he'd add them later, and watched the few testers he had churn within a month because they couldn't separate their clients.

The single-tenant decision had been made by someone else, two years before Rui downloaded the repo, for a different product entirely. It cost Rui his fourth-quarter momentum. It also cost him about four hundred euros in domain and infra he kept paying for out of stubbornness. The boilerplate didn't pick his ORM, didn't pick his auth provider, didn't pick his deploy target, didn't pick his testing setup — actually, it did pick all of those, and he just hadn't read the list.

The defaults that quietly own you

Some defaults are reversible. Swapping a CSS framework is annoying but doable. Changing your form library will ruin a Tuesday, not a quarter. Other defaults are not. They braid themselves into every feature you build and removing them means a rewrite.

  • Auth provider. If your boilerplate ships with a hosted auth service, you've committed to their pricing tiers, their session model, their account-linking quirks. Migrating later means rotating every user's credentials and praying the email goes through.
  • ORM and schema patterns. The first ten tables look the same in every ORM. The hundredth doesn't. Polymorphic relations, soft deletes, audit logs, multi-tenancy — these are the places where ORM choice quietly determines what kind of product you can build cheaply and what you'd need to rewrite half the data layer to support.
  • Multi-tenancy model. Users-only vs organizations-with-roles is not a refactor. It's an architectural shift. Pick wrong and any B2B pivot dies on contact with reality.
  • Background jobs. A boilerplate that punts on queues will quietly force you into synchronous webhooks and bloated request handlers, and you won't notice until a Stripe retry brings the server down on a Saturday.
  • Deploy target. Serverless vs long-running is not a swap. Cron, file uploads, long requests, streaming, websockets — half your roadmap is gated by this choice and the boilerplate's README rarely mentions it.

The defaults you can live with

Conversely there's a long list of things people obsess over that genuinely don't matter much. Your linter config. Your CSS framework. Whether the buttons are in a components/ui folder or a lib/ui folder. The exact shape of your form validation library. These are taste, not architecture. A boilerplate that gets these wrong costs you an afternoon of grumbling and nothing else.

The curriculum trap

Rui made a mistake I've watched dozens of developers make. He treated the boilerplate as a curriculum. He bought it partly to learn from it. He'd read the auth flow and finally understand JWTs. He'd read the Stripe integration and finally understand subscriptions. He'd absorb good patterns by osmosis.

He did not absorb good patterns by osmosis. Almost nobody does. Reading code you didn't write is not how engineers learn — it's how they confuse themselves into thinking they've learned. The patterns slide past your eyes, you nod along, and a week later you can't reproduce any of it without going back to the source.

People learn by deleting. By breaking. By writing the broken version themselves first and then noticing what they got wrong. The fastest way to actually learn what a boilerplate is doing is to start deleting files until something breaks, and then figure out why. Most people don't have the stomach for it because the boilerplate cost them three hundred dollars and breaking it feels like setting money on fire.

It isn't. The three hundred dollars was already gone. What's left is the codebase, and you can do whatever you want with it. Including, eventually, throwing it away.

When a boilerplate is actually the right call

I want to be careful here. The argument is not that boilerplates are bad. The argument is that they're a specific tool for a specific situation, and most people who buy them aren't in that situation.

The situations where a boilerplate genuinely earns its price:

  1. 1.You've shipped this shape of product before. An agency on its eleventh client SaaS that's structurally identical to the previous ten. A founder building their third dashboard-with-billing for a niche they already understand. You're not figuring out what to build. You're moving the known parts faster.
  2. 2.You need a v0 in a week to test a hypothesis. A CTO with a concrete experiment, a deadline, and a willingness to throw the code away when the experiment ends. The boilerplate is scaffolding for a prototype, not foundations for a company.
  3. 3.The product surface genuinely lives in the parts the boilerplate handles. Some products are dashboards over an API. Auth, billing, settings, and a couple of charts. If that describes what you're shipping honestly, not aspirationally, then yes — the boilerplate has done eighty percent of your work.
  4. 4.You are operationally constrained, not creatively constrained. You know exactly what to build and your bottleneck is hours in the day, not clarity in the head. A boilerplate buys hours. It cannot buy clarity.

The situations where a boilerplate will quietly hurt you:

  1. 1.First-time builder still figuring out the product surface. You don't yet know which decisions matter. You're going to accept defaults that look harmless and find out three months in that one of them was the product. This was Rui, three times.
  2. 2.Engineer who learns by writing. If you're the kind of person who only really understands a system once you've built a worse version of it, the boilerplate denies you the education your future self needed.
  3. 3.Product with an unusual primitive. If the core thing your app does is not in the boilerplate — if it's a graph, a stream, a spatial canvas, a multi-agent loop — then ninety percent of the boilerplate is irrelevant and the ten percent that isn't will fight you.
  4. 4.You're using purchase as procrastination. This is the hardest one to admit. Buying a boilerplate can feel like progress. It is not progress. It is shopping. If you find yourself comparing three of them on a Sunday afternoon, you are not building a company. You are avoiding building a company.

The weekend that worked

Back to Rui. September 2025. He'd been working a contract for a fintech in Lisbon for the summer, which paid well enough that he could take a month off. He took the month. He didn't open the old repos. He went for a lot of runs along the Douro and read a Le Carré novel he'd been meaning to read for years.

Somewhere in week three he started sketching in a notebook. Not code. Just sentences. What would I build if I had to write every single line of it. Not the actual constraint — he had Cursor open like everyone else — but the thought experiment. If nothing came for free, what would I bother building at all.

What came out, after a few notebook pages, was a tool for freelance translators. He had a friend who did it, complained about it constantly, and the complaints were specific. Glossary management was terrible. Most translators kept theirs in Excel. The existing tools were enterprise software with enterprise prices and enterprise UIs. There was room for something small and good.

He sat down on a Saturday morning at the kitchen table — the desk has the bad window, the kitchen has the good light — and started typing. Blank Next app. He installed exactly what he needed. He wrote his own auth, because he wanted magic links only, no passwords, no OAuth, because translators don't have GitHub accounts. He picked Postgres because he knew it. He skipped Stripe entirely for the first month because he wanted to validate the product with five free users before he wrote a billing page.

By Sunday night he had a glossary tool with a working share link. By the following Friday he had three translators using it. By December he had forty paying customers at nine euros a month, which is not a fortune, but it's three hundred and sixty euros that arrives every month without him doing anything, and more importantly it's the first thing he'd built that anyone had ever paid for twice.

The code is not better than the boilerplate's. In several places it's worse. He has a settings page that is, frankly, embarrassing. The point isn't that hand-rolled is technically superior. The point is that writing every line forced him to decide every line, and one of those decisions — that translators want magic links because they hate password managers, that glossaries should sync to a Google Sheet because that's where the work already lives — was the product. He couldn't have skipped his way to it. The boilerplate would have routed him around the decision and he'd never have known the decision existed.

What he does differently now

Rui still uses other people's code constantly. He's not a purist. He installs libraries. He copies snippets from Stack Overflow and from this directory and from his own old projects. The difference now is in what he refuses to outsource.

  • The first version of the data model is always his. He writes the schema on paper before he writes any code. If he can't fit it on one notebook page, the product isn't clear enough to start.
  • Auth is the second thing he writes, not the first. He builds something usable without login, sees who actually wants to use it, and only then adds accounts. Reverses the entire boilerplate workflow.
  • Billing comes after revenue, not before. He'll take payment via a Stripe payment link for the first five customers before he wires anything programmatic. If five people won't pay, the billing page is decoration.
  • He treats every default as a question. If a library makes a choice for him, he stops and asks whether he'd have made the same choice. Sometimes the answer is yes. The pause is the point.
  • He checks the directory before evaluating any new boilerplate. When he's tempted, which is still about once a quarter, he opens /dir/boilerplates and reads the entries with the question, would this remove a decision I actually need to make? Most of the time the answer is yes, and he closes the tab.

The bicycle, again

I keep coming back to the bicycle because the metaphor does real work. A bicycle is a tremendous machine for someone who knows where they're going. It triples your range. It makes a city smaller. It lets you carry things you couldn't carry on foot, arrive places you couldn't reach in a day, and feel a kind of efficient joy that walking doesn't give you. None of that is in dispute.

But none of it works if you don't know the route. Pedal hard in the wrong direction and you'll be exhausted, far from home, in a part of town you didn't mean to visit, and convinced the bicycle is the problem. It isn't. You are. Or, more kindly: the decision you didn't make is.

Most indie builders, including most of the very smart ones, buy a boilerplate before they've decided what they're building. They use the boilerplate as a way of putting off the decision. The boilerplate, being inanimate and helpful, obliges. It hands them a working app. They mistake working for decided. They ride the bicycle hard for six weeks and end up somewhere that nobody wanted them to go, including themselves.

Rui's habit now, when a builder friend asks him whether to buy a particular boilerplate, is to ask a different question first. He doesn't ask about the framework or the auth provider or the price. He asks: can you describe, in two sentences, what you're going to build, who's going to pay for it, and why they won't churn in month two. If they can, the boilerplate question becomes easy. If they can't, no boilerplate is going to help them. The boilerplate isn't the missing piece. The decision is.

He still checks /dir/boilerplates when one shows up on his timeline. Not to buy. To remember what the bicycles cost.

keep reading →