Modules Overview
The modular architecture of better-ts-stack projects
How modules work
A generated project is built from modules. Each module adds its own template files, npm dependencies, scripts, and environment variables. Only the modules you select are added.
Available Modules
Backend
Express server with TypeScript, routing, and middleware. Used by every Backend API project
Frontend
Next.js 16 or TanStack Start with React 19 and Tailwind CSS v4. Chosen in the full-stack framework prompt
Database
PostgreSQL (Prisma or Drizzle) or MongoDB (Mongoose). Chosen in two prompts: database, then ORM
Auth
JWT + bcrypt for Express, Better Auth for Next.js and TanStack Start (requires a database)
Docker
Multi-stage Dockerfile and docker-compose.yml. Available for every app type
How Modules Are Selected
Your prompt answers decide which modules are added:
| Prompt answer | Module(s) activated |
|---|---|
App type = backend | Express base module |
App type = fullstack + framework = nextjs | Next.js base module |
App type = fullstack + framework = tanstack | TanStack Start base module |
Database = postgresql + ORM = prisma | Prisma module for the chosen framework |
Database = postgresql + ORM = drizzle | Drizzle module for the chosen framework |
Database = mongodb + ORM = mongoose | Mongoose module (Express, Next.js, TanStack) |
Auth = yes (Express) | JWT auth module |
Auth = yes (Next.js / TanStack, database selected) | Better Auth module |
Docker = yes | Docker module |
Better Auth is only prompted for Next.js and TanStack Start projects when a
database has been selected. If database type is none, auth is skipped
automatically.
How Module Merging Works
Each module has a config.json. When you select several modules, the CLI merges them:
- Dependencies: merged into a single
package.json - Scripts: merged, so each module can add its own scripts
- Environment variables: merged into
.env.example/.env - Template files: each module's files are copied into the project
Example: Express + PostgreSQL + Prisma + JWT Auth
The final package.json will include:
{
"dependencies": {
"express": "^5.2.1",
"cors": "^2.8.6",
"cross-env": "^10.1.0",
"helmet": "^8.3.0",
"morgan": "^1.12.0",
"dotenv": "^17.4.2",
"@prisma/client": "^7.10.0",
"bcrypt": "^6.0.0",
"jsonwebtoken": "^9.0.3"
},
"scripts": {
"dev": "cross-env NODE_ENV=development tsx watch src/index.ts",
"build": "tsc",
"start": "cross-env NODE_ENV=production node dist/index.js",
"lint": "eslint src",
"format": "prettier --write \"src/**/*.ts\"",
"type:check": "tsc --noEmit",
"prisma:generate": "prisma generate",
"prisma:migrate": "prisma migrate dev",
"prisma:studio": "prisma studio",
"prebuild": "prisma generate"
}
}Module Availability Matrix
| Module | Backend (Express) | Backend (NestJS) | Full-stack (Next.js) | Full-stack (TanStack) |
|---|---|---|---|---|
| Express base | Always | - | - | - |
| NestJS base | - | Always | - | - |
| Next.js base | - | - | Always | - |
| TanStack base | - | - | - | Always |
| PostgreSQL + Prisma | Yes | Yes | Yes | Yes |
| PostgreSQL + Drizzle | Yes | Yes | Yes | Yes |
| MongoDB + Mongoose | Yes | Yes | Yes | Yes |
| JWT Auth | Yes | Yes | - | - |
| Better Auth | - | - | Yes (requires DB) | Yes (requires DB) |
| Docker | Yes | Yes | Yes | Yes |
Extending After Generation
All generated code is plain TypeScript, so you can edit any file.
Adding to the backend
- New routes ->
src/routes/ - New middleware ->
src/middleware/ - New controllers ->
src/controllers/
Adding to the frontend
- Next.js: new pages ->
app/, API routes ->app/api/, components ->components/ - TanStack Start: new routes ->
src/routes/(Vite regeneratessrc/routeTree.gen.tsduring dev/build), server functions ->createServerFn, components ->src/components/
Adding to the database
- Prisma: edit
prisma/schema.prisma, then runnpm run prisma:migrate - Drizzle: edit
lib/schema.ts(Next.js) orsrc/lib/schema.ts(Express, TanStack Start), then runnpm run db:generate && npm run db:migrate - Mongoose: add new model files to
src/models/(models/in Next.js)