Skip to main content

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.
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

Web Application (apps/web)

The Next.js frontend for admin dashboard and customer interface.
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

Shared Packages

Database Package (packages/db)

Drizzle ORM schema definitions and database utilities.
{
  "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.
{
  "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.
{
  "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 both API and Web in parallel
bun run dev
Turborepo runs both apps/api:dev and apps/web:dev concurrently.

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

1

Create package directory

mkdir -p packages/my-package/src
cd packages/my-package
2

Create package.json

{
  "name": "@restai/my-package",
  "version": "0.0.1",
  "private": true,
  "type": "module",
  "exports": {
    ".": "./src/index.ts"
  },
  "devDependencies": {
    "typescript": "^5.8.0"
  }
}
3

Create entry file

// src/index.ts
export const myFunction = () => {
  return "Hello from my-package";
};
4

Use in other packages

// In apps/api/package.json
{
  "dependencies": {
    "@restai/my-package": "workspace:*"
  }
}

Best Practices

  1. Version Consistency: Use workspace:* for internal dependencies
  2. Type Exports: Always export types from packages for consumer use
  3. Barrel Exports: Use index.ts to re-export from subdirectories
  4. Peer Dependencies: Mark framework packages (React, Next.js) as peers in shared packages
  5. 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.

Build docs developers (and LLMs) love