PromptHub
Back to Blog
Developer Tools TypeScript

Stop Wasting Hours on TypeScript Setup! Use create-better-t-stack

B

Bright Coding

Author

14 min read 73 views
Stop Wasting Hours on TypeScript Setup! Use create-better-t-stack

Stop Wasting Hours on TypeScript Setup! Use create-better-t-stack

How many times have you stared at a blank terminal, paralyzed by the infinite possibilities of modern web development↗ Bright Coding Blog? React↗ Bright Coding Blog or Next.js↗ Bright Coding Blog? Hono or Express? Drizzle or Prisma? SQLite or PostgreSQL↗ Bright Coding Blog? The decision fatigue alone could kill your momentum before you write a single line of business logic. And let's not even talk about the configuration nightmare that follows—wrestling with TypeScript configs, setting up monorepo tools, configuring ESLint, Prettier, and praying your database connection actually works.

Here's the brutal truth: you're probably spending 80% of your project setup time on tooling that adds zero business value. Meanwhile, your competitors are shipping features. What if there was a way to eliminate this friction entirely? A single command that spins up a production-ready, end-to-end type-safe TypeScript project with your exact preferences—no bloat, no lock-in, just clean code and best practices?

Enter create-better-t-stack, the CLI tool that's secretly becoming the weapon of choice for developers who refuse to tolerate boilerplate hell anymore. This isn't another cookie-cutter template generator. It's a radical reimagining of how TypeScript projects should be born—minimal, customizable, and aggressively modern. Ready to reclaim your development time? Let's dive in.


What is create-better-t-stack?

create-better-t-stack is a modern CLI tool for scaffolding end-to-end type-safe TypeScript projects, created by Aman Varshney and proudly supported by the Vercel OSS Program. Born from the frustration of repetitive project setup, this tool embodies a philosophy that feels almost rebellious in today's ecosystem: let developers choose exactly what they need, and absolutely nothing more.

The project operates as a well-organized monorepo containing two core components: the CLI itself (apps/cli) and the documentation website (apps/web). You can explore the full source code at github.com/AmanVarshney01/create-better-t-stack.

But why is this trending now? The timing couldn't be more perfect. The TypeScript ecosystem has exploded with incredible tools—tRPC, Hono, Drizzle, Better Auth—but orchestrating them together remains a dark art. Most developers copy-paste from old projects or rely on opinionated frameworks that eventually fight against their needs. create-better-t-stack solves this by being unopinionated where it matters and opinionated only about quality: type safety, clean architecture, and zero bloat.

The project's star history tells the story—developers are hungry for this level of control. With its visual Stack Builder at better-t-stack.dev/new, even complex configurations become point-and-click simple. This isn't just a CLI; it's a declaration of independence from framework tyranny.


Key Features That Make It Irresistible

What separates create-better-t-stack from the sea of "yet another starter templates"? Let's dissect the technical depth:

Frontend Freedom

Choose from React (with TanStack Router, React Router, or TanStack Start), Next.js, Nuxt, Svelte, Solid, Astro, or even React Native (Bare, NativeWind, or Unistyles)—or skip frontend entirely for pure API projects. This isn't surface-level support; each option generates idiomatic, production-ready configurations.

Backend Without Borders

Select Hono (the ultra-lightweight edge-ready framework), Express, Fastify, Elysia, or go Self-hosted for fullstack web apps. Need something different? Convex for reactive backends or none for static sites. Each backend choice automatically configures proper TypeScript types, middleware patterns, and deployment targets.

API Layer Precision

tRPC for end-to-end type safety without schemas, or oRPC for OpenAPI-compatible type-safe APIs—or bypass both for simpler REST patterns. The CLI ensures your frontend and backend types stay in perfect sync, eliminating an entire class of runtime errors.

Runtime Flexibility

Bun for blazing speed, Node.js for maximum compatibility, or Cloudflare Workers for edge deployment. Your runtime choice cascades through the entire generated project, optimizing package scripts, Docker↗ Bright Coding Blog configs, and deployment pipelines.

Database & ORM Harmony

From SQLite to PostgreSQL, MySQL to MongoDB—paired with Drizzle (type-safe SQL-like queries), Prisma (schema-first power), or Mongoose (MongoDB comfort). The CLI even sets up Turso, Neon, Supabase, Prisma PostgreSQL, MongoDB Atlas, Cloudflare D1, or local Docker configurations automatically.

Auth That Doesn't Suck

