Architecture
Architecture
Baseline layering, boundaries, and enforceable rules.
This school-os uses a strong default architecture that is intentionally overridable.
Principles
- Keep apps thin; keep reusable behavior in packages.
- Prefer module public entrypoints over deep internal imports.
- Keep domain logic separate from transport and framework concerns.
- Enforce boundaries with automated checks, not only conventions.
Layering
apps/web
src/app/*is routing and composition.src/modules/*is feature-level UI and workflows.src/lib/*contains framework-agnostic helpers for the app.src/components/*contains reusable visual components.
apps/nest-api
src/modules/*holds feature modules (controller/service/repository).src/common/*holds cross-cutting HTTP concerns (filters, interceptors, pipes, guards).src/config/*holds validated environment configuration.- Controllers stay thin; business logic lives in services; database access in repositories.
packages/*
- Packages should remain app-agnostic and not import app aliases like
@/.... - Shared packages expose public entrypoints and avoid framework lock-in when possible.
Enforcement
- Run
bun run architecture:checklocally and in CI (import boundaries + kebab-case naming). - Boundary checks currently validate:
- no
@/...imports insidepackages/* - no deep web module imports (
@/modules/*/*/*) from outsidesrc/modules/ - no cross-app relative imports via
../../apps/ - no cross-app relative imports (
../../apps/...) - kebab-case file/folder names under TS/JS
src/(allows Nest dotted names likeauth.service.ts, route groups(auth), and[id]params)
- no
ADRs
See /docs/architecture/adr-0001-strong-default-overridable for rationale and trade-offs.