Opinionated by Design: Why I Chose Sensible Defaults Over Endless Configuration

When people hear about a new project scaffolding tool, one of the first questions they ask is: "Can I choose React Query or TanStack Query?" "What about pnpm instead of Bun?" "Can I use ESLint instead of Biome?" "Can I choose Radix instead of Base UI?" "Can I skip Tailwind?" These are reasonable questions. In fact, I asked myself the same ones while building create-notils. My first instinct was to make everything configurable. The more I thought about it, the more I realized I was about to build
When people hear about a new project scaffolding tool, one of the first questions they ask is:
"Can I choose React Query or TanStack Query?"
"What about pnpm instead of Bun?"
"Can I use ESLint instead of Biome?"
"Can I choose Radix instead of Base UI?"
"Can I skip Tailwind?"
These are reasonable questions. In fact, I asked myself the same ones while building create-notils. My first instinct was to make everything configurable.
The more I thought about it, the more I realized I was about to build something I didn't actually want to use.
The Configuration Trap
Most project generators start simple. Then someone requests another option. Another package manager. Another ORM. Another authentication provider. Another CSS framework. Another UI library.
Eventually the CLI starts looking like this:
? Which package manager?
❯ npm
pnpm
yarn
bun
? Which CSS framework?
? Which ORM?
? Which auth library?
? Which formatter?
? Which icon library?
? Which deployment target?
Enter fullscreen mode Exit fullscreen mode
It feels flexible. But every new option creates more combinations to support. Five choices in one prompt don't create five possible projects. They multiply with every other prompt. The complexity grows much faster than the number of features.
I Built the Tool I Wanted to Use
One thing I've learned from building side projects is this: the first user should always be yourself.
Every project I start today uses almost exactly the same stack:
- Next.js 16
- React 19
- Bun
- Tailwind CSS v4
- shadcn/ui
- Base UI
- Biome
- TypeScript
- Turborepo (when needed)
I wasn't switching between ten different combinations every week. I was rebuilding the same foundation over and over. So instead of asking twenty questions during scaffolding, I decided to optimize for the workflow I actually have.
npx create-notils my-app
Enter fullscreen mode Exit fullscreen mode
A few seconds later, I'm writing features instead of answering prompts.
Opinionated Doesn't Mean Closed
There's an important distinction between opinionated and restrictive.
Some tools hide their implementation behind abstractions. Others generate code you aren't expected to touch. That isn't the direction I wanted.
Everything create-notils generates belongs to you. The UI components are source files. The configuration files are yours. The project structure is yours. If you don't like one of my decisions, you can change it immediately.
There is no vendor lock-in. The CLI gives you a starting point, not a framework you have to live inside forever.
Defaults Should Be Battle-Tested
Every opinion in create-notils comes from building real projects.
I didn't choose Bun because it was trendy; I chose it because it's the package manager and runtime I use every day. I didn't choose Biome because it's newer than ESLint; I chose it because having one fast tool for linting and formatting simplified my workflow.
The same applies to Tailwind CSS v4, shadcn/ui, Base UI, and the rest of the stack. The goal isn't to pick the newest tools. The goal is to reduce decisions that I already know the answer to.
Configuration Can Come Later
One question I get is: "What if someone doesn't want your stack?"
That's a fair point. The answer is: not every problem needs to be solved in version 0.1.
As create-notils evolves, it will become more modular. Instead of exposing every decision through dozens of prompts, I'm exploring a different direction: generate a solid foundation first, then let developers add capabilities as they need them.
- Authentication
- Database
- Storage
- Payments
- Monitoring
Those additions can evolve independently without turning the initial project creation into an interrogation.
Optimizing for Momentum
One of the biggest costs of starting a new project isn't writing code. It's context switching.
Every prompt interrupts momentum. Every configuration choice forces another decision before you've even written your first component. I'd rather spend those first ten minutes building a homepage than deciding which formatter to use.
That's why create-notils intentionally has very few questions. It assumes a sensible set of defaults and gets out of the way.
The Road Ahead
Being opinionated today doesn't prevent flexibility tomorrow. In fact, I think it makes future flexibility easier.
By first defining a production-ready baseline, I can later introduce optional capabilities without compromising the core experience. The foundation stays consistent. The project grows through composition instead of endless configuration.
That's the direction I want to explore next. In the next article, I'll take a closer look at how create-notils is organized internally, why the UI lives in its own package, and how that decision helps keep multiple applications consistent without duplicating components.
Try out the compiler architecture yourself by running
npx create-notils my-app, or check out the source code on GitHub.


