diff --git a/README.md b/README.md new file mode 100644 index 0000000..d8a72c3 --- /dev/null +++ b/README.md @@ -0,0 +1,177 @@ +# GoodGo Platform AI + +Vietnam's intelligent real estate platform — property search, AI-powered valuation, and end-to-end transaction management. + +## Tech Stack + +| Layer | Technology | +|-------|-----------| +| **Backend** | NestJS 11, TypeScript, Prisma ORM, CQRS | +| **Frontend** | Next.js 14, React 18, Tailwind CSS, Zustand | +| **Database** | PostgreSQL 16 + PostGIS 3.4 | +| **Search** | Typesense 27 | +| **Cache/Queue** | Redis 7 | +| **AI/ML** | FastAPI, XGBoost, Claude API, Underthesea | +| **MCP** | Model Context Protocol servers (property search, valuation, analytics) | +| **Storage** | MinIO (S3-compatible) | +| **Monitoring** | Prometheus + Grafana | +| **Payments** | VNPay, MoMo, ZaloPay | + +## Architecture Overview + +``` +┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ +│ Next.js 14 │────▶│ NestJS API │────▶│ PostgreSQL + │ +│ (Web App) │ │ (REST) │ │ PostGIS │ +└─────────────┘ └──────┬───────┘ └──────────────────┘ + │ + ┌────────────┼────────────┐ + │ │ │ + ┌─────▼──┐ ┌──────▼───┐ ┌────▼─────┐ + │ Redis │ │Typesense │ │ MinIO │ + │ Cache │ │ Search │ │ Storage │ + └────────┘ └──────────┘ └──────────┘ + │ + ┌─────▼──────────────────────────┐ + │ MCP Servers │ + │ ├─ Property Search │ + │ ├─ Market Analytics │ + │ └─ Valuation │ + └─────────────┬─────────────────┘ + │ + ┌───────▼────────┐ + │ AI Services │ + │ (FastAPI) │ + │ ├─ AVM │ + │ └─ Moderation │ + └────────────────┘ +``` + +## Monorepo Structure + +``` +goodgo-platform-ai/ +├── apps/ +│ ├── api/ # NestJS backend (port 3000) +│ └── web/ # Next.js frontend (port 3001) +├── libs/ +│ ├── ai-services/ # Python FastAPI — AVM + content moderation +│ └── mcp-servers/ # MCP server implementations +├── prisma/ # Database schema & migrations +├── e2e/ # Playwright E2E tests +├── monitoring/ # Prometheus & Grafana configs +└── docs/ # Developer documentation +``` + +## Quick Start + +### Prerequisites + +- **Docker Engine 24+** & Docker Compose v2 +- **Node.js 22 LTS** +- **pnpm 10.27+** (`corepack enable && corepack prepare pnpm@latest --activate`) + +### Setup + +```bash +# 1. Clone the repository +git clone && cd goodgo-platform-ai + +# 2. Copy environment file +cp .env.example .env + +# 3. Start infrastructure services +docker compose up -d + +# 4. Verify services are healthy +docker compose ps + +# 5. Install dependencies +pnpm install + +# 6. Generate Prisma client +pnpm db:generate + +# 7. Run database migrations +pnpm db:migrate:dev + +# 8. Seed the database (optional) +pnpm db:seed + +# 9. Start all apps in dev mode +pnpm dev +``` + +The API will be available at `http://localhost:3000` and the web app at `http://localhost:3001`. + +### Infrastructure Services + +| Service | Port(s) | Dashboard | +|---------|---------|-----------| +| PostgreSQL + PostGIS | 5432 | — | +| Redis | 6379 | — | +| Typesense | 8108 | `http://localhost:8108/health` | +| MinIO | 9000 / 9001 | `http://localhost:9001` (console) | +| AI Services (FastAPI) | 8000 | `http://localhost:8000/health` | +| Prometheus | 9090 | `http://localhost:9090` | +| Grafana | 3002 | `http://localhost:3002` | + +## Development + +### Common Commands + +```bash +pnpm dev # Start all apps (API + Web) +pnpm build # Build all packages +pnpm lint # Run ESLint +pnpm typecheck # TypeScript type checking +pnpm format # Format with Prettier +pnpm test # Run unit/integration tests +``` + +### Database + +```bash +pnpm db:generate # Regenerate Prisma client +pnpm db:migrate:dev # Create and apply migrations +pnpm db:migrate:deploy # Apply migrations (CI/production) +pnpm db:seed # Seed database +pnpm db:studio # Open Prisma Studio (visual editor) +pnpm db:reset # Reset database (destructive) +``` + +### E2E Testing + +```bash +pnpm test:e2e # Run all E2E tests +pnpm test:e2e:api # API tests only +pnpm test:e2e:web # Web UI tests only +pnpm test:e2e:report # Open HTML test report +``` + +## API Modules + +| Module | Description | +|--------|-------------| +| **auth** | Registration, login, JWT + refresh token rotation, OAuth (Google/Zalo), KYC | +| **listings** | Property listing CRUD, status workflow, media management | +| **search** | Typesense full-text search with geo-spatial filters | +| **payments** | VNPay, MoMo, ZaloPay integration | +| **subscriptions** | Plan management, usage tracking | +| **notifications** | Email and in-app notifications | +| **admin** | Listing moderation, user management | +| **analytics** | Market reports, price indices, AVM integration | +| **mcp** | MCP server bridge (property search, valuation, analytics) | +| **metrics** | Prometheus metrics endpoint | + +Each module follows Domain-Driven Design with `presentation/`, `application/`, `domain/`, and `infrastructure/` layers. + +## Documentation + +- [Development Environment](docs/dev-environment.md) — Docker setup and local services +- [Architecture](docs/architecture.md) — System design, data flow, module structure +- [Deployment](docs/deployment.md) — Production deployment guide + +## License + +Proprietary — All rights reserved. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..3e8d160 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,239 @@ +# Architecture + +## System Overview + +GoodGo Platform AI is a monorepo containing a NestJS backend, Next.js frontend, Python AI services, and MCP (Model Context Protocol) servers. The system is orchestrated with Turborepo and pnpm workspaces. + +``` + ┌──────────────────────────────────────────┐ + │ Client (Browser) │ + └──────────────────┬───────────────────────┘ + │ + ┌──────────────────▼───────────────────────┐ + │ Next.js 14 (apps/web) │ + │ ┌─────────┐ ┌──────────┐ ┌───────┐ │ + │ │ Pages │ │Components│ │Zustand │ │ + │ │(App │ │(UI + │ │(State) │ │ + │ │ Router) │ │ Domain) │ │ │ │ + │ └─────────┘ └──────────┘ └───────┘ │ + └──────────────────┬───────────────────────┘ + │ REST API + ┌──────────────────▼───────────────────────┐ + │ NestJS 11 (apps/api) │ + │ │ + │ ┌────────┐ ┌────────┐ ┌─────────────┐ │ + │ │ Auth │ │Listings│ │ Payments │ │ + │ ├────────┤ ├────────┤ ├─────────────┤ │ + │ │ Search │ │ Admin │ │Subscriptions│ │ + │ ├────────┤ ├────────┤ ├─────────────┤ │ + │ │Analytics│ │ MCP │ │Notifications│ │ + │ └────────┘ └────────┘ └─────────────┘ │ + └───┬─────┬──────┬─────────┬──────────────┘ + │ │ │ │ + ┌────────────▼┐ ┌─▼────┐ ▼ ┌───▼──────────┐ + │ PostgreSQL │ │Redis │ │ │ Typesense │ + │ + PostGIS │ │ │ │ │ (Search) │ + └─────────────┘ └──────┘ │ └──────────────┘ + │ + ┌───────────────▼──────────────────────┐ + │ MCP Servers (libs/mcp-servers) │ + │ ┌──────────┐┌──────────┐┌────────┐ │ + │ │ Property ││ Market ││Valua- │ │ + │ │ Search ││Analytics ││tion │ │ + │ └──────────┘└──────────┘└───┬────┘ │ + └──────────────────────────────┼───────┘ + │ + ┌──────────────────────────────▼───────┐ + │ AI Services (libs/ai-services) │ + │ FastAPI + XGBoost + Claude API │ + │ ┌──────────┐ ┌────────────────┐ │ + │ │ AVM │ │ Moderation │ │ + │ │(Pricing) │ │ (Claude API) │ │ + │ └──────────┘ └────────────────┘ │ + └──────────────────────────────────────┘ +``` + +## Module Architecture + +Each API module follows a layered Domain-Driven Design structure: + +``` +modules/{module-name}/ +├── presentation/ # HTTP layer +│ ├── controllers/ # Route handlers +│ └── dtos/ # Request/response DTOs (class-validator) +├── application/ # Business orchestration +│ ├── commands/ # Write operations (CQRS) +│ ├── queries/ # Read operations (CQRS) +│ ├── handlers/ # Command/query handlers +│ └── services/ # Application services +├── domain/ # Core business logic +│ ├── entities/ # Domain entities & value objects +│ ├── repositories/ # Repository interfaces (abstractions) +│ └── events/ # Domain events +├── infrastructure/ # External integrations +│ ├── repositories/ # Prisma repository implementations +│ └── services/ # External service adapters +└── {module-name}.module.ts # NestJS module definition +``` + +### CQRS Pattern + +The platform uses NestJS CQRS (`@nestjs/cqrs`) for complex operations: + +- **Commands** — mutate state (create listing, process payment, register user) +- **Queries** — read state (search properties, get analytics) +- **Events** — cross-module communication (listing published → index in Typesense, payment completed → send notification) + +### Shared Module + +The `shared/` module provides cross-cutting concerns: + +- **Prisma service** — database connection and client +- **Redis service** — caching and session management +- **Guards** — JWT auth guard, roles guard, throttle guard +- **Pipes** — global validation pipe (whitelist mode) +- **Filters** — exception filters for consistent error responses +- **Decorators** — `@CurrentUser()`, `@Roles()`, `@Public()` + +## Data Flow + +### Property Listing Lifecycle + +``` +DRAFT → PENDING_REVIEW → ACTIVE → RESERVED → SOLD/RENTED + │ │ + ▼ │ + REJECTED EXPIRED +``` + +1. **Seller/Agent** creates listing (status: `DRAFT`) +2. **Seller** submits for review → `PENDING_REVIEW` +3. **Admin** moderates (AI moderation score assists) → `ACTIVE` or `REJECTED` +4. Active listings are indexed in Typesense for search +5. **Buyer** makes inquiry → `Inquiry` record created +6. Transaction workflow: `OFFER_MADE → DEPOSIT_PAID → CONTRACT_SIGNING → COMPLETED` + +### Search Flow + +``` +User Query → NestJS Search Module → Typesense + │ + ├─ Full-text on title/description + ├─ Faceted filters (price, type, bedrooms) + └─ Geo-spatial (lat/long + radius) +``` + +### Payment Flow + +``` +User → API (create payment) → Provider (VNPay/MoMo/ZaloPay) + │ + [User pays on provider page] + │ +Provider callback → API → Verify signature → Update Payment status + │ + SUCCESS / FAILED +``` + +### AI Valuation Flow + +``` +API Request → MCP Valuation Server → AI Service (FastAPI) + │ + XGBoost Model + │ + ┌─────▼──────┐ + │ Estimated │ + │ Price + │ + │ Confidence │ + │ + Factors │ + └─────────────┘ +``` + +## Database Schema + +### Core Models + +``` +User ──┬── Agent (1:1, for AGENT role users) + ├── OAuthAccount (1:N, Google/Zalo) + ├── RefreshToken (1:N, token families) + ├── Subscription (1:N) + ├── SavedSearch (1:N) + └── UsageRecord (1:N) + +Property ──┬── PropertyMedia (1:N, images/videos) + ├── Listing (1:N) + └── Valuation (1:N) + +Listing ──┬── Inquiry (1:N) + ├── Lead (1:N) + ├── Transaction (1:N) + └── Agent (N:1) + +Transaction ── Payment (1:N) + +Plan ── Subscription (1:N) + +MarketIndex (standalone — city/district/month aggregates) +``` + +### Key Design Decisions + +- **PostGIS** for spatial queries — property locations stored as `Point` geometry +- **JSON columns** for flexible data: amenities, nearby POIs, KYC data, subscription features +- **Token family tracking** for secure refresh token rotation (detects reuse attacks) +- **Soft statuses** over soft deletes — listings use status workflow, not `deletedAt` + +## MCP Servers + +Three Model Context Protocol servers provide AI tool interfaces: + +| Server | Tools | Data Source | +|--------|-------|-------------| +| **Property Search** | `search_properties`, `compare_properties`, `get_property_details` | Typesense | +| **Market Analytics** | `get_market_report`, `analyze_trends`, `get_price_indices` | PostgreSQL | +| **Valuation** | `estimate_valuation`, `extract_features`, `compare_valuations` | AI Services (FastAPI) | + +MCP servers are registered via `McpModule` in NestJS, managed by `McpRegistryService`, and exposed through `McpTransportController` over HTTP. + +## AI Services + +Python FastAPI microservice (`libs/ai-services/`) provides: + +| Endpoint | Model | Purpose | +|----------|-------|---------| +| `POST /avm/estimate` | XGBoost | Property price estimation with confidence score | +| `POST /moderation/check` | Claude API | Content moderation for listing descriptions | +| `GET /health` | — | Health check | + +- **Underthesea** handles Vietnamese text tokenization and NLP preprocessing +- XGBoost model uses engineered features (area, location, property type, amenities) + +## Security + +- **JWT + Refresh Token Rotation** — 15-minute access tokens, 7-day refresh tokens with family-based rotation +- **OAuth** — Google and Zalo social login +- **Rate Limiting** — 60 req/60s default, 10 req/60s for auth endpoints +- **Helmet** — HTTP security headers +- **CORS** — Configurable origins via `CORS_ORIGINS` +- **Input Validation** — class-validator (backend), Zod (frontend) +- **Content Sanitization** — sanitize-html for user-generated content +- **KYC** — Agent verification workflow (NONE → PENDING → VERIFIED/REJECTED) + +## Monitoring + +- **Prometheus** scrapes `/metrics` endpoint every 15 seconds +- **Grafana** dashboards auto-provisioned from `monitoring/grafana/dashboards/` +- **Pino** structured JSON logging with configurable log levels +- Metrics include HTTP request duration, error rates, and custom business metrics + +## Event System + +The platform uses `@nestjs/event-emitter` for loose coupling between modules: + +- `listing.published` → Typesense indexer updates search index +- `payment.completed` → Notification service sends confirmation +- `inquiry.created` → Agent notification triggered +- `user.registered` → Welcome email sent diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..f439d83 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,226 @@ +# Deployment Guide + +## Overview + +GoodGo Platform AI consists of four deployable services: + +| Service | Technology | Default Port | +|---------|-----------|-------------| +| **API** | NestJS (Node.js) | 3000 | +| **Web** | Next.js | 3001 | +| **AI Services** | FastAPI (Python) | 8000 | +| **Infrastructure** | Docker Compose | Various | + +## Prerequisites + +- Docker Engine 24+ & Docker Compose v2 +- Node.js 22 LTS +- pnpm 10.27+ +- Python 3.12 (for AI services, if running outside Docker) + +## Environment Configuration + +Copy `.env.example` to `.env` and configure all required values: + +```bash +cp .env.example .env +``` + +### Required Variables + +| Variable | Description | Example | +|----------|-------------|---------| +| `DATABASE_URL` | PostgreSQL connection string | `postgresql://user:pass@host:5432/goodgo` | +| `JWT_SECRET` | JWT signing key (min 32 chars) | Generate with `openssl rand -hex 32` | +| `JWT_REFRESH_SECRET` | Refresh token signing key | Generate with `openssl rand -hex 32` | +| `REDIS_URL` | Redis connection string | `redis://localhost:6379` | +| `TYPESENSE_API_KEY` | Typesense admin API key | Generate a secure random key | + +### Optional Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `API_PORT` | API server port | `3000` | +| `WEB_PORT` | Web app port | `3001` | +| `NODE_ENV` | Environment mode | `development` | +| `CORS_ORIGINS` | Allowed CORS origins | — | +| `CLAUDE_API_KEY` | Claude API key (for content moderation) | — | +| `NEXT_PUBLIC_MAPBOX_TOKEN` | Mapbox token (for maps) | — | +| `VNPAY_*`, `MOMO_*`, `ZALOPAY_*` | Payment gateway credentials | — | + +## Infrastructure Setup (Docker Compose) + +Start all infrastructure services: + +```bash +docker compose up -d +``` + +This starts: + +- **PostgreSQL 16 + PostGIS 3.4** (port 5432) +- **Redis 7** (port 6379) +- **Typesense 27** (port 8108) +- **MinIO** (API: 9000, Console: 9001) +- **AI Services** (port 8000) +- **Prometheus** (port 9090) +- **Grafana** (port 3002) + +Verify all services are healthy: + +```bash +docker compose ps +``` + +All services include health checks. Wait until all show `healthy` status. + +## Database Setup + +```bash +# Generate Prisma client +pnpm db:generate + +# Apply migrations +pnpm db:migrate:deploy + +# Seed initial data (optional) +pnpm db:seed +``` + +## Building for Production + +### API (NestJS) + +```bash +cd apps/api +pnpm build +``` + +Output: `apps/api/dist/` + +Run in production: + +```bash +NODE_ENV=production node apps/api/dist/main.js +``` + +### Web (Next.js) + +```bash +cd apps/web +pnpm build +``` + +Output: `apps/web/.next/` + +Run in production: + +```bash +NODE_ENV=production pnpm --filter web start +``` + +### AI Services (FastAPI) + +The AI service runs in Docker via `docker compose`. To build separately: + +```bash +cd libs/ai-services +docker build -t goodgo-ai-services . +docker run -p 8000:8000 --env-file ../../.env goodgo-ai-services +``` + +## Production Checklist + +### Security + +- [ ] Set strong, unique `JWT_SECRET` and `JWT_REFRESH_SECRET` (min 32 characters) +- [ ] Set `NODE_ENV=production` +- [ ] Configure `CORS_ORIGINS` to only allow your domain(s) +- [ ] Change default database passwords +- [ ] Change default MinIO credentials (`MINIO_USER`, `MINIO_PASSWORD`) +- [ ] Change default Grafana credentials (`GRAFANA_ADMIN_USER`, `GRAFANA_ADMIN_PASSWORD`) +- [ ] Use a strong, unique `TYPESENSE_API_KEY` +- [ ] Enable SSL/TLS termination (reverse proxy) +- [ ] Set `MINIO_USE_SSL=true` if MinIO is exposed publicly + +### Database + +- [ ] Run `pnpm db:migrate:deploy` (not `db:migrate:dev`) +- [ ] Enable PostgreSQL connection pooling (PgBouncer recommended) +- [ ] Configure automated backups +- [ ] Set appropriate `max_connections` in PostgreSQL config + +### Monitoring + +- [ ] Verify Prometheus is scraping `/metrics` endpoint +- [ ] Import Grafana dashboards from `monitoring/grafana/dashboards/` +- [ ] Set up alerting rules for error rates and latency + +### Performance + +- [ ] Configure Redis `maxmemory` and eviction policy +- [ ] Set appropriate Typesense `--memory-limit` +- [ ] Enable gzip/brotli compression in reverse proxy +- [ ] Configure CDN for static assets (Next.js `/_next/static/`) + +## Health Checks + +| Service | Endpoint | Expected Response | +|---------|----------|-------------------| +| API | `GET /metrics` | Prometheus metrics | +| AI Services | `GET /health` | `{"status": "ok"}` | +| Typesense | `GET /health` | `{"ok": true}` | +| Redis | `redis-cli ping` | `PONG` | +| PostgreSQL | `pg_isready -h host -p 5432` | Exit code 0 | + +## Scaling Considerations + +### Horizontal Scaling + +- **API**: Stateless — scale with multiple instances behind a load balancer +- **Web**: Stateless — scale with multiple instances or deploy to Vercel/Cloudflare +- **AI Services**: CPU-bound — scale based on valuation request volume +- **Redis**: Use Redis Cluster for high availability +- **PostgreSQL**: Read replicas for query-heavy workloads + +### Recommended Architecture (Production) + +``` + ┌─────────────┐ + │ Load Balancer│ + │ (nginx/ALB) │ + └──────┬──────┘ + │ + ┌────────────┼────────────┐ + │ │ │ + ┌─────▼──┐ ┌─────▼──┐ ┌─────▼──┐ + │ API #1 │ │ API #2 │ │ API #N │ + └────────┘ └────────┘ └────────┘ + │ │ │ + └────────────┼────────────┘ + │ + ┌────────────┼────────────┐ + │ │ │ + ┌─────▼──┐ ┌─────▼──┐ ┌─────▼─────┐ + │ PG │ │ Redis │ │ Typesense │ + │Primary │ │Cluster │ │ Cluster │ + │+ Replica│ │ │ │ │ + └────────┘ └────────┘ └────────────┘ +``` + +## Rollback + +### Application Rollback + +Deploy the previous container image or build artifact. The API and Web are stateless — no rollback-specific steps needed. + +### Database Rollback + +Prisma does not support automatic down migrations. If a migration must be reverted: + +1. Identify the migration in `prisma/migrations/` +2. Write a manual SQL rollback script +3. Apply via `psql` or a migration tool +4. Update `_prisma_migrations` table + +Always test migrations against a staging database before production deployment. diff --git a/docs/dev-environment.md b/docs/dev-environment.md index 3b0bcdf..2848cca 100644 --- a/docs/dev-environment.md +++ b/docs/dev-environment.md @@ -2,8 +2,9 @@ ## Prerequisites -- Docker Engine 24+ & Docker Compose v2 -- Node.js 22 LTS (for running app services locally) +- **Docker Engine 24+** & Docker Compose v2 +- **Node.js 22 LTS** +- **pnpm 10.27+** — install via `corepack enable && corepack prepare pnpm@latest --activate` ## Quick Start @@ -16,19 +17,41 @@ docker compose up -d # 3. Verify all services are healthy docker compose ps + +# 4. Install dependencies +pnpm install + +# 5. Generate Prisma client +pnpm db:generate + +# 6. Run database migrations +pnpm db:migrate:dev + +# 7. Seed the database (optional) +pnpm db:seed + +# 8. Start API and Web in dev mode +pnpm dev ``` -## Services +API runs at `http://localhost:3000`, Web at `http://localhost:3001`. -| Service | Port(s) | Description | Dashboard/UI | -| ---------- | ----------- | ---------------------------- | ------------------------------- | -| PostgreSQL | 5432 | Database with PostGIS | — | -| Redis | 6379 | Cache, sessions, queue | — | -| Typesense | 8108 | Full-text search engine | http://localhost:8108/health | -| MinIO | 9000 / 9001 | S3-compatible object storage | http://localhost:9001 (console) | +## Infrastructure Services + +| Service | Port(s) | Description | Dashboard/UI | +|---------|---------|-------------|--------------| +| PostgreSQL + PostGIS | 5432 | Database with spatial queries | — | +| Redis | 6379 | Cache, sessions, queue | — | +| Typesense | 8108 | Full-text search engine | `http://localhost:8108/health` | +| MinIO | 9000 / 9001 | S3-compatible object storage | `http://localhost:9001` (console) | +| AI Services | 8000 | FastAPI — AVM + moderation | `http://localhost:8000/health` | +| Prometheus | 9090 | Metrics collection | `http://localhost:9090` | +| Grafana | 3002 | Dashboards & monitoring | `http://localhost:3002` | ## Common Commands +### Docker Compose + ```bash # Start services docker compose up -d @@ -50,6 +73,36 @@ docker compose restart redis docker compose ps ``` +### Development + +```bash +pnpm dev # Start all apps in watch mode +pnpm build # Build all packages +pnpm lint # ESLint across monorepo +pnpm typecheck # TypeScript type checking +pnpm format # Prettier formatting +pnpm test # Run unit/integration tests +``` + +### Database + +```bash +pnpm db:generate # Regenerate Prisma client +pnpm db:migrate:dev # Create and apply migrations +pnpm db:seed # Seed database +pnpm db:studio # Open Prisma Studio (visual editor) +pnpm db:reset # Reset database (destructive) +``` + +### E2E Testing + +```bash +pnpm test:e2e # Run all E2E tests +pnpm test:e2e:api # API tests only +pnpm test:e2e:web # Web UI tests only +pnpm test:e2e:report # Open HTML test report +``` + ## Connecting to Services ### PostgreSQL @@ -76,11 +129,25 @@ curl http://localhost:8108/health ### MinIO -- API: `http://localhost:9000` -- Console: `http://localhost:9001` (login: minioadmin / minioadmin_secret) +- **API**: `http://localhost:9000` +- **Console**: `http://localhost:9001` (login: `minioadmin` / `minioadmin_secret`) + +### AI Services + +```bash +curl http://localhost:8000/health +``` + +### Grafana + +- **URL**: `http://localhost:3002` +- **Login**: `admin` / `admin` (default, configurable via `.env`) ## Troubleshooting -- **Port conflict**: Change ports in `.env` (e.g., `DB_PORT=5433`) -- **Permission issues**: Run `docker compose down -v` and restart -- **PostGIS not available**: Ensure using `postgis/postgis:16-3.4` image +- **Port conflict** — Change ports in `.env` (e.g., `DB_PORT=5433`) +- **Permission issues** — Run `docker compose down -v` and restart +- **PostGIS not available** — Ensure using `postgis/postgis:16-3.4` image +- **Prisma client out of date** — Run `pnpm db:generate` after pulling schema changes +- **AI service not starting** — Check `docker compose logs ai-services` for Python dependency errors +- **Typesense unhealthy** — Verify `TYPESENSE_API_KEY` matches in `.env` and Docker config