Starter Docs
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:check locally and in CI (import boundaries + kebab-case naming).
  • Boundary checks currently validate:
    • no @/... imports inside packages/*
    • no deep web module imports (@/modules/*/*/*) from outside src/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 like auth.service.ts, route groups (auth), and [id] params)

ADRs

See /docs/architecture/adr-0001-strong-default-overridable for rationale and trade-offs.

On this page