JurgestBalla
AboutServicesWorkBlogContact
JurgestBalla

Senior Full-Stack Engineer

ERP Integrations & Legacy Modernization

Tirana, Albania

Navigation

AboutServicesWorkBlogContact

Connect

LinkedInGitHubinfo@jurgest.comB2B projects via Klartech

Legal

Privacy policyImprint

© 2026 Jurgest Balla. All rights reserved.

Built by me ·

Back to blog
Published 27 May 20255 min read

Monorepos with Nx and Turborepo: what I kept and what I dropped

After several products in Nx and Turborepo monorepos: the structure, caching and shared-type habits that paid off, and the ones that only added ceremony.

MonorepoNxTurborepoTypeScript

Why a monorepo at all

Most of the products I worked on had a web app, an admin app, sometimes a mobile app, and one or more backend services. Without a monorepo, the same types, validation rules and UI components were copied between repositories and slowly drifted apart.

What I kept

  1. Shared types and validation in one package. API request and response shapes defined once, with Zod schemas that both the backend and the frontend import.
  2. A shared UI package with Storybook, so a button or a table is fixed once for every app.
  3. Remote caching for builds and tests. On a busy branch it turns a ten-minute pipeline into a two-minute one.
  4. One lint and format setup for the whole repository.
apps/
  web/          // Next.js
  admin/        // React
  api/          // NestJS
packages/
  shared-types/ // Zod schemas + inferred types
  ui/           // components + Storybook

What I dropped

Generators for every new file, deep folder hierarchies inside packages, and packages created "just in case". A package earns its place when two apps really use it.

The rule that matters most

Dependencies point one way: apps depend on packages, packages never depend on apps. Enforce it with lint rules; the day it breaks, builds start to fail in confusing ways.