Formatting & Naming
- Imports: Use
@/*forapps/webmodules 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:
camelCasefor variables/functions,PascalCasefor types/components,UPPER_SNAKEfor constants/enums. - Strict TypeScript: No
.jsfiles allowed (allowJs: false).
Prisma Workflow Rules
- Schema changes: If you change
prisma/schema.prisma, proactively runnpm 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 withprisma db push. - No Prisma diff, no Prisma commands: If neither
prisma/schema.prismanorprisma/migrations/**changed, do not run Prisma migration commands. - Build contract:
npm run buildmust stay database-independent. Never hide schema mutation inside generic scripts likenpm run build. - Forbidden contexts for
db push: Never useprisma db pushin 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_URLpresent in the environment.
Errors and Error Handling
ThrowAppError(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 tokenizednr-*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
labellayout. - 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, oralignSelfoverrides 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: Intat the database level. - Use explicit UUIDs for all Record IDs.
- Rely on Prisma compound unique keys for lookups.