<!-- BEGIN:nextjs-agent-rules -->

# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.

# TypeScript Standards

- **Global Type Definitions**: All shared `type`, `interface`, and `enum` definitions must be placed in the `src/types/` directory.
- **Naming Convention**: Use the `.d.ts` extension (e.g., `src/types/auth.d.ts`).
- **No Inline Types**: Avoid defining complex types or interfaces inside component or service files; export them from the central types directory instead.
- **TypeScript Verification**: ALWAYS use `npm run type-check` to verify TypeScript compilation. Do NOT use `npx tsc --noEmit` directly.

## Token Expiration & Logout

- **Server-Side Logout**: Use `serverLogout()` from `@/lib/server-logout` to clear cookies and redirect
- **Client-Side Logout**: Use `signOut()` from `next-auth/react` with `redirect: false` to avoid "window is not defined" errors
- **Cookie Clearing**: Clear all `next-auth.*` cookies on token expiration (check for `tokenExpiry` in JWT callback)
- **Auto-Redirect**: Middleware (`proxy.ts`) checks `tokenExpiry` and redirects expired tokens to `/login?redirected=true`
- **Login Page Cleanup**: Login page auto-clears cookies when accessed with `?loggedout=true` or `?redirected=true` params

## Server Actions & Cache Invalidation

- **Use `revalidateTag()` not `revalidatePath()`** - Granular cache invalidation is more efficient than full-page revalidation
- **Cache tags defined in**: `app/actions/cache-tags.ts` - Use centralized `CACHE_TAGS` constants
- **Cache profile**: Always pass `DEFAULT_CACHE_PROFILE` as second argument to `revalidateTag()` (Next.js 16+ requirement)
- **Tag strategy**:
  - `employees` - Employee list, individual employee data
  - `attendance` - Attendance records, check-in/out
  - `leaves` - Leave requests, balances
  - `biometric` - Biometric devices, logs
  - `dashboard` - Dashboard stats (invalidated when any domain changes)
- **Cross-domain invalidation**: When action affects multiple domains (e.g., biometric sync affects attendance), revalidate all relevant tags
- **Fetch functions**: Do NOT use `revalidateTag` in fetch-only actions (they read cached data)
- **Mutation functions**: ALWAYS use `revalidateTag` after successful mutations

## Development Workflow Rules

- **TypeScript Verification**: ALWAYS use `npm run type-check` to verify changes
- **DO NOT run `npm run build`** after every change - it's slow and unnecessary for development
- **Test in dev mode**: Run `npm start` or `npm run dev` and verify in browser
- **Only build for production**: Run `npm run build` ONLY when preparing for deployment or when explicitly requested

## HeroUI Table Best Practices

- **Always guard `items` prop**: Use `(items || []).filter(i => i && i.id)` to prevent "cannot be rendered outside a collection" error
- **Never return `null` from Table.Body render function** - filter invalid items BEFORE passing to `items`
- **Always provide valid `key`**: Ensure each row has a unique, non-null `key` prop
- **Empty state handling**: Check `(items || []).length === 0` and show custom empty state UI instead of empty Table
- **ToastProvider script warning**: Wrap `<ToastProvider />` in a client-only component to avoid "script tag" warnings during SSR

## Server Action Error Handling

- **Business validation errors (400, 409)**: Return `{ success: false, error: message }` instead of throwing to avoid Next.js server error logs
- **Example pattern for actions with expected validation errors**:
  ```typescript
  export async function someAction() {
    try {
      // ... action logic
      return { success: true, data: result };
    } catch (error: any) {
      const message =
        error?.response?.data?.message || error?.message || "Action failed";
      return { success: false, error: message };
    }
  }
  ```
- **Client-side handling**: Check `result.success` and throw error in client component for toast display
- **Never use `redirect()` in server actions called from client components** - Use `window.location.href` in client instead

- Prevent NaN Display: Ensure no value in the UI renders as NaN. The backend must return consistent null/default values, and the frontend must implement robust validation or fallback values (e.g., 0 or -) for any missing or invalid data.
- Accessibility (ARIA): Always provide an `aria-label` or `aria-labelledby` prop for all interactive elements (Buttons, Inputs, Selects, Tables, Table.Column) especially when they are icon-only. Tables and Columns MUST have these to ensure screen reader compatibility and prevent console warnings.
- PressResponder (HeroUI): Avoid using non-button/non-pressable elements as children of components that inject click handlers (like `ButtonGroup.Separator` inside a `Button`). This causes "PressResponder was rendered without a pressable child" warnings. Use standard `Separator` or keep interactive children wrapped strictly in valid `Button` components.
- No Nested Buttons in Triggers (HeroUI): Components like `Dropdown.Trigger`, `Popover.Trigger`, or `Tooltip.Trigger` often already render a `<button>` or inject click behaviors. **NEVER** place a `<Button>` component inside these triggers. This results in a `<button>` inside a `<button>`, which is invalid HTML and causes a full Client Hydration Failure (leading to UI flashes). Instead, use a `div` or `span` with `role="button"` and manual styling.
- Specific Transitions Only: **NEVER** use `transition-all`. It causes a noticeable delay/fade when toggling light/dark modes because the browser tries to transition the background-color and text-color. Always use specific properties like `transition-[transform,opacity,width,box-shadow]` to keep interactions smooth while ensuring theme switches are instantaneous.
<!-- END:nextjs-agent-rules -->
