# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. **IMPORTANT**: Always refer to [docs/environment.md](docs/environment.md) for detailed environment configuration, runtime modes, and known issues. Keep that document updated when making infrastructure or configuration changes. ## Project Overview Banatie is a comprehensive monorepo for AI-powered image generation platform featuring multiple applications: - **API Service** (`apps/api-service`) - Core REST API using Express.js and TypeScript for image generation with Gemini AI - **Landing Page** (`apps/landing`) - Next.js public website with demo functionality - **Studio Platform** (`apps/studio`) - Next.js SaaS application with authentication, billing, and subscriptions. Based on https://github.com/nextjs/saas-starter - **Admin Dashboard** (`apps/admin`) - Next.js administration interface for monitoring and management The project uses MinIO for object storage and PostgreSQL for data persistence, all orchestrated with Docker Compose. ## Development Commands The project has **two separate environments**: ### Development Mode (Local API + Docker Infrastructure) From `apps/api-service/`: ```bash pnpm dev # Start infrastructure + API with hot reload pnpm infra:up # Start only infrastructure (postgres, minio) pnpm infra:down # Stop infrastructure pnpm infra:logs # View infrastructure logs ``` ### Production Mode (All Services in Docker) From `prod-env/`: ```bash docker compose up -d # Start all services docker compose up -d --build # Rebuild and start docker compose down # Stop all services docker compose logs -f app # API logs docker compose logs -f landing # Landing logs ``` ### Monorepo Commands (from root) - `pnpm build` - Build all applications - `pnpm lint` - Run ESLint on all applications - `pnpm typecheck` - Run TypeScript checking on all applications - `pnpm test` - Run tests - `pnpm clean` - Clean all build outputs and dependencies ## Architecture ### Monorepo Structure ``` banatie-service/ ├── apps/ │ ├── api-service/ # Express.js REST API (TypeScript) │ │ ├── docker-compose.yml # Dev infrastructure only │ │ ├── .env # Dev config (localhost) │ │ └── Dockerfile # Production build │ ├── landing/ # Next.js landing page │ │ └── Dockerfile # Production build │ ├── studio/ # Next.js SaaS platform │ └── admin/ # Next.js admin dashboard ├── packages/ │ └── database/ # Shared database package (Drizzle ORM) ├── prod-env/ # Production environment │ ├── docker-compose.yml # All services (api, landing, infra) │ ├── .env # Prod config (Docker hostnames) │ └── README.md # Deployment instructions ├── data/ # Docker volume data (postgres, minio) ├── docs/ │ └── environment.md # Environment configuration guide ├── pnpm-workspace.yaml # Workspace configuration └── package.json # Root workspace scripts ``` ### API Service Architecture (`apps/api-service/`) - **Express App**: Configured in `src/app.ts` with middleware, CORS, and route mounting - **Server Entry**: `src/server.ts` starts the HTTP server - **Database Client**: `src/db.ts` - Drizzle ORM connection to PostgreSQL - **Authentication**: `src/services/ApiKeyService.ts` - API key management and validation - **Image Generation**: `src/services/ImageGenService.ts` - Gemini AI integration - **Storage**: `src/services/MinioStorageService.ts` - File uploads to MinIO - **Route Handling**: - `src/routes/bootstrap.ts` - Bootstrap initial master key (one-time) - `src/routes/admin/keys.ts` - API key management (master key required) - `src/routes/textToImage.ts` - Image generation endpoint (API key required) - `src/routes/upload.ts` - File upload endpoint (project key required) - `src/routes/images.ts` - Image serving endpoint (public) ### Middleware Stack (API Service) - `src/middleware/upload.ts` - Multer configuration for file uploads (max 3 reference images, 5MB each; single file upload for `/api/upload`) - `src/middleware/validation.ts` - Express-validator for request validation - `src/middleware/errorHandler.ts` - Centralized error handling and 404 responses - `src/middleware/auth/validateApiKey.ts` - API key authentication - `src/middleware/auth/requireMasterKey.ts` - Master key authorization - `src/middleware/auth/rateLimiter.ts` - Rate limiting per API key (100 req/hour) ### TypeScript Configuration (API Service) - Path aliases configured in `apps/api-service/tsconfig.json`: - `@/*` maps to `src/*` - `@/types/*` maps to `src/types/*` - `@/services/*` maps to `src/services/*` - `@/middleware/*` maps to `src/middleware/*` - `@/routes/*` maps to `src/routes/*` - `@/utils/*` maps to `src/utils/*` ### Storage & Data - **MinIO**: Object storage for generated images and uploads (port 9000) - **PostgreSQL**: Database for API keys, user data, and metadata (port 5460) - Database name: `banatie_db` - User: `banatie_user` - Tables: `api_keys`, `organizations`, `projects`, `users`, `images`, `upload_sessions` - **File Organization**: `orgId/projectId/category/year-month/filename.ext` ### Database Package (`packages/database/`) Shared Drizzle ORM package used by API service and future apps: - **Schema**: `src/schema/apiKeys.ts` - API keys table definition - **Client Factory**: `src/client.ts` - Database connection creator - **Migrations**: `migrations/` - SQL migration files - **Configuration**: `drizzle.config.ts` - Drizzle Kit configuration Key table: `api_keys` - Stores hashed API keys (SHA-256) - Two types: `master` (admin, never expires) and `project` (90-day expiration) - Soft delete via `is_active` flag - Audit trail with `createdBy`, `lastUsedAt`, `createdAt` ## Environment Configuration **CRITICAL**: See [docs/environment.md](docs/environment.md) for complete configuration details, known issues, and solutions. **Important**: We use TWO `.env` files with different purposes: ### Root `.env` (Docker Compose Infrastructure) Used by Docker Compose services (MinIO, Postgres, API container). Key differences from local: - `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db` (Docker network hostname) - `MINIO_ENDPOINT=minio:9000` (Docker network hostname) - `MINIO_ROOT_USER` and `MINIO_ROOT_PASSWORD` - MinIO admin credentials - All variables are passed to the app container via docker-compose.yml environment section ### Development `.env` (`apps/api-service/.env`) Used when running `pnpm dev` locally (connects to Docker via port forwarding): - `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db` - `MINIO_ENDPOINT=localhost:9000` - **NOTE**: This file is excluded from Docker builds ### Production `.env` (`prod-env/.env`) Used when running `docker compose` in prod-env (internal Docker hostnames): - `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db` - `MINIO_ENDPOINT=minio:9000` - `IS_DOCKER=true` environment variable is set ### Secrets (`secrets.env`) Sensitive values stored separately (NOT in git): - `GEMINI_API_KEY` - Required for image generation - `MASTER_KEY`, `API_KEY` - Optional testing keys See `secrets.env.example` in each directory for template. ### Required Environment Variables - `DATABASE_URL` - PostgreSQL connection string - `GEMINI_API_KEY` - Google Gemini API key (required) - `MINIO_ENDPOINT` - MinIO endpoint - `MINIO_ACCESS_KEY` - MinIO service account key (`banatie_service`) - `MINIO_SECRET_KEY` - MinIO service account secret (`banatie_service_key_2024`) - `MINIO_BUCKET_NAME` - Storage bucket name (default: `banatie`) - `MINIO_ROOT_USER` - MinIO admin user (`banatie_admin`) - `MINIO_ROOT_PASSWORD` - MinIO admin password - `PORT` - Server port (default: 3000) - `NODE_ENV` - Environment mode - `CORS_ORIGIN` - CORS origin setting ## Key Dependencies ### API Service - **@banatie/database** - Shared database package (workspace dependency) - **@google/genai** - Google Gemini AI client - **drizzle-orm** - TypeScript ORM (via database package) - **postgres** - PostgreSQL client for Node.js (via database package) - **express** v5 - Web framework - **multer** - File upload handling - **minio** - MinIO client for object storage - **express-validator** - Request validation - **winston** - Logging - **helmet** - Security middleware ### Database Package - **drizzle-orm** - TypeScript ORM for SQL databases - **drizzle-kit** - CLI tools for migrations - **postgres** - PostgreSQL client for Node.js ### Frontend Apps (Next.js) - **next** - React framework - **tailwindcss** - Utility-first CSS framework - **typescript** - Type safety - **supabase** - Authentication and database (studio app) - **stripe** - Payment processing (studio app) ## Service Ports | Service | Port | Description | | --------------- | ---- | ------------------ | | API Service | 3000 | REST API endpoints | | Landing Page | 3001 | Public website | | Studio Platform | 3002 | SaaS application | | Admin Dashboard | 3003 | Administration | | PostgreSQL | 5460 | Database | | MinIO API | 9000 | Object storage | | MinIO Console | 9001 | Storage management | ## API Endpoints (API Service) ### Public Endpoints (No Authentication) - `GET /health` - Health check with uptime and status - `GET /api/info` - API information and limits - `POST /api/bootstrap/initial-key` - Create first master key (one-time only) ### Admin Endpoints (Master Key Required) - `POST /api/admin/keys` - Create new API keys (master or project) - `GET /api/admin/keys` - List all API keys - `DELETE /api/admin/keys/:keyId` - Revoke an API key ### Protected Endpoints (API Key Required) - `POST /api/text-to-image` - Generate images from text only (JSON) - `POST /api/upload` - Upload single image file to project storage - `GET /api/images` - List generated images **Authentication**: All protected endpoints require `X-API-Key` header ## Authentication Setup ### First-Time Setup 1. **Start Services**: `docker compose up -d` 2. **Create Master Key**: ```bash curl -X POST http://localhost:3000/api/bootstrap/initial-key ``` Save the returned key securely! 3. **Create Project Key** (for testing): ```bash curl -X POST http://localhost:3000/api/admin/keys \ -H "X-API-Key: YOUR_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{"type": "project", "projectId": "test", "name": "Test Key"}' ``` ### Using API Keys ```bash # Image generation with project key curl -X POST http://localhost:3000/api/text-to-image \ -H "X-API-Key: YOUR_PROJECT_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "a sunset", "filename": "test_image" }' # File upload with project key curl -X POST http://localhost:3000/api/upload \ -H "X-API-Key: YOUR_PROJECT_KEY" \ -F "file=@image.png" ``` ### Key Management - **Master Keys**: Never expire, can create/revoke other keys, admin access - **Project Keys**: Expire in 90 days, for image generation only - **Rate Limits**: 100 requests per hour per key - **Revocation**: Soft delete via `is_active` flag ## Development Notes - Uses pnpm workspaces for monorepo management (required >= 8.0.0) - Node.js >= 18.0.0 required - TypeScript with strict mode enabled across all apps - ESLint configured with TypeScript and Prettier integration - Jest for testing with ts-jest preset (API service) - Each app can be developed and deployed independently - **Docker**: Uses monorepo-aware Dockerfiles in each app directory - **Environment**: Two separate configs (dev: `apps/api-service/`, prod: `prod-env/`) - **Secrets**: Stored in `secrets.env` (not tracked in git)