Cursor-rules
PromptBeginner5 minmarkdown
.cursorrules
.llmrules
0
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.
Sign in to like and favorite skills
.llmrules
Code Style and Structure
Here are some pieces of information you need to know about this project:
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.
@vitejs/plugin-rsc)src/entry.rsc.tsx; SSR HTML generated by src/entry.ssr.tsxdrizzle-kit migrations@conform-to/react) + zod/v4 for form validationAsyncLocalStorageDATABASE_URL, SESSION_SECRETpnpm dev. Build: pnpm build. Typecheck: pnpm typecheck. DB: pnpm db, pnpm db:generate, pnpm db:migrate, pnpm db:studio.src/routes/
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).handle.ts (see src/routes/app/handle.ts) to expose server-only pieces via the createHandle pattern.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.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.route.tsx) are server by default. Do data fetching here (DB, session, etc.). Avoid DB access in client components."use client" and should live in client.tsx (or adjacent files) within the route directory.createHandle/getServerHandle pattern when a route needs to expose server-only components to a parent shell (see src/routes/app/handle.ts).unstable_middleware from the server route module to protect or redirect (see redirectIfLoggedInMiddleware, requireUserMiddleware).cacheRoute() at the top of server route components when appropriate to set CDN/edge cache headers.zod/v4 and @conform-to/zod/v4 to match the configured version.
import { z } from "zod/v4"import { parseWithZod } from "@conform-to/zod/v4"src/actions/<domain>/actions.ts define actions with "use server" and the shape
(prev: SubmissionResult | undefined, formData: FormData) => Promise<SubmissionResult>.const submission = parseWithZod(formData, { schema }).return submission.reply({ ...options }).redirect(...), and return submission.reply({ resetForm: boolean }).requireUser() inside actions that need auth.src/routes/marketing/login/client.tsx):
useActionState:
const [lastResult, action, pending] = useActionState(serverAction, undefined).const [form, fields] = useForm({ action, lastResult, schema }).<Form action={action} form={form}> and use <Input field={fields.email} ... /> etc.<FormErrors form={form} /> and <FormSuccessMessage lastResult={lastResult}>...</FormSuccessMessage>.redirectTo).src/actions/<domain>/schema.ts and import into both the action and the client form.login, signup, createOrganizationAction, updateName, etc.). Prefer descriptive verbs; suffix with Action when it clarifies intent, but keep consistency within a domain.src/db/schema.ts.getDb(); do not instantiate pools in actions/components.src/db/queries/* and mutations in src/db/mutations/*.getUser() to read current user (may be undefined). Use requireUser() when user must exist.unstable_middleware = [requireUserMiddleware] to route.tsx.getSession().set("user", { id }); logout destroys it via destroySession().redirect() only from server contexts.navbar, drawer, etc.).src/routes/marketing/route.tsx) shows how to open auth modals from the navbar using client-on.ts helpers.src/routes/app/route.tsx) demonstrates co-locating a server-provided SidebarContent via the handle API and rendering notifications fed by server data.btn, input, card) and semantic colors (primary, base-100, etc.).max-w-screen-xl mx-auto px-4 for page shells.sm:menu-horizontal, lg:drawer-open).src/components/ui/*. Add new ones here if broadly reusable. Route-specific UI belongs next to the route in client.tsx or sibling files.src/routes/..., add route.tsx (server). If interactive UI is needed, add client.tsx with "use client" and render it from the server route.src/db/queries/* / src/db/mutations/* as needed. Reuse getDb().src/actions/<domain>/{schema.ts,actions.ts} with zod v4 schemas and server actions.client.tsx, use useActionState, useForm({ action, lastResult, schema }), and <Form>/<Input> components.unstable_middleware to routes requiring auth, and call requireUser() inside actions.cacheRoute() in server route.tsx if the page can be cached; avoid for highly dynamic/authenticated content.src/components/ui/*.any. Export explicit types for public helpers.@/* path alias from tsconfig.json.src/lib/session.ts within the server request lifecycle.submission.reply pattern; it powers lastResult and error display.