869 lines
32 KiB
Markdown
869 lines
32 KiB
Markdown
# AGENTS.md - AI Coding Agent Reference
|
|
|
|
This file provides project-specific guidance for AI coding agents working in this repository. It reflects the current architecture and migration status of the codebase.
|
|
|
|
---
|
|
|
|
## Project Overview
|
|
|
|
This project is a Next.js admin dashboard starter that is being migrated from template scaffolding to an app-owned architecture.
|
|
|
|
Current core stack:
|
|
|
|
- **Framework**: Next.js 16 (App Router)
|
|
- **Language**: TypeScript 5.7
|
|
- **UI**: shadcn/ui + Tailwind CSS v4
|
|
- **Authentication**: Auth.js
|
|
- **Persistence**: PostgreSQL + Drizzle ORM
|
|
- **Data Fetching**: TanStack React Query
|
|
- **URL State**: nuqs
|
|
- **Forms**: TanStack Form + Zod
|
|
- **Charts**: Recharts
|
|
- **Monitoring**: Sentry
|
|
- **Package Manager**: Bun preferred, npm acceptable
|
|
|
|
Current migration status:
|
|
|
|
- Auth has been moved to **Auth.js**
|
|
- Multi-tenant data now uses app-owned **`users`**, **`organizations`**, and **`memberships`**
|
|
- **`products`** has been migrated to Route Handlers + Drizzle
|
|
- **`users`** has been migrated to Route Handlers + Drizzle
|
|
- RBAC now uses a global `users.system_role` plus organization-scoped `memberships.role`
|
|
- self-service sign-up is disabled; accounts must be created by an admin
|
|
- some legacy pages still exist as placeholders or transitional seams
|
|
|
|
---
|
|
|
|
## Governance Layer
|
|
|
|
This repository now treats governance documentation as implementation input, not optional background reading.
|
|
|
|
Before any task that changes behavior, architecture, permissions, reporting, exports, PDFs, approvals, or CRM workflow, agents must review the relevant standards and foundations first.
|
|
|
|
Primary governance documents:
|
|
|
|
- `AGENTS.md`
|
|
- `docs/standards/task-contract-template.md`
|
|
- `docs/standards/task-catalog.md`
|
|
- `docs/standards/project-foundations.md`
|
|
- `docs/standards/architecture-rules.md`
|
|
- `docs/standards/ui-ux-rules.md`
|
|
- `docs/standards/task-review-checklist.md`
|
|
- `docs/adr/**`
|
|
- `docs/business/**`
|
|
- `docs/security/**`
|
|
- `docs/implementation/**` for the related feature lineage
|
|
|
|
### Task Execution Rules
|
|
|
|
All tasks follow these rules:
|
|
|
|
- review first; implementation without review is prohibited
|
|
- reuse existing foundations before creating new modules, helpers, or flows
|
|
- extend existing services before creating duplicate services
|
|
- extend existing route groups before creating duplicate APIs
|
|
- extend existing permission models before creating duplicate permission systems
|
|
- extend existing export/report foundations before creating duplicate export flows
|
|
- keep business logic in feature service layers, not in route handlers or client components
|
|
- document any exception when an existing foundation cannot be reused
|
|
|
|
Required review order for non-trivial work:
|
|
|
|
1. `AGENTS.md`
|
|
2. `docs/standards/**`
|
|
3. relevant `docs/adr/**`
|
|
4. relevant `docs/business/**`
|
|
5. related completed tasks from `docs/standards/task-catalog.md` and `docs/implementation/**`
|
|
6. existing foundations under `src/features/foundation/**`
|
|
7. existing feature implementations under `src/features/**`
|
|
8. existing APIs under `src/app/api/**`
|
|
9. permission and access enforcement under `src/lib/auth/**`, `src/features/crm/security/**`, and `docs/security/**`
|
|
10. existing audit patterns under `src/features/foundation/audit-log/**`
|
|
|
|
### Historical Knowledge Rule
|
|
|
|
Before implementing any feature:
|
|
|
|
1. review related foundations
|
|
2. review related ADRs
|
|
3. review related completed tasks from `docs/standards/task-catalog.md`
|
|
4. reuse before creating
|
|
|
|
Implementation without historical review is prohibited.
|
|
|
|
### Required Foundations
|
|
|
|
The following reusable foundations are mandatory whenever the task touches their area:
|
|
|
|
- Audit Foundation: `src/features/foundation/audit-log/**`
|
|
- Approval Foundation: `src/features/foundation/approval/**`
|
|
- Storage Foundation: `src/features/foundation/storage/**` and `src/features/foundation/document-artifact/**`
|
|
- PDF Foundation: `src/features/foundation/pdf-generator/**` and `src/features/crm/quotations/document/**`
|
|
- Report Foundation: `src/features/crm/reports/**`, `docs/adr/0017-report-foundation.md`
|
|
- CRM Authorization Foundation: `src/lib/auth/crm-access.ts`, `src/features/crm/security/**`, `docs/security/**`
|
|
- Customer Ownership Foundation: `docs/adr/0015-customer-ownership-contact-sharing.md`, `src/features/crm/customers/**`
|
|
- Contact Sharing Foundation: `docs/adr/0015-customer-ownership-contact-sharing.md`, `src/app/api/crm/customers/[id]/contacts/[contactId]/shares/**`
|
|
|
|
If a task touches CRM leads, enquiries, quotations, approvals, reports, exports, storage, or PDFs, agents must explicitly check whether one of these foundations already solves part of the problem.
|
|
|
|
### Architecture Constraints
|
|
|
|
Frontend constraints:
|
|
|
|
- Next.js App Router only
|
|
- server components first
|
|
- `PageContainer` for dashboard page headers
|
|
- shadcn/ui primitives and existing app UI wrappers
|
|
- TanStack React Query with server prefetch + `HydrationBoundary` + client `useSuspenseQuery()` for data-heavy app pages
|
|
- TanStack Form + Zod for forms
|
|
- `nuqs` for URL state
|
|
- existing CRM terminology helpers and Thai labels for business-facing CRM UI
|
|
|
|
Backend constraints:
|
|
|
|
- Route Handlers are the main HTTP boundary
|
|
- feature service layer owns business logic
|
|
- Drizzle ORM owns database access
|
|
- auth and organization access go through `@/auth` and `src/lib/auth/session.ts`
|
|
- CRM scope resolution goes through resolved-access helpers, not direct role-string branching
|
|
- audit logging goes through `src/features/foundation/audit-log/service.ts`
|
|
|
|
Forbidden patterns:
|
|
|
|
- Redux for new application state
|
|
- SWR for new server-state fetching
|
|
- React Hook Form for new forms in this repo
|
|
- direct database access from client components
|
|
- business logic inside route handlers
|
|
- new Clerk usage
|
|
- direct role-string authorization such as `if (role === 'sales')`
|
|
- report-specific export systems that bypass `src/features/crm/reports/server/exports/service.ts`
|
|
|
|
### Mandatory Task Review
|
|
|
|
Before implementation, every non-trivial task must review:
|
|
|
|
- reusable foundations
|
|
- relevant ADRs
|
|
- related completed tasks from `docs/standards/task-catalog.md`
|
|
- related existing APIs
|
|
- permission and scope enforcement
|
|
- audit events and existing entity/action naming
|
|
- duplication risk across services, routes, exports, datasets, and UI shells
|
|
|
|
Implementation without this review is prohibited.
|
|
|
|
### AI Workflow
|
|
|
|
AI coding agents should follow this workflow for non-trivial work:
|
|
|
|
1. Requirement analysis: restate the requested outcome, scope, and non-goals.
|
|
2. Historical review: read the required standards, related ADRs, completed task notes, and relevant business/security docs.
|
|
3. Architecture review: identify the approved foundations, service boundaries, route groups, permissions, audit events, and UI shells that already apply.
|
|
4. Existing pattern discovery: search the codebase for similar components, hooks, utilities, dialogs, forms, tables, services, route handlers, layouts, providers, and tests before creating new ones.
|
|
5. Implementation plan: choose the smallest change that extends existing architecture and document any justified exception.
|
|
6. Implementation: make scoped changes in the owning feature/foundation area.
|
|
7. Self review: check architecture, reuse, security, data freshness, UI states, accessibility, and maintainability before delivery.
|
|
8. Validation: run the most relevant lint, typecheck, test, build, or manual verification available for the change.
|
|
9. Delivery: summarize what changed, what was verified, and any residual risks or follow-up work.
|
|
|
|
For small documentation-only or inspection tasks, agents may use a lighter version of this workflow, but they must still preserve project rules and avoid inventing new architecture.
|
|
|
|
### Existing Pattern Discovery
|
|
|
|
Before creating any new component, hook, utility, dialog, service, API, layout, table, form, provider, export flow, report dataset, permission helper, or audit event, agents must search for an existing implementation that can be reused or extended.
|
|
|
|
Minimum discovery expectations:
|
|
|
|
- search by domain name, route segment, entity name, and UI pattern
|
|
- inspect neighboring features under `src/features/**`
|
|
- inspect shared UI under `src/components/**`
|
|
- inspect existing route handlers under `src/app/api/**`
|
|
- inspect shared auth, permission, audit, report, PDF, approval, storage, and document foundations when the task touches those areas
|
|
- prefer extending an existing module over introducing a parallel one
|
|
|
|
If a new implementation is still required, document why the existing pattern could not be reused.
|
|
|
|
### AI Skill Composition
|
|
|
|
External AI skills, plugins, models, and assistant-specific workflows may help with implementation, but project standards always have the highest priority.
|
|
|
|
Use this responsibility order:
|
|
|
|
1. Project standards: `AGENTS.md`, `docs/standards/**`, ADRs, business docs, security docs, and implementation history.
|
|
2. Architecture: approved Next.js, Auth.js, Drizzle, React Query, route-handler, service-layer, permission, and foundation patterns.
|
|
3. Existing code pattern: local implementations already present in this repository.
|
|
4. External skill: framework, UI, accessibility, performance, testing, documentation, or migration guidance.
|
|
5. UI polish: visual refinement that preserves the established dashboard design language.
|
|
|
|
AI-specific guidance must not override repository rules. When external advice conflicts with this document or the standards docs, follow the repository rule and note the conflict if it affects the deliverable.
|
|
|
|
---
|
|
|
|
## Technology Stack Details
|
|
|
|
### Core Runtime
|
|
|
|
- Next.js 16.x with App Router
|
|
- React 19.x
|
|
- TypeScript strict mode
|
|
|
|
### Styling & UI
|
|
|
|
- Tailwind CSS v4
|
|
- shadcn/ui components
|
|
- CSS custom properties and theme registry
|
|
|
|
### State Management
|
|
|
|
- Zustand for local UI state
|
|
- nuqs for URL search params
|
|
- TanStack Form + Zod for forms
|
|
|
|
### Data Fetching
|
|
|
|
- TanStack React Query for server state
|
|
- server prefetch with `HydrationBoundary` + `dehydrate`
|
|
- `useSuspenseQuery()` for client consumption of prefetched data
|
|
|
|
### Authentication & Authorization
|
|
|
|
- Auth.js for authentication
|
|
- app-owned `organizations` and `memberships` for multi-tenant access
|
|
- global system role stored on `users.system_role`
|
|
- organization role and permissions stored on `memberships`
|
|
- client-side nav filtering is UX-only; real protection must be server-side
|
|
|
|
### Persistence & APIs
|
|
|
|
- PostgreSQL + Drizzle ORM
|
|
- Route Handlers under `src/app/api/**` are the main server boundary
|
|
- feature services call those route handlers through `src/lib/api-client.ts`
|
|
- mock APIs remain only as **legacy migration seams**
|
|
|
|
---
|
|
|
|
## Current Auth Model
|
|
|
|
The current auth model is app-owned and centered around:
|
|
|
|
- `users`
|
|
- `organizations`
|
|
- `memberships`
|
|
|
|
Important files:
|
|
|
|
- `src/auth.ts` - Auth.js config and exported helpers
|
|
- `src/lib/auth/session.ts` - shared server-side auth helpers
|
|
- `src/proxy.ts` - route protection
|
|
- `src/db/schema.ts` - current database schema
|
|
|
|
Current behavior:
|
|
|
|
- authentication uses an Auth.js **Credentials** provider
|
|
- passwords are verified against `users.password_hash`
|
|
- global RBAC uses `users.system_role` with `super_admin | user`
|
|
- organization RBAC uses `memberships.role` with `admin | user`
|
|
- the user row stores `active_organization_id`
|
|
- session enrichment loads organization and membership data on each request
|
|
- self-service sign-up is disabled
|
|
- initial super admin bootstrap is done with the seed script, not through the UI
|
|
|
|
Preferred server-side helpers:
|
|
|
|
- `requireSession()`
|
|
- `requireSystemRole()`
|
|
- `requireOrganizationAccess(options?)`
|
|
|
|
Do not introduce new Clerk usage.
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```text
|
|
/src
|
|
├── app/ # Next.js App Router
|
|
│ ├── auth/ # Auth pages
|
|
│ ├── dashboard/ # Dashboard routes
|
|
│ ├── api/ # Route handlers
|
|
│ ├── layout.tsx # Root layout
|
|
│ └── page.tsx # Landing / redirect entry
|
|
│
|
|
├── components/
|
|
│ ├── ui/ # shadcn/ui and app UI primitives
|
|
│ ├── layout/ # Sidebar, header, providers
|
|
│ ├── forms/ # Form field wrappers
|
|
│ ├── themes/ # Theme system
|
|
│ └── icons.tsx # Single icon registry
|
|
│
|
|
├── db/
|
|
│ └── schema.ts # Drizzle schema
|
|
│
|
|
├── features/
|
|
│ ├── auth/
|
|
│ ├── overview/
|
|
│ ├── products/ # Migrated: React Query + Route Handlers + Drizzle
|
|
│ ├── users/ # Migrated: React Query + Route Handlers + Drizzle + RBAC
|
|
│ ├── react-query-demo/
|
|
│ ├── kanban/
|
|
│ ├── chat/
|
|
│ ├── notifications/
|
|
│ └── profile/
|
|
│
|
|
├── config/
|
|
│ └── nav-config.ts
|
|
│
|
|
├── hooks/
|
|
│ ├── use-nav.ts
|
|
│ └── use-data-table.ts
|
|
│
|
|
├── lib/
|
|
│ ├── api-client.ts
|
|
│ ├── auth/
|
|
│ ├── db.ts
|
|
│ ├── query-client.ts
|
|
│ └── searchparams.ts
|
|
│
|
|
├── styles/
|
|
└── types/
|
|
```
|
|
|
|
Relevant docs/plans:
|
|
|
|
- `plans/req.md`
|
|
- `plans/implementation-plan.md`
|
|
- `docs/themes.md`
|
|
- `docs/nav-rbac.md`
|
|
- `docs/clerk_setup.md` is legacy historical reference only
|
|
|
|
---
|
|
|
|
## Build & Development Commands
|
|
|
|
```bash
|
|
# Install dependencies
|
|
bun install
|
|
# or
|
|
npm install
|
|
|
|
# Development server
|
|
bun run dev
|
|
# or
|
|
npm run dev
|
|
|
|
# Build
|
|
bun run build
|
|
# or
|
|
npm run build
|
|
|
|
# Start
|
|
bun run start
|
|
# or
|
|
npm run start
|
|
|
|
# Lint
|
|
bun run lint
|
|
# or
|
|
npm run lint
|
|
|
|
# Format
|
|
bun run format
|
|
# or
|
|
npm run format
|
|
```
|
|
|
|
---
|
|
|
|
## Environment Configuration
|
|
|
|
Copy `env.example.txt` to `.env.local` and configure:
|
|
|
|
### Required
|
|
|
|
```env
|
|
AUTH_SECRET=your-long-random-secret
|
|
DATABASE_URL=postgres://postgres:postgres@localhost:5432/training_system
|
|
SUPER_ADMIN_EMAIL=admin@example.com
|
|
SUPER_ADMIN_PASSWORD=change-this-password
|
|
```
|
|
|
|
### Optional for Sentry
|
|
|
|
```env
|
|
NEXT_PUBLIC_SENTRY_DSN=https://...@....ingest.sentry.io/...
|
|
NEXT_PUBLIC_SENTRY_ORG=your-org
|
|
NEXT_PUBLIC_SENTRY_PROJECT=your-project
|
|
SENTRY_AUTH_TOKEN=sntrys_...
|
|
NEXT_PUBLIC_SENTRY_DISABLED="false"
|
|
```
|
|
|
|
Notes:
|
|
|
|
- keep auth and database secrets server-only
|
|
- OAuth providers can be added later through Auth.js
|
|
- billing is currently modeled as app-owned organization plan data, not a live provider integration
|
|
- run `npm run setup:db` on first setup to apply migrations and seed the initial super admin
|
|
|
|
---
|
|
|
|
## Code Style Guidelines
|
|
|
|
### TypeScript
|
|
|
|
- strict mode enabled
|
|
- use explicit return types for public functions when useful
|
|
- prefer `interface` for object contracts
|
|
- use `@/*` imports from `src`
|
|
|
|
### Component Conventions
|
|
|
|
- use function declarations for components
|
|
- server components by default
|
|
- add `'use client'` only when needed
|
|
- use `cn()` for className merging
|
|
|
|
### Forms
|
|
|
|
- use TanStack Form via `useAppForm` from `@/components/ui/tanstack-form`
|
|
- use Zod for submit validation
|
|
- avoid `useState` inside `AppField` render props
|
|
|
|
### Buttons
|
|
|
|
- use `<Button isLoading={isPending}>` for loading states
|
|
|
|
### Component Reuse Policy
|
|
|
|
Before creating any new UI building block, search for an existing shared or feature-local pattern first.
|
|
|
|
This applies to:
|
|
|
|
- cards and summary cards
|
|
- data tables, columns, filters, and toolbars
|
|
- dialogs, sheets, drawers, destructive confirmations, and preview panels
|
|
- forms, field wrappers, validation schemas, and submit buttons
|
|
- status badges, labels, empty states, loading states, and error states
|
|
- action bars, page headers, side panels, tabs, and navigation helpers
|
|
|
|
Reuse order:
|
|
|
|
1. shared app components under `src/components/**`
|
|
2. foundation or CRM shared components under `src/features/foundation/**` and `src/features/crm/**`
|
|
3. same-feature components under `src/features/<feature>/components/**`
|
|
4. a new component only when reuse would create inappropriate coupling or unclear ownership
|
|
|
|
New reusable components should follow the established shadcn/ui, Tailwind, `cn()`, icon registry, accessibility, and server/client boundary patterns.
|
|
|
|
### Refactoring Policy
|
|
|
|
Refactoring is encouraged when it reduces duplication, clarifies ownership, or makes the requested change safer.
|
|
|
|
Preferred refactoring:
|
|
|
|
- extend existing modules, services, schemas, query keys, mutations, and components
|
|
- keep public contracts backward compatible unless the task explicitly requires a breaking change
|
|
- move repeated business logic into the owning feature service or foundation
|
|
- simplify local code while preserving established architecture and terminology
|
|
- update documentation when a new rule, exception, or reusable pattern is introduced
|
|
|
|
Avoid:
|
|
|
|
- broad rewrites unrelated to the task
|
|
- parallel helpers that duplicate foundation behavior
|
|
- replacing working project patterns with a different library or architecture
|
|
- cosmetic churn in files outside the requested scope
|
|
- renaming domain concepts without a business or ADR-backed reason
|
|
|
|
### Maintainability Expectations
|
|
|
|
Code should be understandable to future agents and engineers without relying on hidden prompt context.
|
|
|
|
- keep contracts explicit and close to their feature boundary
|
|
- prefer clear names over comments for ordinary logic
|
|
- add short comments only for non-obvious business rules, security decisions, or compatibility seams
|
|
- avoid leaking implementation details from services into UI components
|
|
- keep route handlers thin and move reusable logic into feature/foundation services
|
|
|
|
---
|
|
|
|
## Navigation & RBAC
|
|
|
|
Navigation is configured in `src/config/nav-config.ts`.
|
|
|
|
Current access properties:
|
|
|
|
- `systemRole`
|
|
- `requireOrg`
|
|
- `permission`
|
|
- `role`
|
|
- `plan`
|
|
- `feature`
|
|
|
|
Notes:
|
|
|
|
- `systemRole` is for global access such as `super_admin`
|
|
- `requireOrg` remains a compatibility seam and means the user must have an active organization
|
|
- nav filtering in `src/hooks/use-nav.ts` uses Auth.js session data
|
|
- server routes and server pages must enforce real access independently
|
|
|
|
---
|
|
|
|
## Date & Time Formatting Rules
|
|
|
|
- All date and time rendering must use the shared formatter in `src/lib/date-format.ts`.
|
|
- Never use `Date.prototype.toLocaleString()`, `toLocaleDateString()`, `toLocaleTimeString()`, or `Intl.DateTimeFormat()` directly inside React components.
|
|
- UI date display standard:
|
|
- Date: `YYYY-MM-DD`
|
|
- DateTime: `YYYY-MM-DD HH:mm:ss`
|
|
- Time: `HH:mm:ss`
|
|
- API responses must remain ISO-8601 UTC.
|
|
- UI is responsible for formatting.
|
|
- Timezone is fixed to `Asia/Bangkok`.
|
|
- Calendar system must always use Gregorian (AD), never Buddhist Era (BE).
|
|
- All formatting must be deterministic to ensure identical SSR and Client rendering and prevent React hydration mismatches.
|
|
|
|
---
|
|
|
|
## Authentication Patterns
|
|
|
|
### Protected Routes
|
|
|
|
Dashboard routes are protected through `src/proxy.ts`.
|
|
|
|
Example protected page:
|
|
|
|
```tsx
|
|
import { auth } from '@/auth';
|
|
import { redirect } from 'next/navigation';
|
|
|
|
export default async function Page() {
|
|
const session = await auth();
|
|
|
|
if (!session?.user) {
|
|
redirect('/auth/sign-in');
|
|
}
|
|
|
|
if (!session.user.activeOrganizationId) {
|
|
redirect('/dashboard/workspaces');
|
|
}
|
|
|
|
return <div>Protected</div>;
|
|
}
|
|
```
|
|
|
|
### Shared Server Helpers
|
|
|
|
Prefer:
|
|
|
|
- `requireSession()`
|
|
- `requireSystemRole()`
|
|
- `requireOrganizationAccess(options?)`
|
|
|
|
### Plan / Feature Gating
|
|
|
|
Do not use vendor-specific gating components.
|
|
|
|
Read plan or feature state from app-owned organization data and enforce it server-side.
|
|
|
|
---
|
|
|
|
## Data Fetching Patterns
|
|
|
|
### Service Layer Architecture
|
|
|
|
Each feature should use:
|
|
|
|
```text
|
|
src/features/<name>/api/
|
|
types.ts
|
|
service.ts
|
|
queries.ts
|
|
mutations.ts # when mutations exist
|
|
```
|
|
|
|
Rules:
|
|
|
|
- components import types from `types.ts`
|
|
- components call query options from `queries.ts`
|
|
- services call local route handlers through `apiClient`
|
|
- route handlers talk to Drizzle / database
|
|
|
|
### Backend Patterns
|
|
|
|
Preferred patterns in this repo:
|
|
|
|
| Pattern | Guidance |
|
|
| --- | --- |
|
|
| Route Handlers + ORM | Preferred for app-owned features |
|
|
| Server Actions + ORM | Acceptable when it fits the feature well |
|
|
| BFF | Acceptable when proxying to an external backend |
|
|
| Mock | Legacy only, not the preferred path |
|
|
|
|
### React Query
|
|
|
|
Preferred pattern for new pages:
|
|
|
|
1. define query options in `queries.ts`
|
|
2. prefetch in the server page
|
|
3. hydrate with `HydrationBoundary`
|
|
4. read with `useSuspenseQuery()`
|
|
|
|
Required pattern for CRUD mutations:
|
|
|
|
1. every feature must define centralized query key factories in `queries.ts`
|
|
2. use grouped keys such as `all`, `lists()`, `list(filters)`, `details()`, `detail(id)`, plus child-resource keys like `contacts(id)` or `followups(id)` when needed
|
|
3. after create, explicitly invalidate the list-level key
|
|
4. after update, explicitly invalidate both list and detail keys
|
|
5. after delete, explicitly invalidate the list key and remove stale detail queries with `removeQueries`
|
|
6. invalidate related queries affected by the mutation, such as counts, child tabs, document previews, approval panels, and cross-feature related lists
|
|
7. do not rely on `staleTime` alone to refresh production CRUD data
|
|
8. do not rely on `router.refresh()` alone for CRUD freshness; React Query invalidation is required first, and `router.refresh()` is optional only as a supplement
|
|
|
|
Mutation callback safety rule:
|
|
|
|
- if a shared mutation object from `api/mutations.ts` is spread into `useMutation({ ...sharedMutation, ... })`, do not override `onSuccess` or `onSettled` in a way that drops cache invalidation
|
|
- prefer keeping cache invalidation inside the shared mutation definition
|
|
- if component-level success behavior is needed, either:
|
|
- put invalidation in shared `onSettled` and keep UI concerns like toast and closing dialogs in component `onSuccess`, or
|
|
- call the shared invalidate helper explicitly from the component before closing the sheet/dialog
|
|
|
|
UI completion rule after successful mutation:
|
|
|
|
- close sheet/dialog only after the mutation promise resolves successfully
|
|
- table/detail views must show fresh data immediately without a full browser refresh
|
|
- related tabs and counts must refresh in the same interaction when their backing data changed
|
|
|
|
### URL State
|
|
|
|
Use `nuqs` for table search params and list filters.
|
|
|
|
### Tables
|
|
|
|
Use:
|
|
|
|
- TanStack Table
|
|
- React Query
|
|
- `useDataTable`
|
|
- column definitions under the feature component tree
|
|
|
|
---
|
|
|
|
## Enterprise UI / UX Standards
|
|
|
|
Enterprise dashboard work should feel consistent, calm, scannable, and production-ready. New UI must reuse the existing dashboard shell, shadcn/ui primitives, Tailwind tokens, app icon registry, and CRM terminology rules before introducing new visual patterns.
|
|
|
|
### Visual Hierarchy
|
|
|
|
- make the primary task, primary data, and primary action clear without relying on explanatory text blocks
|
|
- use `PageContainer` for dashboard page framing and keep action placement predictable
|
|
- group related filters, metrics, tables, forms, and detail panels by task flow
|
|
- keep typography hierarchy restrained inside cards, tables, dialogs, and side panels
|
|
- avoid visual clutter, decorative-only UI, and competing emphasis
|
|
|
|
### Layout And Responsiveness
|
|
|
|
- design for desktop dashboard density while keeping mobile and tablet layouts usable
|
|
- preserve spacing consistency with existing dashboard, CRM, report, and table pages
|
|
- use stable dimensions for toolbars, action buttons, status badges, cards, table controls, and loading placeholders
|
|
- avoid layouts where text, controls, sticky panels, or table actions overlap at common breakpoints
|
|
- verify horizontal scrolling only where it is deliberate, such as wide data tables
|
|
|
|
### States And Feedback
|
|
|
|
Every user-facing data surface should account for:
|
|
|
|
- loading states, preferably skeletons that preserve layout stability
|
|
- empty states with a clear next action or explanation
|
|
- error states with actionable copy and no leaked backend internals
|
|
- disabled and pending states for actions and submit buttons
|
|
- successful mutation completion only after cache invalidation or refresh behavior is triggered
|
|
|
|
### Accessibility And Interaction
|
|
|
|
- preserve semantic HTML and accessible names for interactive controls
|
|
- keep keyboard navigation usable for menus, dialogs, forms, tabs, and tables
|
|
- ensure focus behavior is predictable when opening and closing dialogs or sheets
|
|
- maintain readable contrast in light and dark modes
|
|
- do not rely on color alone to communicate status or required action
|
|
|
|
### Enterprise Dashboard Standards
|
|
|
|
Dashboard and CRM pages should prefer:
|
|
|
|
- clear information hierarchy from summary to detail
|
|
- summary cards only when they answer a real operational question
|
|
- balanced table, filter, chart, and detail panel composition
|
|
- grouped actions with the most common action in the most predictable location
|
|
- sticky action panels or footers when they improve long-form completion
|
|
- consistent empty/loading/error states across sibling pages
|
|
- restrained whitespace that improves scanning without hiding dense operational data
|
|
|
|
Avoid:
|
|
|
|
- one-off visual systems inside dashboard pages
|
|
- oversized marketing-style hero sections for operational tools
|
|
- unnecessary nested cards
|
|
- duplicating table, filter, export, report, approval, PDF, or permission UI patterns already owned by a foundation
|
|
|
|
### Design Review Checklist
|
|
|
|
Before considering UI work complete, agents must verify:
|
|
|
|
- readability: labels, values, and actions are clear
|
|
- consistency: spacing, typography, radius, borders, icons, and controls match nearby screens
|
|
- responsiveness: mobile, tablet, and desktop layouts remain usable
|
|
- accessibility: keyboard, focus, contrast, semantics, and non-color status cues are covered
|
|
- component reuse: shared app, CRM, table, form, and foundation components were reused where appropriate
|
|
- visual balance: dense data remains scannable without decorative clutter
|
|
- state coverage: loading, empty, error, disabled, and success states are represented
|
|
- maintainability: UI logic, business rules, and server-state behavior remain in the correct layers
|
|
|
|
---
|
|
|
|
## Current Migration Guidance
|
|
|
|
Use the migrated `products` feature as the main reference for new CRUD work.
|
|
|
|
Important current status:
|
|
|
|
- `products` is migrated to Auth.js + Route Handlers + Drizzle
|
|
- `users` is migrated to Auth.js + Route Handlers + Drizzle
|
|
- new features should follow the `products` and `users` pattern, not the old mock pattern
|
|
|
|
Legacy seams still present:
|
|
|
|
- `src/constants/mock-api.ts`
|
|
- `src/constants/mock-api-users.ts`
|
|
- some placeholder pages under workspaces, billing, profile, and exclusive sections
|
|
|
|
Treat those as migration seams, not target architecture.
|
|
|
|
---
|
|
|
|
## Deployment Notes
|
|
|
|
### Production Requirements
|
|
|
|
Ensure these are set:
|
|
|
|
- `AUTH_SECRET`
|
|
- `DATABASE_URL`
|
|
- `SUPER_ADMIN_EMAIL`
|
|
- `SUPER_ADMIN_PASSWORD`
|
|
- relevant `SENTRY_*` variables if using Sentry
|
|
|
|
### Build Considerations
|
|
|
|
- app builds as standalone
|
|
- database migrations must be applied before runtime
|
|
- production secrets must not be exposed as `NEXT_PUBLIC_*`
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Auth fails in development
|
|
|
|
- verify `AUTH_SECRET`
|
|
- verify `DATABASE_URL`
|
|
- verify migrations are applied
|
|
- verify the super admin seed has run and seeded users have valid `password_hash`
|
|
|
|
### Theme not applying
|
|
|
|
- verify theme CSS import in `src/styles/theme.css`
|
|
- verify theme registration in `theme.config.ts`
|
|
|
|
### Navigation items not showing
|
|
|
|
- check `access` in `nav-config.ts`
|
|
- verify session has active organization, role, or permissions as needed
|
|
|
|
### Feature data looks stale
|
|
|
|
- verify mutation invalidates the feature query key factory
|
|
- verify filters are included in the query key
|
|
|
|
---
|
|
|
|
## External Documentation
|
|
|
|
- [Next.js App Router](https://nextjs.org/docs/app)
|
|
- [Auth.js](https://authjs.dev)
|
|
- [Drizzle ORM](https://orm.drizzle.team)
|
|
- [shadcn/ui](https://ui.shadcn.com/docs)
|
|
- [Tailwind CSS v4](https://tailwindcss.com/docs)
|
|
- [TanStack Query](https://tanstack.com/query)
|
|
- [TanStack Table](https://tanstack.com/table/latest)
|
|
- [TanStack Form](https://tanstack.com/form)
|
|
- [Sentry Next.js](https://docs.sentry.io/platforms/javascript/guides/nextjs/)
|
|
|
|
---
|
|
|
|
## Notes for AI Agents
|
|
|
|
1. Always use `cn()` for className merging.
|
|
2. Respect the feature-based structure and keep new work inside `src/features/`.
|
|
3. Server components are the default.
|
|
4. Avoid `any`; keep contracts explicit.
|
|
5. Use `PageContainer` for page headers instead of importing `Heading` directly in pages.
|
|
6. Use TanStack Form + Zod via the existing project wrappers.
|
|
7. Use icons only through `@/components/icons`.
|
|
8. For new app-owned features, prefer Route Handlers + Drizzle + React Query.
|
|
9. Never import from `@/constants/mock-api*` directly in components.
|
|
10. Use `@/auth` and `src/lib/auth/session.ts` for auth and organization checks.
|
|
11. Do not introduce new Clerk usage.
|
|
12. Treat legacy mock-backed modules as migration seams.
|
|
13. Follow the migrated `products` and `users` feature patterns when building new CRUD modules.
|
|
14. Do not re-enable self-service sign-up unless the product requirement changes explicitly.
|
|
15. For every CRUD mutation, explicitly invalidate React Query caches for list/detail/related data; never rely on passive staleness recovery.
|
|
16. Centralize query keys in each feature's `api/queries.ts`; do not scatter manual string query keys in components.
|
|
17. When deleting entities, remove stale detail queries with `removeQueries` in addition to invalidating lists.
|
|
18. If a component overrides `useMutation` callbacks on top of a shared mutation config, preserve or explicitly call the shared invalidation behavior before closing UI.
|
|
19. After successful create/update/delete, sheets, dialogs, and destructive modals must close only after cache invalidation has been triggered and the UI can refresh from fresh data.
|
|
20. Review `docs/standards/**`, relevant `docs/adr/**`, `docs/business/**`, and `docs/security/**` before implementing non-trivial changes.
|
|
21. Review related completed task notes in `docs/standards/task-catalog.md` and `docs/implementation/**` before implementing non-trivial changes.
|
|
22. Reuse foundations under `src/features/foundation/**` and `src/features/crm/**` before introducing new services, routes, permissions, exports, or datasets.
|
|
23. Do not create duplicate report/export/PDF/approval/security plumbing when a project foundation already exists.
|
|
24. CRM authorization must flow through resolved access helpers such as `resolveCrmMembershipAccess()`, `buildCrmSecurityContext()`, or report-context builders; do not authorize with raw role strings alone.
|
|
|
|
### AI Self Review Checklist
|
|
|
|
Before declaring implementation complete, verify:
|
|
|
|
- architecture follows the project standards and approved foundations
|
|
- historical review was completed for non-trivial work
|
|
- existing services, APIs, components, query keys, mutations, and UI shells were reused or extension rationale is documented
|
|
- no duplicated business logic, permission checks, export/report flows, PDF flows, approval flows, or audit plumbing was introduced
|
|
- server-side auth, organization access, CRM scope, pricing visibility, and audit behavior are enforced where applicable
|
|
- route handlers remain thin and business logic remains in feature/foundation services
|
|
- React Query invalidation covers list, detail, child-resource, counts, previews, approval panels, and related cross-feature data affected by mutations
|
|
- UI is consistent with dashboard and CRM standards
|
|
- loading, empty, error, disabled, pending, and success states are handled where user-facing behavior requires them
|
|
- accessibility, keyboard navigation, focus behavior, contrast, and responsive layout were considered
|
|
- date/time rendering uses `src/lib/date-format.ts` and remains deterministic
|
|
- code remains maintainable, scoped, and free of unrelated rewrites
|
|
- relevant lint, typecheck, tests, build, or manual checks were run or explicitly noted as not run
|
|
|
|
### Future Compatibility
|
|
|
|
This guide is AI-agent agnostic. It applies to Codex, Claude Code, Gemini CLI, Cursor, Windsurf, Cline, and future coding assistants.
|
|
|
|
Agents may use their own planning, tool, or skill systems, but must preserve these repository priorities:
|
|
|
|
1. project governance and standards
|
|
2. accepted ADRs and business/security documents
|
|
3. existing foundations and feature implementations
|
|
4. local code patterns
|
|
5. external framework or assistant-specific recommendations
|
|
|
|
Before implementing any task, review:
|
|
- AGENTS.md
|
|
- docs/standards/*
|
|
- docs/standards/task-catalog.md
|
|
- related ADRs
|
|
- related completed task documents
|
|
|
|
Implementation without review is prohibited.
|