Files
fluxent-web/AGENTS.md
T

3.9 KiB

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.

Fluxent Web

Commands

  • Use pnpm. Checks: pnpm lint, pnpm typecheck, pnpm build; there is no test script. pnpm format formats all **/*.{ts,tsx} with Prettier and the Tailwind plugin (2 spaces, double quotes, no semicolons, LF, 80 columns).
  • Add shadcn primitives only with pnpm dlx shadcn@latest add <component> --yes; read their API first with pnpm dlx shadcn@latest docs <component>.
  • This is Next.js 16.2.6. Read the relevant guide under node_modules/next/dist/docs/ before changing Next.js APIs or conventions; do not assume older Next.js patterns.

App And Auth

  • App Router entry points live in app/. Each authenticated page validates auth() and composes SidebarProvider, AppSidebar, and SidebarInset; the proxy check does not replace server-side validation.
  • Next.js 16 uses proxy.ts, not middleware.ts. Keep auth configuration imported by proxy.ts edge-safe; database and password code belongs in lib/auth/index.ts.
  • Public routes are /login, /register, and /api/auth/*; other routes are protected. OIDC registers only when AUTH_OIDC_ENABLED=true and issuer/client ID are configured.
  • Sidebar active state comes from usePathname() (/ exact, child routes prefix). Add a navigation item only with its route.

Database And Ledger

  • PostgreSQL uses Drizzle + postgres; schema source of truth is lib/db/schema.ts. drizzle.config.ts explicitly loads .env.local. For local DB use pnpm db:up (Compose waits for health), pnpm db:down (keeps the named volume), and pnpm db:logs. Compose binds only to 127.0.0.1:5432; Postgres data mounts at /var/lib/postgresql for the current PostgreSQL image layout. docker compose down -v permanently deletes local DB data.
  • Apply schema changes with pnpm drizzle-kit push --force. Never run pnpm tsx lib/db/reset.ts unless explicitly instructed; it drops application tables.
  • Scope business-data queries and mutations by the authenticated session.user.id, exclude soft-deleted rows with isNull(table.deletedAt), and verify referenced accounts/channels belong to that user.
  • Draft/imported transactions belong in transactions_dirty. cleanseTransactionsAction in lib/actions/bookkeeping.ts validates the whole batch and atomically moves valid rows to transactions.
  • /import currently accepts CCBA CSV only (PDF conversion is not implemented); its server action stages rows in transactions_dirty and resolves account-to-channel mappings.
  • Card brands are stored as lowercase keys. Use normalizeCardBrand() from lib/payment/card-brand.ts and local SVGs under /payment-logos/.

UI And Copy

  • UI stack: shadcn base-nova on @base-ui/react, Lucide, Tailwind v4, and CSS variables in app/globals.css. components/ui/ contains shadcn CLI-managed primitives; the reusable responsive grid list is components/data-list.tsx.
  • Base UI: keep SelectItem inside SelectGroup; give SelectValue plain-text children or explicit formatting when item content is complex. For object-valued Combobox items, provide both itemToStringValue and itemToStringLabel.
  • Forms use FieldGroup, Field, and FieldLabel; use FieldSet/FieldLegend only for meaningful groups. Dialogs use DialogHeader, content/form, and DialogFooter directly inside DialogContent.
  • Use gap-*, not space-x-*/space-y-*; use semantic tokens, not hardcoded palettes or manual dark: overrides. Icon buttons use data-icon="inline-start" or data-icon="inline-end".
  • Product-facing copy is Chinese. Do not add English parentheticals to labels, menus, options, or headings; preserve user-entered values and standard tokens such as CNY and Visa.