Skip to content
RT
Go back

How I start indie projects: Better-T-Stack and the tools inside it

Shipping small products is rarely blocked by “which framework is best.” It’s blocked by setup tax: monorepo layout, typed API, auth, ORM, lint, package manager, deploy shape. Every week you spend re-deciding those is a week you’re not testing whether the product matters.

My default answer to that tax is Better-T-Stack (create-better-t-stack). It isn’t a religion. It’s a scaffold that gets a type-safe TypeScript monorepo to a place where I can ship the first real feature the same day.

This post is not a feature tour of every CLI option. It’s the subset I actually pick when I start (or restart) indie projects—and how those tools fit together once the scaffold is gone.

The job of a scaffold

A good starter does three things:

  1. Removes irreversible busywork — workspace layout, shared TS config, package scripts, a place for apps/ and packages/.
  2. Locks end-to-end types early — so the web app, the server, and the DB layer don’t drift into three different stories.
  3. Leaves room to delete — if a choice is wrong, you can rip it out without rewriting the whole product.

Better-T-Stack is interactive (or fully flag-driven). You choose frontend, backend, runtime, database, ORM, API layer, auth, payments, and addons. The output is a real monorepo, not a demo page with a TODO comment.

I keep a bts.jsonc in those repos. It’s a snapshot of the choices at scaffold time. Safe to delete; useful as a breadcrumb of why the tree looks the way it does.

What I usually pick

Exact combos change by product. Patterns repeat.

Package manager and monorepo: Bun + Turborepo

Most of my recent scaffolds land on Bun as package manager (sometimes pnpm). Turborepo shows up almost every time I care about more than one app in the same repo: web, server, sometimes native, shared packages.

Indie reality: one person, several surfaces. A monorepo with a task graph beats five half-synced folders.

Backend: Hono (often on Bun or Workers)

Hono is the API surface I reach for when I want something small and explicit. In some projects the runtime is Bun; in others it’s Cloudflare Workers via the stack’s Workers path. The point isn’t “edge for its own sake.” It’s a thin HTTP layer that doesn’t force a framework theology on day one.

Data: Postgres + Drizzle (or SQLite/D1 when the deploy story wants it)

Default mental model:

NeedChoice I tend to make
Local product with a real relational DBPostgres + Drizzle, often with Docker for local DB
Edge / Cloudflare-shaped deploySQLite + D1 + Drizzle when that matches the deploy target

Drizzle stays because the schema lives in TypeScript and migrations stay reviewable. I don’t want a black-box “magic models” layer when I’m alone on the product.

API contract: oRPC

When the scaffold offers a typed RPC path, I often take oRPC. Shared input/output types between client and server cut a whole class of “the API returned something else” bugs—especially when the same monorepo owns web and server.

Not every project needs RPC on day one. When the surface is simple, plain Hono routes are fine. When the product grows multiple client call sites, types across the wire pay rent.

Auth: Better Auth when I need accounts

Better Auth is the default I enable when the product has users (not every MVP does). It’s optional in the scaffold; I leave auth: none until login is a real requirement. Auth too early is a distraction. Auth too late is a rewrite.

Payments: Polar when the product sells

On stacks that include payments, I’ve used Polar with Better Auth where that integration is the point. Again: only when money is in scope. Scaffolding Stripe/Polar ceremony before the first paid use case is how side projects die of configuration.

Frontend: depends on the product

Better-T-Stack is not “one frontend.” What I’ve actually scaffolded:

The skill is matching the frontend to the distribution of the product, not to Twitter trends that week.

Lint and agent hygiene: Biome / Ultracite / Oxlint, Ruler, Skills

Addons I keep seeing in my trees:

I’m not collecting linters for sport. I want check to be one command and I want AI tools to read the same conventions I do.

How the pieces fit (one mental model)

create-better-t-stack


   monorepo (Turborepo)
   ├── apps/web     (TanStack / Next / …)
   ├── apps/server  (Hono)
   ├── apps/native  (optional)
   └── packages/*   (db, auth, shared types)

        ├── Drizzle schema → Postgres / D1
        ├── oRPC or HTTP routes
        ├── Better Auth (when needed)
        └── Polar (when money is real)

The scaffold’s job is to draw that diagram in files. My job after that is product: one painful workflow, one path to money or learning, not infinite architecture.

What I deliberately don’t put in every project

The anti-pattern is treating Better-T-Stack as a shopping cart. It’s a starting configuration, not a scorecard of how modern you are.

When I wouldn’t use it

Scaffolds are leverage when you’ll live in the repo for months. They’re overhead when the idea dies in a weekend—and that’s fine; just don’t romanticize either outcome.

A practical starting recipe

If I were spinning up another small SaaS-shaped product tomorrow, the defaults I’d type without overthinking:

  1. Better-T-Stack interactive (or the reproducible command it prints)
  2. Bun + Turborepo
  3. Hono backend
  4. Drizzle + Postgres (Docker locally) or D1 if the deploy story is Cloudflare-first
  5. oRPC if client/server share the monorepo
  6. TanStack Start or TanStack Router for web (Next only if I have a concrete reason)
  7. Better Auth only when accounts are required
  8. Biome/Ultracite or Oxlint — one lint path
  9. Ship a single user-visible loop before adding Polar, native, or a second app

Then delete anything the scaffold added that I don’t understand. If I can’t explain a package in one sentence, it doesn’t belong in v0.

The portable rule

Pick a scaffold that encodes type-safe defaults. Keep the tools that protect speed and honesty. Drop the rest until the product forces them back in.

Better-T-Stack is where I start most TypeScript indie apps. The tools inside it—Hono, Drizzle, oRPC, Better Auth, Turborepo, Bun, TanStack, lint addons—only earn a permanent seat if they still make the next commit easier.

If you want the builder itself: better-t-stack.dev · CLI: create-better-t-stack · GitHub


Share this post on:

Next Post
Hello World