These rules describe how to work in this repo using Cursor: file layout, React Server Components boundaries, where actions/forms live, and UI/data patterns.
## Cursor rules for react-router-dashboard-saas-template
These rules describe how to work in this repo using Cursor: file layout, React Server Components boundaries, where actions/forms live, and UI/data patterns.
### Stack overview
- React 19 + React Router 7 (RSC enabled via `@vitejs/plugin-rsc`)
- Server rendering entry at `src/entry.rsc.tsx`; SSR HTML generated by `src/entry.ssr.tsx`
- Tailwind CSS v4 + daisyUI v5 (semantic component classes)
- Drizzle ORM (PostgreSQL) with `drizzle-kit` migrations
- Conform (`@conform-to/react`) + `zod/v4` for form validation
- Session and request-scoped context via `AsyncLocalStorage`
### Environment
- Required env: `DATABASE_URL`, `SESSION_SECRET`
- Start: `pnpm dev`. Build: `pnpm build`. Typecheck: `pnpm typecheck`. DB: `pnpm db`, `pnpm db:generate`, `pnpm db:migrate`, `pnpm db:studio`.
### Directory layout and conventions
- `src/routes/`
- Each route folder typically contains:
- `route.tsx` → React Server Component (RSC) entry for the route.
- `client.tsx` → co-located Client Components for that route ("islands"). Use `"use client"` pragma.
- `client-on.ts` → small client helpers for imperative UI interactions (e.g., opening modals).
- Optional `handle.ts` (see `src/routes/app/handle.ts`) to expose server-only pieces via the `createHandle` pattern.
- Root shells:
- `src/routes/root/route.tsx` (layout shell + error boundary export from client)
- `src/routes/marketing/route.tsx` (public shell)
- `src/routes/app/route.tsx` (authenticated app shell)
- `src/actions/<domain>/`
- `actions.ts` → server actions (must start with `"use server"`).
- `schema.ts` → `zod/v4` schemas used by the actions and forms.
- Existing domains: `auth`, `organization`, `invitation`, `profile`.
- `src/components/` → shared components across routes.
- `@/components/form` → Conform + zod v4 opinionated wrappers (`useForm`, `Form`, `Input`, etc.).
- `src/components/ui/` → low-level UI primitives (`card`, `modal`, etc.).
- `src/db/`
- `schema.ts` → Drizzle table definitions.
- `queries/*` and `mutations/*` → data access layer separated by read/write.
- `index.ts` → `getDb()` pool + drizzle instance (reused via global).
- `src/lib/`
- `session.ts` → cookie session with ALS; use `getSession()`, `destroySession()`.
- `auth.ts` → `getUser()`, `requireUser()`, and route `unstable_middleware` helpers.
- `cache.ts` → response caching and dataloader batching.
### React Server Components model
- Route files (`route.tsx`) are server by default. Do data fetching here (DB, session, etc.). Avoid DB access in client components.
- Client components must opt-in with `"use client"` and should live in `client.tsx` (or adjacent files) within the route directory.
- Pass server-only values to client via props; avoid leaking server functions or DB clients.
- Use the `createHandle`/`getServerHandle` pattern when a route needs to expose server-only components to a parent shell (see `src/routes/app/handle.ts`).
- Route middleware: export `unstable_middleware` from the server route module to protect or redirect (see `redirectIfLoggedInMiddleware`, `requireUserMiddleware`).
- Caching: call `cacheRoute()` at the top of server route components when appropriate to set CDN/edge cache headers.
### Forms + actions pattern (Conform + zod/v4)
- Always use `zod/v4` and `@conform-to/zod/v4` to match the configured version.
- Example imports:
- `import { z } from "zod/v4"`
- `import { parseWithZod } from "@conform-to/zod/v4"`
- Server action signature:
- In `src/actions/<domain>/actions.ts` define actions with `"use server"` and the shape
`(prev: SubmissionResult | undefined, formData: FormData) => Promise<SubmissionResult>`.
- Parse on the server: `const submission = parseWithZod(formData, { schema })`.
- On validation failure: `return submission.reply({ ...options })`.
- On success: perform side effects, optionally `redirect(...)`, and return `submission.reply({ resetForm: boolean })`.
- Use `requireUser()` inside actions that need auth.
- Client form usage (see `src/routes/marketing/login/client.tsx`):
- Wire the server action using React 19’s `useActionState`:
`const [lastResult, action, pending] = useActionState(serverAction, undefined)`.
- Initialize Conform via our wrapper: `const [form, fields] = useForm({ action, lastResult, schema })`.
- Render with `<Form action={action} form={form}>` and use `<Input field={fields.email} ... />` etc.
- Use `<FormErrors form={form} />` and `<FormSuccessMessage lastResult={lastResult}>...</FormSuccessMessage>`.
- Keep redirect/query state in hidden inputs when needed (e.g., `redirectTo`).
- Where to put schemas:
- Define schemas in `src/actions/<domain>/schema.ts` and import into both the action and the client form.
- Naming:
- Existing naming is mixed (`login`, `signup`, `createOrganizationAction`, `updateName`, etc.). Prefer descriptive verbs; suffix with `Action` when it clarifies intent, but keep consistency within a domain.
### Data access (Drizzle)
- Define tables in `src/db/schema.ts`.
- Get a DB instance via `getDb()`; do not instantiate pools in actions/components.
- Separate reads/writes: put read functions in `src/db/queries/*` and mutations in `src/db/mutations/*`.
- Keep transactions and authorization checks in server actions or server route loaders (not in client).
- Generate and run migrations with drizzle-kit scripts.
### Auth and session
- Use `getUser()` to read current user (may be `undefined`). Use `requireUser()` when user must exist.
- For route-level protection, add `unstable_middleware = [requireUserMiddleware]` to `route.tsx`.
- Login/signup set the session via `getSession().set("user", { id })`; logout destroys it via `destroySession()`.
- Redirect using React Router’s `redirect()` only from server contexts.
### Routing specifics
- The route shells use daisyUI and Tailwind for layout (`navbar`, `drawer`, etc.).
- The marketing shell (`src/routes/marketing/route.tsx`) shows how to open auth modals from the navbar using `client-on.ts` helpers.
- The app shell (`src/routes/app/route.tsx`) demonstrates co-locating a server-provided `SidebarContent` via the handle API and rendering notifications fed by server data.
### UI and styling
- Tailwind v4 with daisyUI v5 (semantic-first):
- Prefer daisyUI component classes (e.g., `btn`, `input`, `card`) and semantic colors (`primary`, `base-100`, etc.).
- Use container pattern `max-w-screen-xl mx-auto px-4` for page shells.
- Use responsive helpers (`sm:menu-horizontal`, `lg:drawer-open`).
- Shared UI primitives live under `src/components/ui/*`. Add new ones here if broadly reusable. Route-specific UI belongs next to the route in `client.tsx` or sibling files.
### Adding a new feature (checklist)
1. Routing: create a new folder in `src/routes/...`, add `route.tsx` (server). If interactive UI is needed, add `client.tsx` with `"use client"` and render it from the server route.
2. Data: add query/mutation helpers in `src/db/queries/*` / `src/db/mutations/*` as needed. Reuse `getDb()`.
3. Actions: create `src/actions/<domain>/{schema.ts,actions.ts}` with zod v4 schemas and server actions.
4. Form: in the route’s `client.tsx`, use `useActionState`, `useForm({ action, lastResult, schema })`, and `<Form>`/`<Input>` components.
5. Auth: add `unstable_middleware` to routes requiring auth, and call `requireUser()` inside actions.
6. Caching: call `cacheRoute()` in server `route.tsx` if the page can be cached; avoid for highly dynamic/authenticated content.
7. Styling: use daisyUI components and semantic colors; keep shared primitives in `src/components/ui/*`.
### TypeScript and code style
- TS is strict; avoid `any`. Export explicit types for public helpers.
- Use the `@/*` path alias from `tsconfig.json`.
- Keep functions small and descriptive; prefer early returns; handle errors close to where they occur.
### Do’s and Don’ts
- Do parse and validate all form input on the server with zod v4.
- Do keep business logic in server actions or server route modules, not in client components.
- Don’t mutate session after response generation; use helpers from `src/lib/session.ts` within the server request lifecycle.
- Don’t access the DB from client code.
- Don’t bypass Conform’s `submission.reply` pattern; it powers `lastResult` and error display.
Comprehensive .cursorrules file for Next.js 15 App Router projects with TypeScript, enforcing server components by default, proper use of "use client" directive, and App Router conventions.
Cursor rules for Python FastAPI projects enforcing async patterns, Pydantic v2 models, dependency injection, and proper error handling.
Rules for consistent React component development with TypeScript interfaces, proper hook patterns, and component composition.
Rules optimizing Cursor Agent mode behavior including multi-file editing context, session management, and autonomous task completion patterns.
Cursor rules for projects using Tailwind CSS with shadcn/ui component library, enforcing consistent utility class usage and component patterns.
Rules for Go backend services enforcing idiomatic Go patterns, proper error handling, and clean architecture conventions.