A TypeScript monorepo for the Forgeng apprenticeship platform:
frontend— Next.js 16 frontend (React 19, Tailwind CSS 4, App Router)backend— NestJS 11 backend with Prisma 6 + PostgreSQL- Managed with pnpm workspaces + Turborepo
- Node.js >= 24
- pnpm 10 (
npm i -g pnpm) - A local PostgreSQL 14+ server
forgeng/
├── backend/ # NestJS backend (@forgeng/backend)
│ ├── prisma/
│ │ ├── schema.prisma
│ │ └── seed.ts
│ ├── src/
│ │ ├── prisma/ # PrismaModule + PrismaService (global)
│ │ ├── app.module.ts
│ │ └── main.ts
│ └── .env # DATABASE_URL, PORT, CORS_ORIGIN
├── frontend/ # Next.js frontend (@forgeng/frontend)
│ └── .env.local # NEXT_PUBLIC_API_URL
├── package.json # root scripts (turbo)
├── pnpm-workspace.yaml
└── turbo.json
pnpm installThis runs husky via the prepare script and installs a pre-commit hook that:
pnpm lint:fix— ESLint--fixin frontend and backendgit add -u— re-stage auto-fixed tracked filespnpm lint— block the commit if anything is still failing
Run the same flow manually: pnpm lint:fix && pnpm lint.
Create the database in your local Postgres instance:
CREATE DATABASE forgeng;Then set the connection string in backend/.env (copy from .env.example):
DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/forgeng?schema=public"
PORT=3001
CORS_ORIGIN="http://localhost:3000"
pnpm prisma:migrate # creates the schema + generates the client
pnpm --filter @forgeng/backend db:seed # optional: insert sample dataRun everything at once (Turborepo):
pnpm devOr run apps individually:
pnpm dev:fe # Next.js -> http://localhost:3000
pnpm dev:be # NestJS -> http://localhost:3001Verify the API and its database connection:
curl http://localhost:3001/health
# -> {"status":"ok","database":"up"}| Command | Description |
|---|---|
pnpm dev |
Run all apps in watch mode (turbo) |
pnpm build |
Build every app (turbo) |
pnpm lint |
Lint every app |
pnpm test |
Run all tests |
pnpm prisma:generate |
Regenerate the Prisma client |
pnpm prisma:migrate |
Create/apply a dev migration |
pnpm prisma:studio |
Open Prisma Studio (DB browser) |
Frontend deploys to Vercel, backend (with managed Postgres) deploys to
Render — both via native GitHub integrations, no GitHub Actions needed.
The repo includes a render.yaml blueprint so Render
provisions the backend and the database in one click.
See docs/deployment.md for the step-by-step guide.
- The API runs on port 3001 to avoid colliding with the Next.js dev server on 3000.
PrismaServiceconnects on module init and disconnects on shutdown; the module is@Global(), soPrismaServicecan be injected anywhere without re-importing.- Frontend reaches the backend via
NEXT_PUBLIC_API_URL(frontend/.env.local).