Skip to main content
We enforce a strict, consistent codebase to ensure maintainability across the monorepo.

Formatting & Naming

  • Imports: Use @/* for apps/web modules and @corgtex/* for shared package entrypoints. Use type imports for type-only imports (import type { X }).
  • Formatting: Double quotes, no semicolons omission (we use semicolons), 2-space indent (enforced via Prettier).
  • Naming: camelCase for variables/functions, PascalCase for types/components, UPPER_SNAKE for constants/enums.
  • Strict TypeScript: No .js files allowed (allowJs: false).

Prisma Workflow Rules

  • Schema changes: If you change prisma/schema.prisma, proactively run npm run prisma:migrate -- --name <descriptive_name> and commit the generated SQL migration file.
  • Migration changes: If you change prisma/migrations/**, validate the migration path against a database before finishing, but do not create or apply schema changes with prisma db push.
  • No Prisma diff, no Prisma commands: If neither prisma/schema.prisma nor prisma/migrations/** changed, do not run Prisma migration commands.
  • Build contract: npm run build must stay database-independent. Never hide schema mutation inside generic scripts like npm run build.
  • Forbidden contexts for db push: Never use prisma db push in CI, Dockerfiles, production deploy flows, or as part of routine agent work in this repo.

Next.js Build Guardrails

  • Database Page Caching: All Prisma-dependent App Router pages MUST have export const dynamic = "force-dynamic". Do not let Next.js attempt static database queries during the build phase.
  • Build Pass: Build-time database fallbacks are not an acceptable substitute for runtime configuration. The web build must continuously succeed without DATABASE_URL present in the environment.

Errors and Error Handling

Throw AppError(status, code, message) from domain logic and convert it in Next.js route handlers with the handleRouteError() helper block from apps/web/lib/http.ts.

UI Control Consistency

  • Workspace app UI should start from the shared UX spine: ControlPrimitives, shared tables, work-item controls, workspace shell/nav, and tokenized nr-* classes.
  • If a page-specific exception is better for the user than the existing shared primitive, promote the stronger behavior into the shared primitive layer instead of copying the exception across pages.
  • Keep a local exception only when the PR plan explains why reuse would hurt task clarity, accessibility, responsive behavior, or performance.
  • Controls in the same family must share size, typography, spacing, and alignment.
  • Filter sets must use the shared filter toolbar pattern for search, selects, multiselects, and apply/clear actions.
  • Inline checkbox or toggle filters must use the shared checkbox filter pattern instead of relying on global label layout.
  • View and mode switches must use shared segmented controls.
  • Module-level navigation must use shared workspace subnav.
  • Empty states and tables must use shared primitives unless the PR plan explains a stronger user need.
  • Table row actions must use shared action groups so edit, resend, revoke, approve, reject, and similar controls align consistently.
  • Inline fontSize, padding, width, minWidth, or alignSelf overrides on buttons, filters, checkbox controls, segmented controls, subnavs, or table actions are review concerns unless they map to a named design-system class.

Database Conventions

  • All monetary values must be stored as *Cents: Int at the database level.
  • Use explicit UUIDs for all Record IDs.
  • Rely on Prisma compound unique keys for lookups.