PlantGuard AI is structured as an npm monorepo with two primary deployable workspaces:
client/): React 19 + TypeScript + Vite Progressive Web Application (PWA).server/): Node.js 22+ Express REST API with MongoDB and Google Gemini AI.gemini-3.8-flash.server/.env)Copy server/.env.example to server/.env:
# Server Networking
PORT=3000
NODE_ENV=production
CLIENT_ORIGIN=https://plantguard.example.com
# Database Connection (MongoDB)
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/plantguard_ai?retryWrites=true&w=majority
# Authentication Secrets (generate with `openssl rand -hex 64`)
JWT_SECRET=your_production_access_token_secret_here
JWT_REFRESH_SECRET=your_production_refresh_token_secret_here
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# Google Gemini Vision AI
GEMINI_API_KEY=AIzaSy...
GEMINI_MODEL=gemini-3.8-flash
# Logging
LOG_LEVEL=info
client/.env)Copy client/.env.example to client/.env:
# Production API Base URL (leave blank if frontend is served behind reverse proxy /api route)
VITE_API_BASE_URL=https://api.plantguard.example.com
Run the unified monorepo verification pipeline from the repository root:
# 1. Install dependencies across all workspaces
npm install
# 2. Run typecheck, unit tests, and production builds
npm run check
# 3. Ensure MongoDB indexes and migrations are applied
npm --prefix server run db:indexes
npm --prefix server run db:migrate
client/dist/ on Vercel, Netlify, or Cloudflare Pages.
npm --prefix client run buildclient/dist/* -> /index.html).server/ to Render, Railway, Fly.io, or Google Cloud Run.
npm --prefix server run buildnode server/dist/server.js/api/v1/healthA complete production docker-compose.yml configuration:
version: '3.8'
services:
mongodb:
image: mongo:7.0
restart: always
volumes:
- mongo_data:/data/db
ports:
- "27017:27017"
server:
build:
context: .
dockerfile: server/Dockerfile
restart: always
environment:
- PORT=3000
- NODE_ENV=production
- MONGODB_URI=mongodb://mongodb:27017/plantguard_ai
- GEMINI_API_KEY=${GEMINI_API_KEY}
- GEMINI_MODEL=gemini-3.8-flash
- JWT_SECRET=${JWT_SECRET}
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
- CLIENT_ORIGIN=https://plantguard.example.com
depends_on:
- mongodb
ports:
- "3000:3000"
client:
build:
context: .
dockerfile: client/Dockerfile
restart: always
ports:
- "80:80"
- "443:443"
volumes:
mongo_data:
Configure container orchestrators and load balancers to use these probe endpoints:
GET /api/v1/health
{ "status": "ok" } when the Express process is responsive.GET /api/v1/health/detailed
readyState === 1 and critical subsystems are healthy.