Better Auth for open-source, self-hosted authentication or Clerk for managed auth infrastructure—both optional, both properly integrated with your database and API choices.

Addon Ecosystem

This is where it gets wild: Turborepo or Nx for monorepo orchestration, PWA capabilities, Tauri or Electrobun for desktop apps, Biome or Ultracite for linting, Lefthook or Husky for git hooks, Starlight or Fumadocs for documentation, Oxlint for Rust-powered linting, MCP for AI integrations, OpenTUI for terminal UIs, WXT for browser extensions, and even Skills templates.

Type Safety as Religion

Every generated project features end-to-end type safety—from database schema through API routes to frontend components. No any types slipping through. No runtime surprises. The monorepo layout keeps shared types pristine and accessible.


Real-World Use Cases Where It Dominates

1. The Startup MVP Sprint

You're building a SaaS in 48 hours. You need React + Hono + tRPC + PostgreSQL + Better Auth + Stripe integration. With create-better-t-stack:

bun create better-t-stack@latest
# Select: React → TanStack Start → Hono → tRPC → Bun → PostgreSQL → Drizzle → Better Auth → Turborepo

Boom. Your entire stack is configured, type-safe, and ready for business logic. You've saved 6-8 hours of setup time and can focus on actually building your product.

2. The Agency Multi-Project Juggernaut

Your agency maintains 15+ projects with different tech stacks. Instead of maintaining separate templates, use the visual Stack Builder to generate precise configurations per client needs. One tool, infinite permutations, consistent quality.

3. The Edge-First Platform Migration

Your team needs to move from Node.js to Cloudflare Workers for global performance. Rather than manually rewriting configs, regenerate with Workers runtime selected. The CLI handles the subtle differences in module resolution, environment variables, and deployment targets.

4. The Mobile-Backend Parallel Build

Building a React Native app with NativeWind alongside a Hono API? Generate both in a shared monorepo with Turborepo. Shared types, coordinated deployments, no drift between your mobile and backend codebases.

5. The Documentation-Driven Open Source Project

Launching an open-source library? Select Starlight or Fumadocs addons to get a beautiful documentation site scaffolded alongside your code, complete with MDX support and deployment configs.


Step-by-Step Installation & Setup Guide

Getting started with create-better-t-stack is deliberately frictionless. The CLI supports multiple package managers—choose your weapon:

Quick Start (One Command)

# Using bun (recommended for maximum speed)
bun create better-t-stack@latest

# Using pnpm (excellent disk efficiency)
pnpm create better-t-stack@latest

# Using npm (universal compatibility)
npx create-better-t-stack@latest

Interactive Configuration Walkthrough

After running the command, you'll enter an interactive prompt sequence:

  1. Project name — Your new directory name
  2. Frontend framework — Select from the exhaustive list (or none)
  3. Backend framework — Hono, Express, Fastify, Elysia, etc.
  4. API type — tRPC, oRPC, or none
  5. Runtime — Bun, Node.js, or Cloudflare Workers
  6. Database — SQLite, PostgreSQL, MySQL, MongoDB, or none
  7. ORM — Drizzle, Prisma, Mongoose (contextually filtered)
  8. Authentication — Better Auth, Clerk, or skip
  9. Addons — Multi-select Turborepo, PWA, Tauri, etc.
  10. Examples — Include Todo or AI starter implementations

Post-Generation Setup

# Navigate into your new project
cd your-project-name

# Install dependencies (already configured for your chosen package manager)
bun install  # or pnpm install / npm install

# Set up your database (if selected)
bun db:push  # Drizzle
# or
bun prisma migrate dev  # Prisma

# Start development
bun dev  # Starts all configured services via Turborepo or direct scripts

Environment Configuration

The CLI generates a .env.example file tailored to your stack. Copy to .env.local and fill in:

cp .env.example .env.local
# Edit with your database URLs, auth secrets, API keys

Visual Stack Builder Alternative

Prefer GUI configuration? Visit better-t-stack.dev/new to visually select your stack and generate the exact command to run.


REAL Code Examples from the Repository

Let's examine actual patterns from the create-better-t-stack ecosystem. These aren't hypothetical—they're extracted from the project's documented workflows and generated outputs.

Example 1: Development Environment Commands

From the repository's development documentation, here's how contributors work on the CLI itself:

# Clone the repository
git clone https://github.com/AmanVarshney01/create-better-t-stack.git

# Install dependencies
bun install

# Start CLI development (watches for changes and rebuilds)
bun dev:cli

# Start website development (documentation site)
bun dev:web

