DEV Community

Moukie
Moukie

Posted on

Stop explaining your stack to Cursor in every new chat (use .cursor/rules instead)

You know the pattern.

You open a new Cursor chat. You type "fix this bug". Cursor gives you JavaScript with no types, useEffect where a Server Component would work, and imports from next/router instead of next/navigation.

So you write: "actually use TypeScript strict mode, we're on App Router, and use next/navigation not next/router".

It fixes it. Next session: same explanation.

There's a better way.


.cursor/rules/ — persistent context for every chat

Cursor reads every .md file in your .cursor/rules/ folder at the start of each chat. It's like a system prompt, but per-project, and you write it once.

mkdir -p .cursor/rules
Enter fullscreen mode Exit fullscreen mode

Now create .cursor/rules/nextjs.md:

## Next.js 14 App Router — Rules

- Server Components by default. Only add "use client" for interactivity or hooks.
- Named exports everywhere except page.tsx and layout.tsx.
- Use next/navigation (not next/router): useRouter, usePathname, redirect(), notFound().
- TypeScript strict mode. No `any`. Use `unknown` and narrow.
- Fetch in Server Components when possible — no useEffect + fetch for data.
- Tailwind: mobile-first, use cn() for conditional classes.
Enter fullscreen mode Exit fullscreen mode

Open a new chat. Ask Cursor to "add a server action to fetch the current user". It'll do it correctly — typed, using auth() server-side, no client component — without you explaining anything.


Add more rules per concern

Keep each file focused on one topic:

.cursor/rules/stripe.md

## Stripe — Rules

- Read raw body with req.text() before signature verification — never parse as JSON first.
- Verify: stripe.webhooks.constructEvent(body, signature, STRIPE_WEBHOOK_SECRET).
- Handle webhooks idempotently — they can fire multiple times.
- Attach userId in metadata on checkout session AND subscription_data.metadata.
- Never trust amount from client — verify via webhook.
Enter fullscreen mode Exit fullscreen mode

.cursor/rules/validation.md

## Zod Validation — Rules

- Validate all external input at API boundaries.
- Use z.safeParse() when input may be invalid.
- Infer TypeScript types: type User = z.infer<typeof UserSchema>
- Validate env vars at startup — crash early if misconfigured.
- Never use z.any().
Enter fullscreen mode Exit fullscreen mode

.cursor/rules/security.md

## Security — Rules

- Verify auth server-side on every protected route — never trust client state.
- Check ownership on resource operations: if (post.authorId !== userId) throw Forbidden.
- Use parameterized queries — never string concatenation.
- Rate limit: 10 req/min per IP on auth endpoints.
- Security headers: X-Content-Type-Options, X-Frame-Options, CSP.
Enter fullscreen mode Exit fullscreen mode

Rules vs CLAUDE.md

If you use Claude Code alongside Cursor:

  • .cursor/rules/ → Cursor reads these
  • CLAUDE.md → Claude Code reads this

They serve similar purposes but different tools. Keep them in sync.


What to put in rules

Good rules are actionable and specific:

✅ "Use z.safeParse() when input may be invalid"
✅ "Server Components by default — only add 'use client' when needed"
✅ "Validate env vars at startup with Zod — crash early"

Bad rules are vague:

❌ "Write clean code"
❌ "Follow best practices"
❌ "Be careful with security"

The test: could Cursor misinterpret this? If yes, make it more specific.


My full set of rules

I use 25 rule files across my projects — one per topic:

  • Next.js 14 App Router
  • React + TanStack Query + Zustand
  • Python FastAPI + Pydantic v2
  • Go idioms
  • Prisma + PostgreSQL (query patterns, indexing)
  • Redis caching
  • Stripe webhooks
  • Auth.js v5
  • Tailwind + shadcn/ui
  • Anthropic Claude API + OpenAI streaming
  • Docker multi-stage builds
  • Vercel deployment
  • OWASP web security
  • Vitest + React Testing Library
  • Conventional Commits + Git workflow
  • Zod validation
  • REST API design

I packaged them up: Cursor Rules & AI Coding Config Pack — $19 on Gumroad

Includes CLAUDE.md templates for Claude Code users too.


What rules do you use in your projects? Drop them in the comments.

Top comments (0)