Development Workflow
This guide covers everything you need to know for daily development with TurboStack.
Development Commands
Starting Applications
# Start all applications (parallel with Turborepo)
bun run dev
Starts frontend (4100), backend (4101), and docs (4102) # Start only frontend
bun run dev:web
# Start only backend
bun run dev:api
# Start only documentation
bun run dev:docs
Application Port URL 🖥️ Frontend 4100 localhost:4100 ⚡ Backend 4101 localhost:4101 📚 API Docs 4101 localhost:4101/openapi 📖 Docs Site 4102 localhost:4102
Database Commands
Generate Client bash bun run db:generate Regenerate Prisma client after schema
changes
Push Schema bash bun run db:push Apply schema to database (dev only)
Create Migration bash bun run db:migrate Create and apply migration files
Prisma Studio bash bun run db:studio Visual database browser at localhost:5555
Development Workflow
1. Adding a New API Route
Create Route File
Create a new route file in apps/backend/src/routes/: // apps/backend/src/routes/products.ts
import { Elysia , t } from "elysia" ;
import { db } from "@repo/database" ;
export const productRoutes = new Elysia ({ prefix: "/products" })
. get ( "/" , async () => {
const products = await db . product . findMany ();
return { success: true , data: products };
})
. post (
"/" ,
async ({ body }) => {
const product = await db . product . create ({
data: body ,
});
return { success: true , data: product };
},
{
body: t . Object ({
name: t . String (),
price: t . Number (),
}),
}
);
Register Route
Add to apps/backend/src/index.ts: import { productRoutes } from "./routes/products" ;
app . use ( productRoutes );
2. Adding a UI Component
Create Component
Add component to packages/ui/src/: // packages/ui/src/input.tsx
import * as React from "react" ;
export interface InputProps
extends React . InputHTMLAttributes < HTMLInputElement > {}
export const Input = React . forwardRef < HTMLInputElement , InputProps >(
({ className , ... props }, ref ) => {
return < input ref = { ref } className = { className } { ... props } /> ;
}
);
Input . displayName = "Input" ;
Export Component
Add to packages/ui/src/index.ts: export { Input , type InputProps } from "./input" ;
Use in Frontend
// apps/frontend/app/page.tsx
import { Input } from "@repo/shadcn-ui" ;
export default function Page () {
return < Input placeholder = "Enter text..." /> ;
}
3. Database Schema Update
Update Schema
Edit packages/database/prisma/schema.prisma: model Post {
id String @id @default ( cuid ())
title String
content String ?
authorId String
author User @relation ( fields : [ authorId ], references : [ id ] )
createdAt DateTime @default ( now ())
updatedAt DateTime @updatedAt
@@map ( "posts" )
}
model User {
id String @id @default ( cuid ())
// ... existing fields
posts Post []
}
Create Migration
bash bun run db:migrate Enter a descriptive migration name when
prompted.
Generate Client
Regenerate Prisma client with new types.
Turborepo Filtering
Run commands for specific packages:
Build Specific Package
Dev Mode Filtering
# Build only UI package
bun run build --filter=@repo/shadcn-ui
# Build frontend and its dependencies
bun run build --filter=frontend...
# Build package and its dependents
bun run build --filter=...@repo/database
Code Quality
Linting # Run ESLint
bun run lint
# Auto-fix issues
bun run lint:fix
Type Check # TypeScript check
bun run check-types
Format # Format with Prettier
bun run format
Build # Build all apps
bun run build
Debugging
Backend Debugging
Console Logs
VS Code Debugger
Use console.log() or console.error(): console . log ( "User data:" , user );
console . error ( "Error:" , error );
Add to .vscode/launch.json: {
"version" : "0.2.0" ,
"configurations" : [
{
"name" : "Debug Backend" ,
"type" : "bun" ,
"request" : "launch" ,
"program" : "${workspaceFolder}/apps/backend/src/index.ts" ,
"cwd" : "${workspaceFolder}/apps/backend"
}
]
}
Frontend Debugging
Docker Development
Start Services
Database Only
# Start all containers
docker-compose up -d
# View logs
docker-compose logs -f
# Stop containers
docker-compose down
docker run --name turbostack-db \
-e POSTGRES_USER=turbostack \
-e POSTGRES_PASSWORD=turbostack \
-e POSTGRES_DB=turbostack \
-p 5432:5432 \
-d postgres:16-alpine
Environment Variables
Development Setup
Create .env in project root:
# Database
DATABASE_URL = "postgresql://user:password@localhost:5432/turbostack"
# Security
JWT_SECRET = "your-super-secret-jwt-key-min-32-characters"
SESSION_SECRET = "another-super-secret-session-key"
# URLs
FRONTEND_URL = "http://localhost:4100"
NEXT_PUBLIC_API_URL = "http://localhost:4101"
# Optional Services
RESEND_API_KEY = "re_..."
POLAR_ACCESS_TOKEN = "polar_at_..."
Never commit .env files to version control. Always use .env.example as a
template.
Troubleshooting
# Find process using port
lsof -i :4100
# Kill the process
kill -9 < PI D >
# Regenerate Prisma Client
bun run db:generate
# Clear node_modules and reinstall
rm -rf node_modules bun.lockb
bun install
Type errors after schema change
Regenerate Prisma Client: bun run db:generate 2. Restart TypeScript
server in VS Code 3. Clear Next.js cache: rm -rf apps/frontend/.next
# Clear Turborepo cache
bun run turbo clean
# Force rebuild
bun run build --force
Best Practices
Git Workflow
Create feature branches - Write meaningful commit messages - Keep commits
atomic - Review changes before committing
Code Style
Follow ESLint rules - Use Prettier for formatting - Write JSDoc comments -
Keep functions small
Testing
Write tests for business logic - Test API endpoints - Use MSW for API
mocking - Maintain high coverage
Performance
Use Server Components - Minimize client bundles - Optimize images -
Monitor bundle size
Next Steps