Project Structure
Understanding the structure of projects created by Better-T-Stack CLI
Overview
Better-T-Stack CLI scaffolds a monorepo with apps/*
and, when needed, packages/*
. The exact structure depends on your choices (frontend, backend, API, database/ORM, auth, addons, runtime, deploy). This page mirrors what the CLI actually writes.
Root layout
At the repository root you will see:
/
├── apps/ # Applications (web, server, native, docs)
├── packages/ # Only when needed (e.g. Convex backend)
├── package.json # Root package.json (scripts updated by CLI)
├── bts.jsonc # Better‑T Stack configuration (always written)
├── turbo.json # Only when addon "turborepo" is selected
├── pnpm-workspace.yaml # Only when packageManager=pnpm
├── bunfig.toml # Only when packageManager=bun
├── .npmrc # pnpm + (native or nuxt) for alias resolution
└── README.md # Generated quickstart
Notes:
bts.jsonc
lets the CLI detect and enhance your project later; keep it if you plan to usebts add
.turbo.json
exists only if you picked the Turborepo addon.
Monorepo structure by backend
Non-Convex backends (hono, express, fastify, elysia, next)
my-app/
├── apps/
│ ├── web/ # Present if you picked a web framework
│ ├── server/ # Backend API (framework depends on your choice)
│ ├── native/ # Present if you picked React Native (Expo)
│ └── docs/ # Present if you picked the Starlight/Fumadocs addon
└── packages/ # May exist but not used by default
Convex backend
my-app/
├── apps/
│ ├── web/ # Present if you picked a web framework
│ ├── native/ # Present if you picked React Native (Expo)
│ └── docs/ # Present if you picked the Starlight/Fumadocs addon
└── packages/
└── backend/ # Convex functions, schema and config
Frontend Structure (apps/web)
The structure varies by framework. Items marked “(auth)” or “(API)” appear only when those options are enabled.
React with TanStack Router
apps/web/
├── src/
│ ├── components/
│ │ ├── ui/ # shadcn/ui primitives (from web base)
│ │ ├── header.tsx
│ │ ├── loader.tsx
│ │ ├── mode-toggle.tsx
│ │ └── theme-provider.tsx
│ ├── routes/
│ │ ├── __root.tsx # Root layout
│ │ └── index.tsx # Home
│ ├── lib/
│ │ └── utils.ts
│ ├── utils/
│ │ └── trpc.ts (API=trpc) | orpc.ts (API=orpc)
│ ├── main.tsx
│ └── index.css
├── index.html
├── components.json # shadcn/ui config
├── tsconfig.json
├── vite.config.ts
└── package.json
Next.js
apps/web/
├── src/
│ ├── app/
│ │ ├── layout.tsx
│ │ └── page.tsx
│ └── components/
│ ├── mode-toggle.tsx
│ ├── providers.tsx
│ └── theme-provider.tsx
├── components.json
├── next.config.ts
├── postcss.config.mjs
├── tsconfig.json
└── package.json
Notes:
- If you choose
backend=next
, the backend is scaffolded separately inapps/server
. The web app does not include API routes. - (auth) adds
src/app/login/*
andsrc/app/dashboard/*
plus sign-in components.
Backend Structure (apps/server)
The server structure depends on your backend choice:
Hono backend
apps/server/
├── src/
│ ├── routers/
│ │ └── index.ts # Base router
│ └── index.ts # Hono app entry
├── package.json
└── tsconfig.json
Express / Fastify / Elysia
apps/server/
├── src/
│ └── index.ts # Framework entry
├── package.json
└── tsconfig.json
Next (backend)
apps/server/
├── src/
│ ├── app/
│ │ └── route.ts # App Router endpoint
│ └── middleware.ts
├── next.config.ts
├── tsconfig.json
└── package.json
Workers runtime (optional)
When runtime=workers
, you’ll also get:
apps/server/
└── wrangler.jsonc # Cloudflare Workers config (template)
API and auth scaffolding (conditional):
- API=trpc:
src/lib/trpc.ts
,src/lib/context.ts
- API=orpc:
src/lib/orpc.ts
,src/lib/context.ts
- Auth:
src/lib/auth.ts
Database Configuration
Added only when you selected a database and ORM:
Drizzle ORM
apps/server/
├── src/db/
│ └── index.ts # Database connection
├── drizzle.config.ts # Drizzle configuration
└── drizzle/ # Generated migrations (after you run commands)
Prisma ORM
apps/server/
└── prisma/
├── schema.prisma # Database schema
└── migrations/ # Generated after running Prisma commands
Mongoose (MongoDB)
apps/server/
└── src/db/
└── index.ts # Mongoose connection
Auth + DB
If you selected auth, additional files are added for your ORM:
- Drizzle:
src/db/schema/auth.ts
- Prisma:
prisma/schema/auth.prisma
- Mongoose:
src/db/models/auth.model.ts
Docker compose (optional)
If dbSetup=docker
, a docker-compose.yml
is added in apps/server/
for your database.
Native App Structure (apps/native)
Created only when you include React Native (NativeWind or Unistyles):
apps/native/
├── app/ # App screens
│ ├── (tabs)/ # Tab navigation
│ ├── _layout.tsx # Root layout
│ └── index.tsx # Home screen
├── components/ # React Native components
├── lib/ # Utilities
├── assets/ # Images, fonts
├── app.json # Expo configuration
├── package.json # Dependencies
└── tsconfig.json # TypeScript config
If an API is selected, a client utility is added:
- API=trpc:
utils/trpc.ts
- API=orpc:
utils/orpc.ts
Documentation Structure (apps/docs)
When using Starlight or Fumadocs addon:
apps/docs/
├── src/
│ ├── content/ # Documentation content
│ │ └── docs/ # Doc pages
│ └── pages/ # Astro pages (Starlight)
├── astro.config.mjs # Astro config (Starlight)
├── package.json
└── tsconfig.json
Configuration Files
Better-T-Stack Config (bts.jsonc)
{
"$schema": "https://r2.better-t-stack.dev/schema.json",
"version": "<cli-version>",
"createdAt": "<timestamp>",
"database": "<none|sqlite|postgres|mysql|mongodb>",
"orm": "<none|drizzle|prisma|mongoose>",
"backend": "<none|hono|express|fastify|elysia|next|convex>",
"runtime": "<bun|node|workers>",
"frontend": ["<next|tanstack-router|react-router|tanstack-start|nuxt|svelte|solid>"] ,
"addons": ["<turborepo|biome|husky|pwa|starlight>"] ,
"examples": ["<ai|todo|none>"] ,
"auth": <"better-auth"|"clerk"|"none">,
"packageManager": "<bun|pnpm|npm>",
"dbSetup": "<none|docker|d1>",
"api": "<none|trpc|orpc>",
"webDeploy": "<none|wrangler|alchemy>",
"serverDeploy": "<none|wrangler|alchemy>"
}
Turborepo Config (turbo.json)
Generated only if you chose the Turborepo addon.
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
Shared packages
By default, no shared packages are created. You will see packages/backend
only when using the Convex backend. You can add more packages manually as your repo grows.
packages/
└── backend/ # Only with Convex backend
Development Scripts
Scripts are adjusted based on your package manager and whether the Turborepo addon is selected.
With Turborepo:
{
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
"check-types": "turbo check-types",
"dev:web": "turbo -F web dev",
"dev:server": "turbo -F server dev",
"db:push": "turbo -F server db:push",
"db:studio": "turbo -F server db:studio"
}
}
Without Turborepo (example for Bun):
{
"scripts": {
"dev": "bun run --filter '*' dev",
"build": "bun run --filter '*' build",
"check-types": "bun run --filter '*' check-types",
"dev:web": "bun run --filter web dev",
"dev:server": "bun run --filter server dev"
}
}
Notes:
- Convex adds
dev:setup
for initial backend configuration.
Key Details
- Monorepo:
apps/*
always;packages/*
only when needed (Convex) - React web base: shadcn/ui primitives,
components.json
, common utilities - API clients:
src/utils/trpc.ts
orsrc/utils/orpc.ts
added to web/native when selected - Auth: Adds authentication setup based on provider:
better-auth
:src/lib/auth.ts
on server and login/dashboard pages on web appclerk
: Clerk provider setup and authentication components
- ORM/DB: Drizzle/Prisma/Mongoose files added only when selected
- Extras:
pnpm-workspace.yaml
,bunfig.toml
, or.npmrc
added based on package manager and choices - Deploy: Workers deploy adds
wrangler.jsonc
templates to the appropriate app(s)
This reflects the actual files written by the CLI so new projects match what’s documented here.