Project Templates
What files and code better-ts-stack actually generates
This page shows what files and scripts are generated for each selection in the CLI.
Backend API Template (Express)
Selecting Backend API with Express generates:
The base backend template generates exactly two source files: src/index.ts
and src/routes/health.ts. There is no app.ts, routes/index.ts,
middleware/errorHandler.ts, types/ directory, or README.md in the base
output.
src/index.ts
The entry point configures Express middleware, mounts the health route, and starts the server:
import cors from "cors";
import dotenv from "dotenv";
import express, { Express, Request, Response } from "express";
import helmet from "helmet";
import morgan from "morgan";
import healthRouter from "./routes/health";
dotenv.config();
const app: Express = express();
const port = process.env.PORT || 3000;
app.use(helmet());
app.use(cors());
app.use(morgan("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use("/health", healthRouter);
// 404 handler
app.use((_req: Request, res: Response) => {
res.status(404).json({ error: "Not Found" });
});
// Error handler
app.use((err: Error, _req: Request, res: Response) => {
console.error(err.stack);
res.status(500).json({ error: "Internal Server Error" });
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
export default app;Generated package.json scripts
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"format": "prettier --write \"src/**/*.ts\"",
"type:check": "tsc --noEmit"
}
}With bun as the package manager,
devbecomesbun --watch src/index.ts.
Full-stack Templates
Selecting Full-stack generates a single application at the project root. There are no separate backend/ or frontend/ subdirectories. You pick the frontend framework in the prompt.
Next.js
Generated package.json scripts
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
}
}TanStack Start
src/
|-- routes/ # File-based routes (__root.tsx, index.tsx)
|-- routeTree.gen.ts # Generated route tree
|-- router.tsx # createRouter() + QueryClient + SSR query integration
|-- lib/utils.ts # cn() helper
|-- components/ui/ # shadcn-compatible base UI primitives
|-- styles/app.css # Tailwind CSS v4 import + base styles
vite.config.ts # tanstackStart() + tailwind + react plugins
components.json # shadcn CLI-compatible component config
package.json # "type": "module"The template uses the ~/* path alias mapped to src/*. The build produces a
fetch-compatible SSR handler via Vite (no Nitro), and the start script serves
it with srvx. The CLI includes the initial route tree, and TanStack Router
regenerates it during Vite development and builds.
Generated package.json scripts
{
"scripts": {
"dev": "vite dev",
"build": "vite build",
"start": "srvx --prod -s ../client dist/server/server.js",
"preview": "vite preview",
"type:check": "tsc --noEmit",
"lint": "eslint src"
}
}With Database Modules
PostgreSQL + Prisma
Scripts added to package.json:
npm run prisma:generate
npm run prisma:migrate # prisma migrate dev
npm run prisma:studioEnvironment variable added: DATABASE_URL
PostgreSQL + Drizzle
For TanStack Start, the schema and client live in
src/lib/schema.tsandsrc/lib/db.ts(drizzle.config.tspoints at./src/lib/schema.ts).
Scripts added to package.json:
npm run db:generate # drizzle-kit generate
npm run db:migrate # drizzle-kit migrate
npm run db:studio # drizzle-kit studioEnvironment variable added: DATABASE_URL
If Better Auth is also enabled with Drizzle, the generated lib/schema.ts (or
src/lib/schema.ts for TanStack) contains the Better Auth core tables instead
of a sample table.
MongoDB + Mongoose
Environment variable added: MONGODB_URI
Mongoose adds no extra npm scripts. The connection is established in
src/lib/db.ts.
With Auth Module
Environment variables added: JWT_SECRET, JWT_EXPIRES_IN
The auth router is mounted at /auth in src/index.ts.
With Docker Module
The Dockerfile is framework-aware: it uses a Next.js standalone output stage for Next.js projects, an srvx-based production stage for TanStack Start, and a Node.js multi-stage build for Express backends. Both full-stack images run npm run build (and Prisma generate for the database variant) and copy the build output to a non-root Alpine production image.
Scripts added to package.json:
npm run docker:build # docker build -t <projectName> .
npm run docker:up # docker compose up -d
npm run docker:down # docker compose down
npm run docker:logs # docker compose logs -fSupported Combinations
| Framework | App type | Database | ORM/ODM | Auth | Status |
|---|---|---|---|---|---|
| Express | Backend | none | - | JWT | Yes |
| Express | Backend | PostgreSQL | Prisma | JWT | Yes |
| Express | Backend | MongoDB | Mongoose | JWT | Yes |
| Next.js | Full-stack | none | - | - | Yes |
| Next.js | Full-stack | PostgreSQL | Prisma | Better Auth | Yes |
| Next.js | Full-stack | PostgreSQL | Drizzle | Better Auth | Yes |
| Next.js | Full-stack | MongoDB | Mongoose | Better Auth | Yes |
| TanStack | Full-stack | none | - | - | Yes |
| TanStack | Full-stack | PostgreSQL | Prisma | Better Auth | Yes |
| TanStack | Full-stack | PostgreSQL | Drizzle | Better Auth | Yes |
| TanStack | Full-stack | MongoDB | Mongoose | Better Auth | Yes |
| - | Backend | NestJS | - | - | Coming soon |