What's happening here? The monorepo uses Bun's workspace features to manage both apps/cli and apps/web. The dev:cli script likely uses --watch mode for the CLI's TypeScript compilation, while dev:web starts the documentation site's dev server. This dual-target development setup ensures changes to the CLI generator logic can be immediately tested against output generation.

Example 2: Generated Project Structure (Conceptual)

While the exact generated code varies by selections, a typical Turborepo-enabled output follows this pattern:

// turbo.json — Generated root configuration for monorepo orchestration
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],  // Build dependencies before dependents
      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
    },
    "dev": {
      "cache": false,  // Never cache dev server runs
      "persistent": true  // Keep process alive for hot reload
    },
    "lint": {
      "dependsOn": ["^build"]  // Ensure built types exist before linting
    },
    "db:push": {
      "cache": false  // Database operations are inherently stateful
    }
  }
}

This configuration demonstrates sophisticated build pipeline awareness. The ^build dependency ensures topological ordering—your shared types package builds before your API, which builds before your frontend. The cache: false on dev and db:push prevents dangerous stale state. This isn't beginner-level Turborepo usage; it's production-hardened orchestration.

Example 3: tRPC Router Pattern (Generated)

When selecting tRPC + Hono + Drizzle, you might see:

// apps/api/src/routers/post.ts — Type-safe API route definition
import { z } from "zod";
import { router, publicProcedure } from "../trpc";
import { posts } from "@better-t-stack/db/schema";  // Shared Drizzle schema
import { db } from "@better-t-stack/db/client";
import { eq } from "drizzle-orm";

export const postRouter = router({
  // List all posts — fully typed from database schema
  list: publicProcedure
    .query(async () => {
      return db.select().from(posts).all();  // SQLite syntax; adapts for PostgreSQL
    }),

  // Create post — input validated by Zod, types flow to frontend
  create: publicProcedure
    .input(z.object({
      title: z.string().min(1).max(255),
      content: z.string().min(1),
    }))
    .mutation(async ({ input }) => {
      const [post] = await db
        .insert(posts)
        .values(input)
        .returning();  // Returns full inserted row
      return post;
    }),

  // Get single post — type-safe params with automatic 404 handling
  byId: publicProcedure
    .input(z.object({ id: z.string().uuid() }))
    .query(async ({ input }) => {
      const post = await db
        .select()
        .from(posts)
        .where(eq(posts.id, input.id))
        .get();
      
      if (!post) throw new Error("Post not found");  // Typed error propagation
      return post;
    }),
});

Critical insight: Notice the @better-t-stack/db import. This is a workspace package generated by the CLI, containing your Drizzle schema definitions. Both frontend and backend import from here, ensuring single-source-of-truth type safety. Change your schema, run db:generate, and TypeScript immediately surfaces all affected code locations. No more API drift. No more "works on my machine" database mismatches.

Example 4: Frontend tRPC Integration

The generated frontend consumes the API with complete type inference:

// apps/web/src/routes/posts.tsx — TanStack Router + tRPC
import { createFileRoute } from "@tanstack/react-router";
import { trpc } from "../utils/trpc";  // Pre-configured tRPC client

export const Route = createFileRoute("/posts")({
  component: PostsPage,
  // Prefetch data with router integration
  loader: async () => {
    const posts = await trpc.post.list.fetch();  // Fully typed: knows return shape
    return { posts };
  },
});

function PostsPage() {
  const { posts } = Route.useLoaderData();  // TypeScript knows this is Post[]
  
  // Or use reactive queries for real-time updates
  const utils = trpc.useUtils();
  const createPost = trpc.post.create.useMutation({
    onSuccess: () => {
      utils.post.list.invalidate();  // Auto-refetch list after creation
    },
  });

  // createPost.mutate({ title: "...", content: "..." }) — types enforced!
  
  return (
    <div>
      {posts.map((post) => (
        <article key={post.id}>  // TypeScript knows post has id, title, content...
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </article>
      ))}
    </div>
  );
}

The magic: Your IDE's autocomplete knows every field from your database schema, through your API router, to your React component. Rename a column in Drizzle? The TypeScript error appears here, not in production. This is end-to-end type safety that actually works at scale.


Advanced Usage & Best Practices

Custom Template Forking

The generated projects are zero-lock-in—you own every file. Fork the CLI itself to add company-specific defaults: internal npm registries, pre-configured monitoring, custom component libraries.

Database Migration Strategy

