ADR-0002: Monorepo s Turborepo
- Status: Accepted
- Dátum: 2026-05-10
- Rozhodol: Ján Letko (LTK Solutions)
- Súvisiace ADR: ADR-0001 (tech stack), ADR-0003 (hosting)
Kontext
ClubUp má tri samostatné výstupy:
- Marketingový web (
clubup.sk) — verejný, statický - Študentská aplikácia (
app.clubup.sk) — autentifikovaná, dynamická - Admin aplikácia (
admin.clubup.sk) — autentifikovaná, dynamická
Plus zdieľaný kód:
- UI komponenty (shadcn/ui na vlastných tokenoch)
- Database access layer (MongoDB schémy + repository funkcie)
- Auth helpers (OIDC client, RBAC)
- Konfigurácia (TS, ESLint, Tailwind preset)
Otázka: jeden repo alebo tri?
Zvažované možnosti
Možnosť A — Tri samostatné repá (clubup-web, clubup-app, clubup-admin) + npm packagy
- Pros: úplná izolácia, jednoduchšie CI/CD per projekt, jednoduchšie governance.
- Cons: zdieľaný kód musí byť npm package (publish + version bump pre každú zmenu), refactoring naprieč projektami je bolestivý, hlavne pre 1-osobový tím to znamená hodiny administratívy mesačne.
Možnosť B — Monorepo s Turborepo + npm workspaces
- Pros: jeden git history, atomic commity naprieč apps + packages, zdieľaný kód cez
workspace:*, Turborepo cachuje builds, jednoduchá lokálna dev experience. - Cons: všetky projekty sa nasadzujú spolu (čo môže byť aj výhoda — sync verzie), repo je väčšie.
Možnosť C — Monorepo s Nx
- Pros: silnejší tooling než Turborepo, Module Federation podpora.
- Cons: strmšia learning curve, vlastný build orchestrator namiesto npm workspaces, overkill pre náš objem.
Možnosť D — Monorepo s pnpm workspaces (bez Turborepo)
- Pros: najrýchlejšia inštalácia, najmenej miesta na disku.
- Cons: žiadny task graph / cache (musí sa dorobiť),
sportup.skpoužíva npm — prepínanie na pnpm by zlomilo konzistentnosť.
Rozhodnutie
Monorepo s Turborepo + npm workspaces.
Štruktúra:
src/
├── apps/
│ ├── app/ # app.clubup.sk (Next.js)
│ └── admin/ # admin.clubup.sk (Next.js)
└── packages/
├── ui/ # shadcn/ui design system
├── db/ # MongoDB schémy + repositories
├── auth/ # OIDC client + RBAC
└── config/ # TS / ESLint / Tailwind preset
website/ # statický marketingový web (mimo workspaces)
docs/ # dokumentáciaDôvody
- 1-osobový tím — administratívna réžia 3 repov by zožrala kapacitu, ktorú treba na produkt.
- Refactoring naprieč apps — keď zmeníme
Courseschému vpackages/db, hneď vidíme, kde to zlomí vapps/appaapps/admin. V troch repách by to bola séria PRs. - Atomic deployment — keď meníme API zmluvu, frontend ide spolu s backendom v jednom commite.
- Turborepo cache — pri zmene v
packages/uisa rebuilduje len to, čo na ňom závisí; testy sa cachujú. - Konzistentnosť so SportUp.sk — sportup.sk je tiež monorepo (Turborepo + npm).
- Marketingový web mimo workspaces — je statický, nemá
package.jsons deps, žije vwebsite/a deployuje sa cez VerceloutputDirectory: "website"(definované vvercel.json).
Dôsledky
Pozitívne
- Jeden
npm installna celý projekt - Zdieľanie typov zo
packages/dbpriamo doapps/*bez publish - Jeden CI workflow pre všetko (
turbo run test) - Jednoduchšie code reviews (jeden PR pokrýva celú zmenu)
Negatívne / kompromisy
- Repo môže narásť — pri 5+ apps + 10+ packages bude
npm installpomalší. Riešenie: Turborepo remote cache (Vercel ho má zadarmo) - Všetko sa builduje s každým CI — Turborepo cachuje, ale prvý beh je dlhý
- Branch protection musí byť granular — nie každý commit do
apps/adminmá re-deployovať ajapps/app. Vercel má per-app build conditions cezvercel.jsona Ignored Build Step
Neutrálne
- Pôvodne plánovanú „migráciu marketingového webu z websupport.sk” robíme v rámci toho istého repa —
website/je len ďalší priečinok
Implementačné poznámky
package.jsonna rooti má"workspaces": ["src/apps/*", "src/packages/*"]turbo.jsondefinuje task graph (build,dev,lint,test,typecheck)- Každá app má vlastný
vercel.jsons"buildCommand"a"installCommand"(cez Turborepo) src/packages/configexportuje shared TS/ESLint/Tailwind base configs
Revisit
- Ak sa tím rozšíri nad 5 ľudí — možno bude treba rozdeliť práva per-app (CODEOWNERS riadky); monorepo to zvládne
- Ak by sme chceli open-source-nuť len jednu časť (napr.
packages/ui) — potrebovali by sme submodule alebo split-repo nástroj (git-filter-repo) - Pri 50+ packages — vyhodnotiť, či nie je čas prejsť na Nx s Module Federation