Project Structure

A map of the deplo.ai monorepo for contributors and the curious: where the dashboard, API, workers, detection engine, and CLI live, and the layering rules that keep them honest.

deplo.ai is a monorepo with three deployable applications — the Next.js client, the Express server, and the npm CLI — plus shared CI workflows. The client deploys to Vercel, the server to Render, and the CLI publishes to npm as @deplo.ai/cli.

deplo-ai/
deplo-ai/
├── client/                      # Next.js 16 (App Router) — deploys to Vercel
│   ├── app/
│   │   ├── page.tsx             # Landing page
│   │   ├── dashboard/           # Repos, deployments, integrations, monitoring
│   │   ├── onboarding/          # Post-signup provider connection flow
│   │   ├── auth/                # OAuth callback handling
│   │   ├── cli-auth/            # Browser side of `deplo login`
│   │   └── docs/                # This documentation portal
│   ├── components/
│   │   ├── landing/  dashboard/  docs/  auth/  seo/  providers/
│   ├── lib/                     # auth.ts, dashboard-api.ts, docs/navigation.ts
│   └── next.config.ts           # Security headers + /api/* rewrite proxy
│
├── server/                      # Express + TypeScript API — deploys to Render
│   ├── prisma/                  # schema.prisma + migrations
│   └── src/
│       ├── config/              # Zod-validated env
│       ├── domain/              # Entities + repository interfaces (pure TS)
│       ├── application/
│       │   ├── services/        # Auth, Deployment, Integration, CliToken, …
│       │   ├── analysis/        # Stack-detection engine + Groq reasoning
│       │   ├── orchestration/   # DeploymentOrchestrator
│       │   └── notifications/   # Deployment lifecycle emails
│       ├── infrastructure/
│       │   ├── database/        # Prisma client + repository implementations
│       │   ├── queue/           # BullMQ: DeploymentWorker, MonitoringWorker
│       │   ├── redis/           # CacheService
│       │   ├── github/  vercel/  render/  groq/  email/   # external adapters
│       ├── interfaces/
│       │   ├── http/            # REST controllers + middleware
│       │   └── swagger/         # OpenAPI spec (dev-only UI)
│       └── shared/              # Winston logger, AppError
│
├── cli/                         # @deplo.ai/cli — publishes to npm (bin: deplo)
│   └── src/
│       ├── commands/            # login, deploy, status, whoami, connect
│       ├── api.ts  config.ts  git.ts  handoff.ts  ui.ts
│
├── .github/workflows/           # ci.yml, pr-lint.yml, docker.yml, release-cli.yml
└── docker-compose.yml           # Local Postgres 16 + Redis 7

client/ — the web app#

A single Next.js 16 application (React 19, TailwindCSS v4, TypeScript strict) containing the marketing landing page, the dashboard, onboarding, the /cli-auth hand-off page, and this docs portal. Server components are the default; "use client" appears only where browser APIs are required.

The most architecturally important file is next.config.ts: its rewrites() proxy every /api/* request to the backend using the server-only API_URL variable, which is why the browser only ever sees one domain. There are no route handlers under app/api/ — the client contains no API logic at all. See Architecture.

The docs portal itself follows a registry pattern: lib/docs/navigation.ts is the single source of truth for the page tree, and it drives the sidebar, breadcrumbs, prev/next links, search index, and sitemap. Adding a page means one entry there plus one page.tsx.

server/ — the API and workers#

One Node.js 20 process serves the REST API (/api/v1) and runs the background workers. It follows strict clean architecture — each layer depends only inward:

LayerResponsibilityDepends on
domain/Entities and repository interfaces. Pure TypeScript — no framework imports of any kind.Nothing
application/Business logic: services, the detection engine, the deployment orchestrator, notifications.domain, shared
infrastructure/Concrete tech: Prisma, Redis, BullMQ, and the GitHub/Vercel/Render/Groq/SMTP adapters.domain, application
interfaces/Delivery: REST controllers, middleware, Swagger. Controllers route; services decide.application

config/ and shared/ are usable by every layer. The composition root is src/index.ts: it connects Postgres and Redis, wires repositories → services → controllers by constructor injection, starts the BullMQ deployment worker and the five-minute monitoring scheduler, and mounts the Express app — one process, no DI framework, no service mesh.

Places worth reading first#

  • application/analysis/ — the detection engine: RepositoryAnalyzer, StructureAnalyzer, FrameworkDetector with its declarative frameworkSignatures.ts, EnvVarScanner, and GroqReasoningService. See Architecture for how the pipeline fits together.
  • application/orchestration/DeploymentOrchestrator.ts — the deployment state machine: analysis, backend-first deploy, URL wiring, failure diagnosis. Narrated in Deployment Lifecycle.
  • infrastructure/queue/DeploymentQueue (job definitions), DeploymentWorker (retry semantics), MonitoringWorker (uptime probes).
  • prisma/schema.prisma — the whole data model: users, repositories, deployments, ProviderConnection, CLI tokens, uptime samples.

cli/ — the terminal client#

@deplo.ai/cli (v0.1.0, Node 20+, bin name deplo) is a thin client over the same REST API the dashboard uses — it holds no deployment logic of its own. commands/ maps one file per command (login, deploy, status, whoami, connect); handoff.ts implements the loopback browser hand-off described in Authentication & Security; git.ts matches the current directory's GitHub remote to your synced repositories. Full usage in the CLI docs.

CI and local development#

Four GitHub Actions workflows keep the monorepo honest: ci.yml (lint, type-check, test, build for client and server), pr-lint.yml (fast PR gate), docker.yml (Docker build verification), and release-cli.yml (publishing the CLI to npm). Locally, docker-compose.yml provides Postgres 16 and Redis 7:

local development
$ docker compose up postgres redis -d

# server → http://localhost:4000  (REST /api/v1 · Swagger /docs)
$ cd server && npm install && cp .env.example .env
$ npm run prisma:migrate && npm run dev

# client → http://localhost:3000  (rewrites /api/* to 127.0.0.1:4000)
$ cd client && npm install && npm run dev
Note
In development the backend also serves a Swagger UI at localhost:4000/docs; it is disabled in production, where this portal is the documentation surface.