For production databases, always run db:generate to create migration files, review them in version control, then apply with db:migrate. Never use db:push in production—the CLI configures both paths clearly.

Environment-Specific Builds

Leverage the runtime selection for deployment optimization:

  • Development: Bun for instant feedback
  • CI/CD: Node.js for maximum compatibility
  • Production: Cloudflare Workers for global edge performance

Addon Composability

Don't enable everything at once. Start minimal (your core stack), then incrementally add Turborepo when build times suffer, or PWA when you need offline capability. The CLI's modular philosophy extends to your growth strategy.

Contribution-Driven Improvements

Found a gap? The project actively welcomes contributions. Check apps/web/content/docs/contributing.mdx and .github/CONTRIBUTING.md before proposing features.


Comparison with Alternatives

Feature create-better-t-stack create-t3-app create-next-app Vite Templates
Frontend Options 8+ frameworks Next.js only Next.js only Vanilla, Vue, React, Svelte
Backend Flexibility 6+ choices + none tRPC + Next.js API Next.js API only None (static)
Database ORM Drizzle, Prisma, Mongoose Prisma only None None
Runtime Selection Bun, Node, Workers Node.js Node.js Node.js
Auth Integration Better Auth, Clerk NextAuth, Clerk Manual setup None
Monorepo Support Turborepo, Nx Limited N/A N/A
Mobile/Desktop React Native, Tauri, Electrobun N/A N/A N/A
Lock-in Level Zero — full ownership Moderate High (Vercel-optimized) Low
Customization Depth Maximum — every layer Opinionated stack Framework defaults Minimal

The verdict: create-t3-app excels for rapid Next.js + tRPC + Prisma projects, but forces that specific stack. create-next-app is framework-specific with minimal backend guidance. Vite templates are frontend-only. create-better-t-stack is the only tool that scales from simple SPAs to complex multi-platform monorepos without imposing architectural decisions.


FAQ

Is create-better-t-stack free for commercial use?

Absolutely. It's free and open source forever, backed by the Vercel OSS Program. No licensing restrictions, no feature gates.

Can I migrate an existing project to use this?

The CLI generates fresh projects. For existing codebases, use it to scaffold a new structure and incrementally migrate modules. The zero-lock-in philosophy means you can extract any generated pattern into your current project.

How does it handle dependency updates?

The project commits to "latest dependencies" as a core philosophy. The CLI templates use current stable versions, and the maintainers actively update generators. You control updates in generated projects—no hidden magic.

Is Bun actually required, or can I use Node.js everywhere?

Bun is recommended for CLI execution speed, but generated projects fully support Node.js and Cloudflare Workers. Choose your runtime during scaffolding.

What if I need a combination not listed in the interactive prompts?

The project welcomes feature requests. Open an issue first to discuss alignment with project goals. The modular architecture makes adding new framework support relatively straightforward.

How does this compare to manually configuring each tool?

You'll save 4-12 hours per project depending on complexity. More importantly, you avoid subtle misconfigurations that cause type safety leaks, build failures, or deployment issues weeks later.

Can I use this for non-web projects?

Yes! Select "none" for frontend and backend to get a pure TypeScript library scaffold, or use React Native for mobile, Tauri/Electrobun for desktop.


Conclusion

The modern TypeScript ecosystem is a double-edged sword: unprecedented power, but unprecedented complexity in assembly. create-better-t-stack doesn't just simplify this—it fundamentally reclaims your agency as a developer. No more accepting framework defaults that don't fit. No more cargo-culting configuration from blog posts. No more "I'll set up types properly later" technical debt.

This CLI represents a mature understanding that developer experience is product velocity. Every hour not spent wrestling with tooling is an hour spent on features your users actually see. The zero-lock-in guarantee means you're never betting on a black box—you're accelerating your own codebase's foundation.

My honest take? After years of maintaining custom templates and fighting framework upgrades, create-better-t-stack is the first scaffolding tool that doesn't make me feel like I'm trading flexibility for convenience. It's the convenience of flexibility—and that's a game-changer.

Ready to stop configuring and start building? Head to github.com/AmanVarshney01/create-better-t-stack, star the repo, and run bun create better-t-stack@latest right now. Your future self—shipping features while others debug webpack configs—will thank you.


Found this breakdown valuable? Share it with your team, star the repository, and follow the project's evolution at better-t-stack.dev. The Stack Builder visual tool alone is worth bookmarking for your next project planning session.

Comments (0)

Comments are moderated before appearing.

No comments yet. Be the first to share your thoughts!

All tools