Overview del Proyecto
Qué es LeadPilot y a quién sirve
Tipo
SaaS B2B
Agencias de marketing digital
Arquitectura
Monorepo
Turborepo · 2 apps · 2 packages
Deploy
Vercel + Railway
CI/CD via GitHub Actions
LeadPilot es una plataforma SaaS B2B que permite a agencias de marketing crear y gestionar campañas de prospección multicanal (email + LinkedIn). Los usuarios enriquecen leads con IA, definen secuencias de outreach y miden la conversión por canal desde un dashboard centralizado. El repo contiene el frontend Next.js 14 (App Router) y la API Express 4, conectados a PostgreSQL 15 vía Prisma ORM y protegidos con autenticación Clerk.
Tech Stack
Tecnologías detectadas en package.json, turbo.json y configs
| Capa | Tecnología | Versión | Rol en el proyecto |
|---|---|---|---|
| Lenguaje | TypeScript | 5.4 | Lenguaje principal en todos los paquetes |
| Frontend | Next.js | 14.2 | App Router · RSC · Server Actions |
| UI | shadcn/ui + Tailwind | 3.4 | Sistema de componentes + estilos utilitarios |
| Backend | Express | 4.18 | REST API, desplegada en Railway |
| ORM | Prisma | 5.14 | Modelos, migraciones y cliente type-safe |
| Base de datos | PostgreSQL | 15 | Persistencia principal (Railway managed) |
| Auth | Clerk | 5.x | JWT + webhooks de usuario |
| Monorepo | Turborepo | 2.x | Build pipeline + caché distribuida |
| Testing | Vitest + Playwright | 1.6 / 1.44 | Unit/integration (Vitest) · E2E (Playwright) |
| CI/CD | GitHub Actions | — | ci.yml (test+lint) · deploy.yml (Vercel/Railway) |
Arquitectura
Monorepo con frontend BFF + API separada
Cliente
Browser
HTTPS
→
Frontend · Vercel
apps/web
Next.js 14 App Router
→
BFF / Server
Route Handlers
app/api/
Next.js BFF layer
→
API · Railway
apps/api
Express 4 REST
→
Base de datos
PostgreSQL 15
via Prisma ORM
Patrón
Monorepo + BFF
Frontend actúa como BFF (Backend for Frontend), delegando lógica pesada a la API Express.
API Style
REST
Endpoints versionados bajo
/api/v1/. Validación con Zod en cada handler.Auth Flow
Clerk JWT
El frontend obtiene el JWT de Clerk y lo envía como Bearer en todas las peticiones a la API.
Shared Code
packages/shared
Tipos TypeScript compartidos entre web y api. Sin lógica de negocio en este paquete.
Key Entry Points
Archivos donde empezar a leer según la tarea
API Backend — Entry Point
apps/api/src/index.ts
Inicializa Express, monta middleware global (auth, rate-limit, cors) y registra los routers. Punto de partida para entender el servidor.
Rutas del API REST
apps/api/src/routes/
Cada recurso tiene su archivo de rutas (
campaigns.routes.ts, leads.routes.ts). Las rutas apuntan a controllers.Frontend — Layout Raíz
apps/web/app/layout.tsx
Envuelve toda la app con ClerkProvider, ThemeProvider y el layout global. Punto de entrada del frontend.
Modelo de datos
apps/api/prisma/schema.prisma
Source of truth del esquema de base de datos. Leerlo antes de tocar cualquier query o servicio.
Cliente HTTP (Frontend → API)
apps/web/lib/api-client.ts
Wrapper tipado de
fetch que inyecta el JWT de Clerk y maneja errores HTTP. Usar siempre en lugar de fetch directo.CI/CD Pipeline
.github/workflows/ci.yml
Define los pasos de lint, test y build que se ejecutan en cada PR. Referencia para saber qué debe pasar localmente antes de pushear.
Mapa de Directorios
Top-level + 2 niveles — sin node_modules, dist, .next
apps/web/app/(dashboard)/
—
Páginas autenticadas del dashboard FRONTEND
apps/web/app/(auth)/
—
Páginas públicas: login, register, forgot-password FRONTEND
apps/web/app/api/
—
Route Handlers (BFF): proxy + transformación para el cliente FRONTEND
apps/web/components/ui/
—
Componentes shadcn/ui base (no modificar directamente)
apps/web/components/campaigns/
—
Componentes de dominio: CampaignCard, CampaignForm, etc.
apps/web/lib/
—
Utilidades: api-client.ts, auth.ts, utils.ts, constants.ts
apps/api/src/routes/
—
Definición de rutas por recurso API
apps/api/src/controllers/
—
Manejo HTTP: req/res/validación, delega a services API
apps/api/src/services/
—
Lógica de negocio pura, sin dependencias HTTP API
apps/api/src/repositories/
—
Acceso a datos: queries Prisma encapsuladas API
apps/api/src/middleware/
—
Auth (Clerk JWT), rate-limit, validación Zod, error handler
apps/api/prisma/
—
schema.prisma + migrations/ — source of truth del modelo de datos
packages/shared/
—
Tipos TypeScript compartidos entre web y api SHARED
packages/config/
—
ESLint, Prettier, tsconfig base — no tocar sin revisar impacto
.github/workflows/
—
ci.yml (lint+test) · deploy.yml (Vercel + Railway)
Ciclo de una Request
Traza: "Listar campañas de un workspace" — de entrada a respuesta
1
Componente React (Server Component)
apps/web
app/(dashboard)/campaigns/page.tsx
llama a lib/api-client.ts con
GET /api/v1/campaigns, adjuntando el JWT de Clerk.
2
Middleware de Auth
apps/api
middleware/auth.ts
verifica el JWT con el SDK de Clerk. Si es válido, adjunta
req.userId y req.workspaceId al request.
3
Router → Controller
apps/api
routes/campaigns.routes.ts
despacha a controllers/campaigns.controller.ts → listCampaigns().
Validación del query con Zod antes de continuar.
4
Service (Lógica de Negocio)
apps/api
services/campaigns.service.ts → getCampaignsForWorkspace()
aplica reglas de negocio: filtros por plan, paginación, orden por defecto.
5
Repository (Acceso a Datos)
apps/api
repositories/campaigns.repository.ts
ejecuta
prisma.campaign.findMany({ where: { workspaceId } }) y devuelve los datos tipados.
6
Respuesta JSON → Render
apps/web
El controller devuelve
res.json({ data: campaigns, meta: { total, page } }).
El Server Component hidrata con los datos y React renderiza la lista.
Convenciones Detectadas
Patrones que ya sigue el codebase — seguirlos sin excepción
📝 Naming
- Archivos: kebab-case para todos (
campaign-card.tsx) - Componentes React: PascalCase (
CampaignCard) - Variables/funciones: camelCase
- Tipos TS: PascalCase con sufijo de dominio (
CampaignDTO) - Tests:
*.test.tsjunto al archivo fuente, E2E entests/e2e/
⚠️ Error Handling
- API: Error handler centralizado en
middleware/error-handler.ts - Los controllers lanzan instancias de
AppError(clase custom) - No usar
try/catchen controllers — el handler lo captura - Frontend: Errores de fetch en
api-client.tsdevuelvenResult<T, ApiError>
🌿 Git Workflow
- Branches:
feat/,fix/,chore/,refactor/ - Commits: Conventional Commits (
feat: add campaign cloning) - PRs: Squash merge a
main, al menos 1 review - Los PRs deben pasar CI (lint + test) antes de mergear
🧪 Testing
- Unit: Vitest en services y repositories
- Integration: Vitest con DB en memoria (Prisma + SQLite)
- E2E: Playwright en
apps/web/tests/e2e/ - Cobertura mínima configurada: 80% en services
Tareas Comunes
Comandos desde la raíz del monorepo
Dev — Todo en paralelo
pnpm dev
Build producción
pnpm build
Tests unitarios
pnpm test
Tests E2E (Playwright)
pnpm test:e2e
Lint + type-check
pnpm lint && pnpm check-types
Migración de DB
pnpm --filter api prisma migrate dev
Seed de datos
pnpm --filter api prisma db seed
Prisma Studio (UI de BD)
pnpm --filter api prisma studio
Dónde Mirar
Referencia rápida por tipo de tarea
| Si quiero… | Archivo / Carpeta |
|---|---|
| Añadir un endpoint de API | apps/api/src/routes/ + controllers/ + services/ |
| Añadir una tabla o campo a la BD | apps/api/prisma/schema.prisma |
| Añadir una página al dashboard | apps/web/app/(dashboard)/ |
| Crear un componente de UI reutilizable | apps/web/components/ui/ (shadcn) o components/[dominio]/ |
| Llamar a la API desde el frontend | apps/web/lib/api-client.ts |
| Cambiar la lógica de autenticación | apps/api/src/middleware/auth.ts + apps/web/lib/auth.ts |
| Añadir un tipo compartido | packages/shared/src/types/ |
| Modificar el pipeline de CI/CD | .github/workflows/ci.yml o deploy.yml |
| Añadir un test unitario | Junto al archivo fuente: [archivo].test.ts |
| Añadir un test E2E | apps/web/tests/e2e/ |
| Cambiar config de ESLint/Prettier/TS | packages/config/ — cuidado: afecta a todo el monorepo |
CLAUDE.md Generado
Archivo listo para colocar en la raíz del repo
# Project Instructions — LeadPilot
# Generated by CULTIVA IA / onboarding-de-codebase · 2026-06-18
## Tech Stack
- TypeScript 5.4 en todos los paquetes
- Frontend: Next.js 14 App Router + shadcn/ui + Tailwind (apps/web)
- Backend: Express 4 REST API (apps/api)
- Base de datos: PostgreSQL 15 via Prisma 5 ORM
- Auth: Clerk (JWT + webhooks)
- Monorepo: Turborepo + pnpm workspaces
## Build & Run
- Dev: pnpm dev (lanza web + api en paralelo)
- Build: pnpm build
- Lint: pnpm lint
- Type-check: pnpm check-types
## Testing
- Unit/integration: pnpm test (Vitest)
- E2E: pnpm test:e2e (Playwright)
- Cobertura mínima: 80% en services
- Patrón de test: [archivo].test.ts junto al fuente, E2E en apps/web/tests/e2e/
## Code Style
- Archivos: kebab-case (campaign-card.tsx)
- Componentes: PascalCase (CampaignCard)
- Tipos: PascalCase con sufijo de dominio (CampaignDTO)
- Error handling en API: lanzar AppError, NO try/catch en controllers
- HTTP desde frontend: usar SIEMPRE lib/api-client.ts, nunca fetch directo
## Database
- Migración: pnpm --filter api prisma migrate dev
- Seed: pnpm --filter api prisma db seed
- UI: pnpm --filter api prisma studio
- Source of truth del esquema: apps/api/prisma/schema.prisma
## Project Structure
apps/web/ → Frontend Next.js 14
apps/api/ → Backend Express 4
apps/api/prisma/ → Esquema + migraciones
packages/shared/ → Tipos TS compartidos (sin lógica de negocio)
packages/config/ → ESLint, Prettier, tsconfig base
## Conventions
- Commits: Conventional Commits (feat: ... / fix: ... / chore: ...)
- Branches: feat/, fix/, chore/, refactor/
- PRs: squash merge a main, 1 review mínimo, CI verde obligatorio
- Tipos compartidos van en packages/shared/, no duplicar entre apps