feat: add initial project configuration and smoke tests
- Created pnpm workspace configuration to manage packages. - Added a placeholder .gitkeep file in the scripts directory. - Implemented a smoke test script to validate core API and web endpoints. - Established TypeScript base configuration for consistent compilation settings. - Introduced Turbo configuration for task management and build processes.
This commit is contained in:
338
README.md
Normal file
338
README.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# Davinci Platform
|
||||
|
||||
Unified monorepo for the Davinci platform — replaces `davinci-mothership` and `davinci-community-server` as a single codebase with a `DAVINCI_MODE` flag.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Docker Desktop** (includes Docker Compose v2)
|
||||
- **Node.js** 22+ (see `.nvmrc`)
|
||||
- **pnpm** 10+ (`corepack enable && corepack prepare pnpm@10.32.0 --activate`)
|
||||
- **make** (preinstalled on macOS/Linux)
|
||||
|
||||
> Two development modes are supported:
|
||||
> 1. **Docker (recommended)** — everything runs in containers. Zero local setup beyond Docker + Node.js.
|
||||
> 2. **Local + Docker infra** — run the NestJS API and Next.js frontend natively for faster iteration, Docker for Postgres only. See [Local Development](#local-development-without-docker-for-the-app).
|
||||
|
||||
## Quick Start (Docker — Recommended)
|
||||
|
||||
```bash
|
||||
# 1. Install local deps (for Prisma CLI, tests, IDE support)
|
||||
pnpm install
|
||||
|
||||
# 2. Copy environment config
|
||||
cp .env.example .env
|
||||
|
||||
# 3. Start the full dev environment (Postgres + API + Web)
|
||||
make dev-build
|
||||
|
||||
# 4. Run migrations
|
||||
make db:push
|
||||
|
||||
# 5. Seed the dev database with test data
|
||||
make dev-seed
|
||||
|
||||
# 6. Verify everything works
|
||||
make smoke
|
||||
```
|
||||
|
||||
**That's it.** You now have:
|
||||
|
||||
| Service | URL |
|
||||
|---------|-----|
|
||||
| API | http://localhost:4300/health |
|
||||
| API Docs (Scalar) | http://localhost:4300/api-reference |
|
||||
| Web | http://localhost:4000 |
|
||||
| Postgres | localhost:55434 |
|
||||
|
||||
### Useful Commands
|
||||
|
||||
```bash
|
||||
make help # Show all available commands
|
||||
make dev-logs # Tail API container logs
|
||||
make dev-stop # Stop containers (data preserved)
|
||||
make dev-reset # Destroy + rebuild from scratch
|
||||
make dev-seed # Re-seed database
|
||||
```
|
||||
|
||||
## Local Development (Without Docker for the App)
|
||||
|
||||
If you prefer running the NestJS API and Next.js frontend natively (for faster restarts, debugger attach, HMR, etc.) while still using Docker for infrastructure:
|
||||
|
||||
### 1. Start Infrastructure Only
|
||||
|
||||
```bash
|
||||
# Start only Postgres (no app containers)
|
||||
docker compose up db -d --wait
|
||||
```
|
||||
|
||||
### 2. Set Up Environment
|
||||
|
||||
Create a `.env` file (git-ignored) in the repo root:
|
||||
|
||||
```bash
|
||||
# .env
|
||||
DATABASE_URL="postgresql://davinci:davinci@localhost:55434/davinci_platform_dev"
|
||||
PORT=3001
|
||||
NODE_ENV=development
|
||||
DAVINCI_MODE=mothership
|
||||
ENABLE_API_DOCS=true
|
||||
```
|
||||
|
||||
### 3. Generate Prisma Client & Push Schema
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgresql://davinci:davinci@localhost:55434/davinci_platform_dev \
|
||||
pnpm --filter @davinci/api prisma:generate
|
||||
|
||||
DATABASE_URL=postgresql://davinci:davinci@localhost:55434/davinci_platform_dev \
|
||||
pnpm --filter @davinci/api exec prisma db push
|
||||
```
|
||||
|
||||
### 4. Start the Apps
|
||||
|
||||
```bash
|
||||
# Terminal 1: Start API (watch mode — auto-restarts on file changes)
|
||||
pnpm --filter @davinci/api start:dev
|
||||
|
||||
# Terminal 2: Start Web (Next.js dev server with HMR)
|
||||
pnpm --filter @davinci/web dev
|
||||
```
|
||||
|
||||
The API listens on `http://localhost:3001`, Web on `http://localhost:3000`.
|
||||
|
||||
### 5. Seed Data (Optional)
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgresql://davinci:davinci@localhost:55434/davinci_platform_dev \
|
||||
pnpm --filter @davinci/api exec prisma db seed
|
||||
```
|
||||
|
||||
### VS Code Debugger
|
||||
|
||||
With `start:dev --debug`, attach VS Code's debugger:
|
||||
|
||||
```jsonc
|
||||
// .vscode/launch.json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to Davinci API",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"restart": true,
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Davinci Platform Monorepo │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌────────┐ │
|
||||
│ │ packages/api │ │ packages/web │ │ shared │ │
|
||||
│ │ NestJS 11 │ │ Next.js 15.5 │ │ types │ │
|
||||
│ │ Fastify 5 │ │ App Router │ │ consts │ │
|
||||
│ │ Prisma 7 │ │ Tailwind v4 │ │ │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └────────┘ │
|
||||
│ │ │ │
|
||||
│ /api/v1/* /* (frontend) │
|
||||
│ │ │ │
|
||||
│ ┌──────┴──────────────────┴──────┐ │
|
||||
│ │ PostgreSQL │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Key design decisions:**
|
||||
|
||||
- **DAVINCI_MODE** — single codebase operates as either `mothership` (control plane) or `community` (per-tenant) via env flag
|
||||
- **NestJS + Fastify** — high-throughput backend with URI-based API versioning (`/api/v1/...`)
|
||||
- **Prisma 7** — type-safe ORM with `@prisma/adapter-pg` driver
|
||||
- **Next.js 15.5** — App Router with `next-intl` for i18n, Tailwind CSS v4, `shadcn/ui`
|
||||
- **Turborepo** — monorepo build orchestration with caching
|
||||
- **Docker multi-stage** — production image includes nginx reverse proxy on port 80
|
||||
|
||||
### API Versioning
|
||||
|
||||
All business endpoints are served under `/api/v1/...`. Operational endpoints are unversioned:
|
||||
|
||||
| Endpoint | Versioned | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `/health` | No | Liveness probe |
|
||||
| `/api-reference` | No | Scalar API documentation |
|
||||
| `/api/v1/*` | Yes | Business endpoints |
|
||||
|
||||
### API Documentation
|
||||
|
||||
Interactive API documentation powered by [Scalar](https://scalar.com) is available at `/api-reference` in development and test environments. Controlled via `ENABLE_API_DOCS` env var (defaults to enabled in dev/test, disabled in production).
|
||||
|
||||
### Dependency Injection
|
||||
|
||||
The API uses NestJS's built-in DI container. Key global providers:
|
||||
|
||||
| Module | Provider | Description |
|
||||
|--------|----------|-------------|
|
||||
| `ConfigModule` | `ConfigService` | Environment variable access (global) |
|
||||
| `PrismaModule` | `PrismaService` | Database access via `prisma.client` (global) |
|
||||
|
||||
Usage in feature modules:
|
||||
|
||||
```typescript
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service.js';
|
||||
|
||||
@Injectable()
|
||||
export class MyFeatureService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll() {
|
||||
return this.prisma.client.myModel.findMany();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
davinci-platform/
|
||||
├── packages/
|
||||
│ ├── api/ # NestJS 11 backend (Fastify 5 adapter)
|
||||
│ │ ├── src/
|
||||
│ │ │ ├── main.ts # Bootstrap: NestJS + Fastify + versioning + Scalar
|
||||
│ │ │ ├── app.module.ts # Root module (Config, Prisma, Health)
|
||||
│ │ │ ├── docs/ # API documentation (Scalar + OpenAPI)
|
||||
│ │ │ │ └── api-docs.setup.ts # Multi-version Scalar setup
|
||||
│ │ │ ├── health/ # Health module (liveness probe)
|
||||
│ │ │ └── prisma/ # Database module (global PrismaService)
|
||||
│ │ ├── prisma/
|
||||
│ │ │ ├── schema.prisma # Prisma schema
|
||||
│ │ │ └── seed.ts # Idempotent dev seed script
|
||||
│ │ ├── prisma.config.ts # Prisma 7 config (datasource URL, seed)
|
||||
│ │ └── generated/prisma/ # Generated Prisma client (git-ignored)
|
||||
│ ├── web/ # Next.js 15.5 frontend (App Router)
|
||||
│ │ ├── src/
|
||||
│ │ │ ├── app/ # App Router layout + pages
|
||||
│ │ │ ├── i18n/ # next-intl routing + request config
|
||||
│ │ │ ├── middleware.ts # Locale detection middleware
|
||||
│ │ │ └── lib/utils.ts # cn() utility (clsx + tailwind-merge)
|
||||
│ │ ├── messages/en.json # i18n messages
|
||||
│ │ └── components.json # shadcn/ui config
|
||||
│ └── shared/ # Shared types + constants
|
||||
│ └── src/
|
||||
│ ├── index.ts # Barrel export
|
||||
│ └── constants/index.ts # APP_NAME, etc.
|
||||
├── Dockerfile # Multi-stage production build
|
||||
├── nginx.conf # Reverse proxy: /api/* → :3001, /* → :3000
|
||||
├── entrypoint.sh # Production entrypoint
|
||||
├── docker-compose.yml # Dev environment
|
||||
├── docker-compose.test.yml # Isolated test environment
|
||||
├── Makefile # Developer command interface
|
||||
├── turbo.json # Turborepo task config
|
||||
├── smoke-test.sh # 6-endpoint smoke test
|
||||
└── .env.example # Environment template
|
||||
```
|
||||
|
||||
## Makefile Commands
|
||||
|
||||
Run `make help` for the full list. Key commands:
|
||||
|
||||
### Development
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make dev` | Start Postgres + API + Web in watch mode (local apps) |
|
||||
| `make dev-build` | Build and start full dev stack (Docker) |
|
||||
| `make dev-logs` | Tail API container logs |
|
||||
| `make dev-stop` | Stop containers (data preserved) |
|
||||
| `make dev-reset` | Destroy data + rebuild from scratch |
|
||||
| `make dev-seed` | Seed dev database with test data |
|
||||
|
||||
### Testing
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make test` | Full isolated smoke test (build → run → test → teardown) |
|
||||
| `make test:unit` | Unit tests only |
|
||||
| `make test:e2e` | E2E tests only |
|
||||
| `make test:cov` | Tests with coverage report |
|
||||
| `make smoke` | Smoke tests against running dev stack |
|
||||
|
||||
### Code Quality
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make lint` | Lint all packages |
|
||||
| `make format` | Format all files with Prettier |
|
||||
| `make format:check` | Check formatting without writing |
|
||||
|
||||
### Database
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make db:migrate` | Create a new Prisma migration |
|
||||
| `make db:push` | Push schema changes (quick prototyping) |
|
||||
| `make db:studio` | Open Prisma Studio |
|
||||
|
||||
### Docker
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make docker:build` | Build production Docker image |
|
||||
| `make docker:up` | Run full stack via docker-compose |
|
||||
| `make down` | Stop everything (dev + test) |
|
||||
|
||||
## Port Architecture
|
||||
|
||||
Standard ports are used inside containers (Dockerfile, entrypoint, nginx). Docker Compose maps to non-common host ports to avoid conflicts:
|
||||
|
||||
| Stack | API (host → container) | Web (host → container) | Postgres (host → container) |
|
||||
|-------|----------------------|----------------------|---------------------------|
|
||||
| Dev | 4300 → 3001 | 4000 → 3000 | 55434 → 5432 |
|
||||
| Test | 4301 → 3001 | 4001 → 3000 | 45434 → 5432 |
|
||||
| Local (no Docker) | 3001 (direct) | 3000 (direct) | 55434 → 5432 |
|
||||
| Production (nginx) | :80 (reverse proxy) | :80 (reverse proxy) | — |
|
||||
|
||||
> **Ports are chosen to avoid conflicts:** Common tools (React, Vite, Next.js) use 3000/3001/5173. The Docker dev stack uses 4300/4000/55434.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `DATABASE_URL` | *(required)* | PostgreSQL connection string |
|
||||
| `PORT` | `3001` | API server port |
|
||||
| `NODE_ENV` | `development` | `development`, `production`, or `test` |
|
||||
| `DAVINCI_MODE` | `mothership` | Operating mode (`mothership` or `community`) |
|
||||
| `ENABLE_API_DOCS` | auto | Scalar API docs (`true`/`false`; defaults enabled in dev/test) |
|
||||
| `CORS_ORIGIN` | `*` (dev) | Comma-separated allowed origins |
|
||||
| `LOG_LEVEL` | auto | Pino log level (`debug` in dev, `info` in prod) |
|
||||
| `NEXT_PUBLIC_API_URL` | — | Frontend API URL (set in docker-compose) |
|
||||
|
||||
See [`.env.example`](.env.example) for a starter template.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology | Version |
|
||||
|-------|------------|---------|
|
||||
| Runtime | Node.js | 22 LTS |
|
||||
| Package Manager | pnpm | 10.32.0 |
|
||||
| Build Orchestration | Turborepo | 2.x |
|
||||
| Backend Framework | NestJS | 11.x |
|
||||
| HTTP Server | Fastify | 5.x |
|
||||
| ORM | Prisma | 7.x |
|
||||
| Frontend Framework | Next.js | 15.5.x |
|
||||
| CSS | Tailwind CSS | v4 |
|
||||
| UI Components | shadcn/ui | — |
|
||||
| i18n | next-intl | 4.x |
|
||||
| Testing | Vitest | 3.x |
|
||||
| Linting | ESLint (flat config) | 9.x |
|
||||
| Formatting | Prettier | 3.4.x |
|
||||
| API Docs | Scalar + @nestjs/swagger | — |
|
||||
| Database | PostgreSQL | 16 |
|
||||
| Container | Docker (multi-stage) | — |
|
||||
| Reverse Proxy | nginx | — |
|
||||
Reference in New Issue
Block a user