Our setup
One repo, three packages: apps/web (Next.js), apps/api (NestJS), and packages/types (shared TS). Turborepo orchestrates the pipeline, pnpm handles the install graph.
Why it works for us
Shared types are the killer feature. A response shape change in NestJS shows up as a TypeScript error in Next.js in the same PR. No drift, no client SDK to keep in sync, no "the schema is out of date" Slack thread.
When we would not
If our frontend and backend teams worked on different release cadences with different on-call rotations, the monorepo would be friction not leverage. If we had ten apps instead of two, we would invest in Nx instead of Turborepo. If one of the apps was a mobile app with its own native toolchain, we would split.