Overview
RestAI uses Turborepo with Bun workspaces to manage a monorepo containing multiple applications and shared packages. This architecture enables code reuse, consistent tooling, and efficient builds across the entire codebase.
Directory Structure
restai/
├── apps/
│ ├── api/ # Backend API server
│ │ ├── src/
│ │ │ ├── routes/ # API route handlers
│ │ │ ├── middleware/ # Auth, CORS, logging
│ │ │ ├── services/ # Business logic
│ │ │ ├── ws/ # WebSocket handlers
│ │ │ ├── lib/ # Utilities (JWT, Redis, etc.)
│ │ │ ├── app.ts # Hono app setup
│ │ │ └── index.ts # Entry point
│ │ └── package.json
│ │
│ └── web/ # Next.js frontend
│ ├── app/ # App Router pages
│ ├── components/ # React components
│ ├── lib/ # Client utilities
│ ├── hooks/ # Custom React hooks
│ └── package.json
│
├── packages/
│ ├── db/ # Database layer
│ │ ├── src/
│ │ │ ├── schema/ # Drizzle schema definitions
│ │ │ ├── index.ts # DB connection
│ │ │ └── seed.ts # Sample data
│ │ ├── drizzle.config.ts # Drizzle Kit config
│ │ └── package.json
│ │
│ ├── ui/ # Shared UI components
│ │ ├── src/
│ │ │ └── components/ # shadcn/ui components
│ │ └── package.json
│ │
│ ├── validators/ # Shared Zod schemas
│ │ ├── src/
│ │ │ └── index.ts # Validation schemas
│ │ └── package.json
│ │
│ ├── types/ # Shared TypeScript types
│ │ ├── src/
│ │ │ └── index.ts # Type definitions
│ │ └── package.json
│ │
│ └── config/ # Shared configuration
│ ├── src/
│ │ └── index.ts # Constants, env vars
│ └── package.json
│
├── package.json # Root package.json
├── turbo.json # Turborepo configuration
├── bun.lockb # Bun lockfile
└── docker-compose.yml # Redis container
Workspace Configuration
Root package.json
{
"name" : "restai" ,
"private" : true ,
"workspaces" : [
"apps/*" ,
"packages/*"
],
"scripts" : {
"dev" : "turbo dev" ,
"build" : "turbo build" ,
"lint" : "turbo lint" ,
"clean" : "turbo clean" ,
"db:generate" : "bun run --filter @restai/db generate" ,
"db:migrate" : "bun run --filter @restai/db migrate" ,
"db:push" : "bun run --filter @restai/db push" ,
"db:seed" : "bun run --filter @restai/db seed" ,
"db:studio" : "bun run --filter @restai/db studio"
},
"devDependencies" : {
"turbo" : "^2.5.0" ,
"typescript" : "^5.8.0"
},
"packageManager" : "[email protected] "
}
The ^build dependency ensures packages are built before apps that depend on them.
Applications
API Server (apps/api)
The backend API built with Hono and Bun.
Overview
package.json
Dependencies
Key Features:
RESTful API endpoints
WebSocket server for real-time updates
JWT authentication
File upload handling (R2)
Redis integration for caching and pub/sub
Port: 3001{
"name" : "@restai/api" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"scripts" : {
"dev" : "bun run --watch src/index.ts" ,
"build" : "bun build src/index.ts --outdir dist --target bun" ,
"start" : "bun run dist/index.js" ,
"clean" : "rm -rf dist"
},
"dependencies" : {
"@aws-sdk/client-s3" : "^3.700.0" ,
"@hono/zod-validator" : "^0.5.0" ,
"@node-rs/argon2" : "^2.0.2" ,
"@restai/config" : "workspace:*" ,
"@restai/db" : "workspace:*" ,
"@restai/types" : "workspace:*" ,
"@restai/validators" : "workspace:*" ,
"drizzle-orm" : "^0.44.0" ,
"hono" : "^4.7.0" ,
"ioredis" : "^5.6.0" ,
"pino" : "^9.6.0" ,
"zod" : "^3.24.0"
}
}
Workspace Dependencies:
@restai/config - Shared configuration
@restai/db - Database schema and queries
@restai/types - TypeScript types
@restai/validators - Zod validation schemas
External Dependencies:
hono - Web framework
drizzle-orm - Database ORM
ioredis - Redis client
@node-rs/argon2 - Password hashing
@aws-sdk/client-s3 - S3 (R2) uploads
Web Application (apps/web)
The Next.js frontend for admin dashboard and customer interface.
Overview
package.json
Dependencies
Key Features:
Admin dashboard (POS, orders, menu management)
Customer QR code flow
Real-time WebSocket integration
Form validation with React Hook Form + Zod
TanStack Query for server state
Port: 3000{
"name" : "@restai/web" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"scripts" : {
"dev" : "next dev --port 3000" ,
"build" : "next build" ,
"start" : "next start" ,
"clean" : "rm -rf .next"
},
"dependencies" : {
"@hookform/resolvers" : "^5.0.0" ,
"@restai/config" : "workspace:*" ,
"@restai/types" : "workspace:*" ,
"@restai/ui" : "workspace:*" ,
"@restai/validators" : "workspace:*" ,
"@tanstack/react-query" : "^5.69.0" ,
"next" : "^16.1.6" ,
"react" : "^19.2.4" ,
"react-hook-form" : "^7.55.0" ,
"zustand" : "^5.0.0"
}
}
Workspace Dependencies:
@restai/config - Shared configuration
@restai/types - TypeScript types
@restai/ui - Shared UI components
@restai/validators - Form validation schemas
External Dependencies:
next - React framework
@tanstack/react-query - Server state management
react-hook-form - Form handling
zustand - Client state management
Shared Packages
Database Package (packages/db)
Drizzle ORM schema definitions and database utilities.
package.json
Usage Example
{
"name" : "@restai/db" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"exports" : {
"." : "./src/index.ts" ,
"./schema" : "./src/schema/index.ts"
},
"scripts" : {
"generate" : "drizzle-kit generate" ,
"migrate" : "drizzle-kit migrate" ,
"push" : "drizzle-kit push" ,
"studio" : "drizzle-kit studio" ,
"seed" : "bun run src/seed.ts"
},
"dependencies" : {
"@node-rs/argon2" : "^2.0.2" ,
"drizzle-orm" : "^0.44.0" ,
"drizzle-zod" : "^0.7.0" ,
"postgres" : "^3.4.5" ,
"zod" : "^3.24.0"
}
}
UI Package (packages/ui)
Shared React components built with shadcn/ui and Radix UI.
package.json
Usage Example
{
"name" : "@restai/ui" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"exports" : {
"." : "./src/index.ts" ,
"./components/*" : "./src/components/*.tsx"
},
"dependencies" : {
"@radix-ui/react-dialog" : "^1.1.15" ,
"@radix-ui/react-select" : "^2.2.6" ,
"@radix-ui/react-tabs" : "^1.1.13" ,
"class-variance-authority" : "^0.7.1" ,
"lucide-react" : "^0.475.0" ,
"tailwind-merge" : "^3.0.0"
},
"peerDependencies" : {
"react" : "^19.0.0" ,
"react-dom" : "^19.0.0"
}
}
Validators Package (packages/validators)
Shared Zod validation schemas for forms and API requests.
package.json
Usage Example
{
"name" : "@restai/validators" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"exports" : {
"." : "./src/index.ts"
},
"dependencies" : {
"zod" : "^3.24.0"
}
}
Types Package (packages/types)
Shared TypeScript type definitions.
// Common types shared across frontend and backend
export type UserRole =
| "super_admin"
| "org_admin"
| "branch_manager"
| "cashier"
| "waiter"
| "kitchen" ;
export type OrderStatus =
| "pending"
| "confirmed"
| "preparing"
| "ready"
| "served"
| "completed"
| "cancelled" ;
Config Package (packages/config)
Shared configuration and constants.
export const APP_NAME = "RestAI" ;
export const DEFAULT_TIMEZONE = "America/Lima" ;
export const DEFAULT_CURRENCY = "PEN" ;
export const DEFAULT_TAX_RATE = 1800 ; // 18.00%
Build Pipeline
Task Dependencies
Turborepo automatically handles the build order:
1. Shared packages build first:
@restai/types → @restai/validators → @restai/config → @restai/db → @restai/ui
2. Applications build after their dependencies:
@restai/api (depends on: db, types, validators, config)
@restai/web (depends on: ui, types, validators, config)
Development Workflow
Start All Apps
Start Single App
Build for Production
# Start both API and Web in parallel
bun run dev
Turborepo runs both apps/api:dev and apps/web:dev concurrently. # Start only the API
bun run --filter @restai/api dev
# Start only the Web app
bun run --filter @restai/web dev
# Build all packages and apps
bun run build
# Build outputs:
# - apps/api/dist/
# - apps/web/.next/
Workspace Benefits
Code Reuse
Shared validation logic between frontend and backend
Consistent UI components across all pages
Single source of truth for types
Type Safety
Database schema changes automatically propagate
API request/response types shared with frontend
Catch breaking changes at build time
Developer Experience
Hot module replacement across all packages
Instant feedback on type errors
Single command to start entire stack
Build Optimization
Turborepo caches build outputs
Only rebuilds changed packages
Parallel execution of independent tasks
Adding a New Package
Create package directory
mkdir -p packages/my-package/src
cd packages/my-package
Create package.json
{
"name" : "@restai/my-package" ,
"version" : "0.0.1" ,
"private" : true ,
"type" : "module" ,
"exports" : {
"." : "./src/index.ts"
},
"devDependencies" : {
"typescript" : "^5.8.0"
}
}
Create entry file
// src/index.ts
export const myFunction = () => {
return "Hello from my-package" ;
};
Use in other packages
// In apps/api/package.json
{
"dependencies" : {
"@restai/my-package" : "workspace:*"
}
}
Best Practices
Version Consistency: Use workspace:* for internal dependencies
Type Exports: Always export types from packages for consumer use
Barrel Exports: Use index.ts to re-export from subdirectories
Peer Dependencies: Mark framework packages (React, Next.js) as peers in shared packages
Build Outputs: Configure .gitignore to exclude dist/, .next/, etc.
When adding external dependencies, install them at the package level (not root) unless they’re truly global dev tools.