What Are Cursor Rules and Why They Matter
Cursor rules are instructions stored in a .cursorrules file at your project root. They tell Cursor's AI exactly how to write code for your specific project โ which frameworks to use, which patterns to follow, which anti-patterns to avoid, and which conventions to enforce.
Without rules, Cursor guesses. It might generate class components in your hooks-only React project, use var in your TypeScript codebase, or reach for requests when you're an httpx shop. Rules eliminate that guesswork.
Think of it this way: Your .cursorrules file is like onboarding docs for an AI pair programmer. The better your onboarding, the less time you spend correcting its output. This is the foundation of a solid vibe coding setup.
The difference between a good and bad cursor rules file is the difference between an AI that writes code your way versus one that writes generic Stack Overflow answers. The best cursor rules are specific, opinionated, and framework-aware.
How to Set Up .cursorrules in Your Project
Setup takes 30 seconds:
- 1. Create a file called .cursorrules in your project root (same level as package.json, Cargo.toml, or pyproject.toml)
- 2. Paste in the rules for your framework (grab them from below)
- 3. Commit it to your repo so the whole team benefits
# From your project root
touch .cursorrules
# Or if you're using the newer Cursor project rules directory:
mkdir -p .cursor/rules
touch .cursor/rules/main.mdc
โ ๏ธ .cursorrules vs .cursor/rules/ โ Cursor supports both. The .cursorrules file at root is the classic approach and works everywhere. The .cursor/rules/ directory lets you split rules into multiple files with metadata headers. Both work โ pick one and stick with it.
Best Practices for Writing Effective Rules
After testing hundreds of .cursorrules configurations across real projects, here's what actually works:
๐ฏ Be Specific, Not Vague
"Write clean code" is useless. "Use named exports, prefer const arrow functions for components, and co-locate tests in __tests__/" is actionable.
โ Bad
"Follow best practices"
โ Good
"Use Zod for all runtime validation. Never use as type assertions."
๐ Declare Your Stack Upfront
Start with what you're using. Framework, language version, key libraries, package manager. This single block eliminates 80% of wrong suggestions.
๐ซ Include Anti-Patterns
Tell the AI what not to do. "Never use any", "Don't create god components over 200 lines", "Never use datetime โ always pendulum". Exclusions are just as valuable as inclusions.
๐ Describe Your File Structure
If you have conventions about where things go โ routes in app/, utils in lib/, types in types/ โ say so. The AI will follow your architecture instead of inventing its own.
โ๏ธ Keep It Under 500 Lines
Rules get injected into every prompt. Massive files eat your context window. Be concise. Prioritize the rules that save you the most correction time.
Top 10 Cursor Rules (Copy-Paste Ready)
Every rule below is battle-tested, opinionated, and ready to drop into your project. Click the copy button and go.
React / Next.js
For Next.js 14+ App Router projects with TypeScript. Opinionated about Server Components, data fetching, and file structure.
You are an expert React/Next.js developer.
# Stack
- Next.js 14+ (App Router only, no Pages Router)
- React 18+ with Server Components by default
- TypeScript in strict mode
- Tailwind CSS for styling (no CSS modules, no styled-components)
- Zustand for client state, TanStack Query for server state
- Zod for validation, next-safe-action for server actions
# Architecture
- Default to Server Components. Only add "use client" when you need interactivity, browser APIs, or hooks.
- Use the app/ directory. Route groups with (parentheses) for organization.
- Co-locate components with their routes: app/dashboard/_components/
- Shared components go in components/ui/ (primitives) and components/ (composed)
- All data fetching happens in Server Components or server actions. Never fetch in client components directly.
# Patterns
- Named exports only (no default exports except for pages/layouts)
- Use `const ComponentName = () => {}` arrow function syntax for components
- Props interfaces named `{ComponentName}Props`
- Server actions in separate files: app/dashboard/actions.ts
- Use `loading.tsx` and `error.tsx` for each route segment
- Prefer parallel routes and intercepting routes over client-side modals
# Data & State
- Server state: fetch in Server Components with cache/revalidate, or use server actions
- Client state: Zustand stores in stores/ directory, one store per domain
- Form state: useActionState + server actions, not useState + API routes
- URL state: use nuqs for search params as state
# Anti-patterns (NEVER do these)
- No `"use client"` at the top of page.tsx files
- No useEffect for data fetching
- No barrel files (index.ts re-exports)
- No default exports (except pages, layouts, route handlers)
- No inline styles or CSS-in-JS
- No `any` type โ use `unknown` and narrow
- No React.FC โ just type props directly
- No class components
TypeScript (Strict)
Framework-agnostic TypeScript rules. Enforce strict types, modern patterns, and zero any tolerance.
You are an expert TypeScript developer who writes precise, type-safe code.
# TypeScript Configuration
- Strict mode is ON (`strict: true` in tsconfig)
- Target: ES2022+, module: NodeNext or Bundler
- Use `satisfies` operator over `as` for type-safe assignments
- Use `const` assertions for literal types
# Type Patterns
- Prefer `interface` for object shapes that may be extended
- Use `type` for unions, intersections, mapped types, and utility types
- Name types/interfaces in PascalCase, prefix with context: `UserProfile`, `ApiResponse<T>`
- Generic constraints: always constrain with `extends` โ never naked generics
- Use discriminated unions for state machines and result types:
`type Result<T> = { ok: true; data: T } | { ok: false; error: Error }`
# Functions
- Explicit return types on exported functions (inference OK for internal/private)
- Use overloads sparingly โ prefer unions and generics
- Default to `readonly` params for arrays and objects
- Use `unknown` over `any` โ always narrow with type guards
# Error Handling
- Use typed Result pattern instead of throwing: `Result<T, E>`
- When using try/catch, catch `unknown` and narrow
- Custom error classes extending Error with a `code` discriminant
# Validation
- Runtime validation: Zod schemas that infer TypeScript types
- `z.infer<typeof schema>` for all external data (API responses, form data, env vars)
- Never trust external data โ validate at the boundary
# Anti-patterns (NEVER do these)
- No `any` โ this is non-negotiable
- No `as` type assertions (use `satisfies` or type guards)
- No `@ts-ignore` or `@ts-expect-error` without a linked issue
- No `enum` โ use `as const` objects or union types
- No `namespace` โ use ES modules
- No non-null assertions (`!`) โ handle null/undefined properly
- No implicit `any` in callbacks โ type all parameters
Python
Modern Python 3.12+ with type hints, Pydantic, and a strong opinion on project structure. Great for cursor rules for Python projects.
You are an expert Python developer who writes modern, type-safe Python.
# Stack
- Python 3.12+
- Package manager: uv (not pip, not poetry)
- Type hints on ALL functions (params + return types)
- Pydantic v2 for data validation and settings
- Ruff for linting and formatting (not black, not flake8)
# Project Structure
src/
{package_name}/
__init__.py
models/ # Pydantic models
services/ # Business logic
api/ # Route handlers
core/ # Config, dependencies, exceptions
utils/ # Pure utility functions
tests/
conftest.py
test_{module}.py
# Patterns
- Use `from __future__ import annotations` in every file
- Prefer `dataclass` for simple data containers, `BaseModel` for validation
- Use `Annotated` types for dependency injection and validation:
`Annotated[str, Field(min_length=1)]`
- Async by default for I/O operations
- Use `pathlib.Path` over `os.path` โ always
- Use f-strings for formatting (no .format(), no % formatting)
- Use `logging` with structlog, never print()
- Comprehensions over map/filter when readable
# Error Handling
- Custom exception hierarchy: `class AppError(Exception): ...`
- Specific exceptions, not bare `except Exception`
- Use `contextlib.suppress` for expected exceptions
- Never silence errors โ log them at minimum
# Type Hints
- Use `X | None` instead of `Optional[X]`
- Use `list[str]` not `List[str]` (lowercase generics)
- Return types required on all public functions
- Use `TypeVar` and `Protocol` for generic/structural patterns
- Use `@overload` for functions with different return types
# Anti-patterns (NEVER do these)
- No `requests` library โ use `httpx`
- No `datetime` module โ use `pendulum` or `arrow`
- No mutable default arguments
- No wildcard imports (`from x import *`)
- No global state / module-level mutable variables
- No bare `except:` or `except Exception:`
- No relative imports beyond one level
- No print() for logging
Rust
Idiomatic Rust with strong opinions on error handling, ownership patterns, and crate choices.
You are an expert Rust developer who writes idiomatic, safe, and performant code.
# Toolchain
- Rust 2024 edition
- Cargo workspaces for multi-crate projects
- clippy with pedantic lints enabled
- rustfmt with default config
# Error Handling
- Use `thiserror` for library error types, `anyhow` for application code
- Define domain-specific error enums:
`#[derive(Debug, thiserror::Error)] enum AppError { ... }`
- Propagate errors with `?` โ avoid `.unwrap()` in library code
- `.unwrap()` / `.expect()` only in tests and when logically infallible
- Use `Result<T, E>` as return type, not panics
# Patterns
- Prefer `impl Trait` in function params over generic bounds where possible
- Use the builder pattern for complex struct construction
- Derive common traits: `Debug, Clone, PartialEq` minimum for public types
- Use `#[must_use]` on functions that return important values
- Prefer iterators and combinators over manual loops
- Use `Cow<'_, str>` for functions that may or may not allocate
# Concurrency
- Use `tokio` for async runtime (multi-threaded by default)
- Prefer channels (`tokio::sync::mpsc`) over shared state
- Use `Arc<Mutex<T>>` sparingly โ if you need it, consider a channel instead
- Async functions for I/O, sync for computation
# Structure
src/
lib.rs # Public API surface
main.rs # Binary entry point
error.rs # Error types
config.rs # Configuration
models/ # Domain types
handlers/ # Request handlers
services/ # Business logic
# Key Crates
- HTTP: `axum` (not actix-web, not rocket)
- Serialization: `serde` + `serde_json`
- Database: `sqlx` (compile-time checked queries)
- CLI: `clap` with derive macro
- Logging: `tracing` (not `log`)
# Anti-patterns (NEVER do these)
- No `.unwrap()` in production paths
- No `clone()` to satisfy the borrow checker without considering alternatives
- No `Box<dyn Error>` as the primary error type โ use typed errors
- No `unsafe` without a `// SAFETY:` comment explaining the invariant
- No `String` where `&str` suffices in function params
- No manual `impl Display` when `thiserror` derives it
Go
Idiomatic Go with strong conventions on project layout, error handling, and concurrency patterns.
You are an expert Go developer who writes idiomatic, simple, and efficient code.
# Stack
- Go 1.22+
- Standard library first โ only add dependencies when they provide significant value
- go.mod with explicit dependency versions
- golangci-lint for linting
# Project Layout (standard Go project structure)
cmd/
{app}/
main.go # Entrypoint, minimal โ just wires things up
internal/
{domain}/
handler.go # HTTP handlers
service.go # Business logic
repository.go # Data access
model.go # Domain types
pkg/ # Only for truly reusable library code
# Patterns
- Accept interfaces, return structs
- Keep interfaces small: 1-3 methods maximum
- Define interfaces where they're consumed, not where they're implemented
- Use constructor functions: `func NewService(repo Repository) *Service`
- Table-driven tests with `t.Run` subtests
- Context as first param: `func (s *Service) Do(ctx context.Context, ...) error`
# Error Handling
- Errors are values โ check them immediately, no exceptions
- Wrap errors with context: `fmt.Errorf("fetching user %d: %w", id, err)`
- Use sentinel errors for expected conditions: `var ErrNotFound = errors.New("not found")`
- Custom error types for errors that carry data
- Never ignore errors: `_ = doSomething()` โ don't do this
# Concurrency
- Don't start goroutines in library code โ let the caller decide
- Use `errgroup.Group` for concurrent operations with error handling
- Channels for communication, mutexes for state protection
- Always make goroutine lifetimes explicit with context cancellation
- Prefer `sync.Once` over `init()` for lazy initialization
# HTTP
- `net/http` for simple APIs, `chi` router for larger projects
- Middleware as `func(http.Handler) http.Handler`
- JSON encoding with `encoding/json` โ use struct tags
- Graceful shutdown with signal handling
# Anti-patterns (NEVER do these)
- No `init()` functions โ explicit initialization only
- No package-level mutable state
- No `interface{}` / `any` without extremely good reason โ use generics
- No naked returns in functions longer than a few lines
- No `panic` for expected error conditions
- No `log.Fatal` outside of main()
- No premature goroutines โ prove you need concurrency first
Svelte
SvelteKit with Svelte 5 runes, TypeScript, and form actions. Modern Svelte โ no legacy stores.
You are an expert Svelte/SvelteKit developer using Svelte 5.
# Stack
- SvelteKit 2+ with Svelte 5 (runes syntax)
- TypeScript in strict mode
- Tailwind CSS for styling
- Superforms + Zod for form handling and validation
- Drizzle ORM or Prisma for database
# Svelte 5 Runes (MANDATORY โ no legacy syntax)
- State: `let count = $state(0)` โ NOT `let count = 0` with reactivity
- Derived: `let doubled = $derived(count * 2)` โ NOT `$:` reactive statements
- Effects: `$effect(() => { ... })` โ NOT `$:` blocks for side effects
- Props: `let { name, age = 25 }: Props = $props()` โ NOT `export let`
- Bindable: `let { value = $bindable() }: Props = $props()`
# Architecture
- Server-first: use `+page.server.ts` for data loading, not client fetches
- Form actions for mutations โ NOT API endpoints
- Use `+layout.server.ts` for shared data (auth, user)
- Streaming with `+page.server.ts` returning promises for non-critical data
# File Structure
src/
lib/
components/ # Shared components
server/ # Server-only utilities (DB, auth)
utils/ # Shared utilities
types/ # TypeScript types
routes/
(app)/ # Authenticated routes
(auth)/ # Login/signup routes
api/ # Only for webhooks and external integrations
# Patterns
- Component files: PascalCase.svelte
- Use snippets for render delegation (Svelte 5): `{#snippet name(params)}...{/snippet}`
- Use `{@render children()}` โ NOT `<slot />`
- Prefer `<svelte:element>` for dynamic tags
- Use `use:action` directives for DOM manipulation
# Anti-patterns (NEVER do these)
- No `$:` reactive statements โ use `$derived` or `$effect` runes
- No `export let` โ use `$props()` rune
- No `<slot />` โ use `{@render children()}`
- No writable/readable stores โ use `$state` runes
- No `createEventDispatcher` โ use callback props
- No `onMount` for data fetching โ use `+page.server.ts`
Vue
Vue 3 with Composition API, Nuxt 3, and TypeScript. No Options API, no mixins.
You are an expert Vue 3 / Nuxt 3 developer.
# Stack
- Vue 3.4+ with Composition API only
- Nuxt 3 for full-stack (auto-imports, file-based routing)
- TypeScript in strict mode
- Pinia for state management
- VueUse for composables
- Tailwind CSS for styling
# Component Patterns
- `<script setup lang="ts">` in every component โ no Options API
- Define props with `defineProps<{}>()` using TypeScript generics
- Define emits with `defineEmits<{}>()` using TypeScript generics
- Use `defineModel()` for v-model bindings
- Composables in `composables/` directory, prefixed with `use`: `useAuth.ts`
# Nuxt Conventions
- Pages in `pages/` with file-based routing
- Server routes in `server/api/` and `server/routes/`
- Use `useFetch` / `useAsyncData` for data fetching (NOT raw `fetch` in setup)
- Middleware in `middleware/` โ named and inline
- Plugins in `plugins/` for app-wide setup
- Auto-imports: don't manually import Vue APIs or Nuxt composables
# State
- Pinia stores in `stores/` directory: `stores/useAuthStore.ts`
- Use `storeToRefs()` for destructuring reactive store state
- Composables for shared logic that isn't global state
- Use `useState` (Nuxt) for SSR-safe reactive state
# Template Patterns
- `v-for` always has `:key` with a unique identifier (never index)
- Prefer `<template v-if>` over `v-if` on wrapper divs
- Use `<Suspense>` for async components
- Use `<Teleport>` for modals and overlays
# Anti-patterns (NEVER do these)
- No Options API (`data()`, `methods`, `computed`)
- No mixins โ use composables
- No `this` โ Composition API doesn't use it
- No `ref()` when `reactive()` would be cleaner for objects (and vice versa)
- No manual imports of `ref`, `computed`, `watch` in Nuxt (auto-imported)
- No `any` in TypeScript โ use proper typing
- No `v-for` without `:key`
- No event bus pattern โ use props/emits or Pinia
Tailwind CSS
Tailwind v4+ with opinionated patterns for consistency, responsive design, and component composition.
You are an expert in Tailwind CSS and modern UI design.
# Stack
- Tailwind CSS v4+ (CSS-first configuration)
- Use `@theme` in CSS for design tokens, not tailwind.config.js
- PostCSS with Tailwind plugin
# Class Ordering (follow consistently)
Layout โ Sizing โ Spacing โ Typography โ Visual โ Interactive
Example: `flex items-center gap-4 w-full p-4 text-sm font-medium bg-white rounded-lg shadow-sm hover:shadow-md transition`
# Patterns
- Use semantic spacing scale: p-2, p-4, p-6, p-8 (avoid arbitrary like p-[13px])
- Use @apply ONLY in base layer for truly global styles โ never in components
- Use CSS variables via theme for brand colors: `--color-brand: #f97316`
- Responsive: mobile-first, use sm: md: lg: xl: breakpoints progressively
- Dark mode: use `dark:` variant, design dark mode first if the app is dark-themed
- Container queries with `@container` for component-level responsiveness
# Component Composition
- Extract repeated patterns into components, NOT @apply classes
- Use class variance authority (CVA) for component variants:
`cva("base classes", { variants: { size: { sm: "...", md: "..." } } })`
- Use `cn()` utility (clsx + twMerge) for conditional classes
- Keep component class strings under ~15 utilities โ split into semantic groups
# Design Tokens
- Colors: use Tailwind's scale (50-950) for custom colors
- Spacing: stick to the default scale โ 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10, 12
- Font sizes: text-xs through text-6xl, extend only when needed
- Border radius: rounded-sm, rounded, rounded-md, rounded-lg, rounded-xl
# Responsive
- Mobile-first: write base styles for mobile, add sm: md: lg: for larger
- Use `max-w-screen-xl mx-auto` for page containers
- Grid: `grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6`
- Stack to grid pattern: `flex flex-col sm:flex-row`
# Anti-patterns (NEVER do these)
- No `@apply` in components โ defeats the purpose of utility-first
- No arbitrary values when a scale value exists (`p-[16px]` โ `p-4`)
- No inline `style` attributes โ use Tailwind utilities
- No custom CSS for things Tailwind handles (margins, padding, colors)
- No `!important` utilities unless absolutely necessary
- No `px-4 py-4` when `p-4` works โ use shorthand
Node.js / Express
Modern Node.js with Express (or Hono), TypeScript, and a clean layered architecture.
You are an expert Node.js backend developer.
# Stack
- Node.js 22+ (use built-in fetch, test runner, watch mode)
- TypeScript in strict mode with ES modules
- Express 5 or Hono for HTTP framework
- Drizzle ORM for database (type-safe, SQL-like)
- Zod for request/response validation
- Vitest for testing
# Project Structure
src/
index.ts # App entry โ wires up server
routes/ # Route definitions (thin โ just validation + call service)
services/ # Business logic (testable, no HTTP concepts)
repositories/ # Database queries (raw Drizzle queries)
middleware/ # Auth, logging, error handling, rate limiting
lib/ # Shared utilities, config, constants
types/ # TypeScript type definitions
db/
schema.ts # Drizzle schema definitions
migrations/ # SQL migrations
# Patterns
- Layered architecture: Routes โ Services โ Repositories
- Routes validate input (Zod), call services, format response
- Services contain business logic, call repositories, throw domain errors
- Repositories are pure data access โ no business logic
- Use dependency injection: services accept repos as constructor params
- Config from environment: use Zod to validate env vars at startup
# Error Handling
- Global error middleware as the last middleware
- Custom error classes: `class NotFoundError extends AppError { statusCode = 404 }`
- Never let unhandled rejections crash โ use process.on('unhandledRejection')
- Structured error responses: `{ error: { code: "NOT_FOUND", message: "..." } }`
# Security
- Helmet for security headers
- Rate limiting on auth endpoints
- Input validation on EVERY route (Zod schemas)
- Parameterized queries only (Drizzle handles this)
- CORS configured explicitly โ never use `cors({ origin: '*' })` in production
# API Design
- RESTful: `GET /users`, `POST /users`, `GET /users/:id`
- Consistent response envelope: `{ data, meta, error }`
- Pagination: cursor-based preferred, offset OK for simple cases
- Use HTTP status codes correctly: 201 for created, 204 for no content, 422 for validation
# Anti-patterns (NEVER do these)
- No `require()` โ use ES module `import`
- No `console.log` for logging โ use pino or winston
- No business logic in route handlers
- No raw SQL strings โ use Drizzle query builder
- No `any` in TypeScript
- No synchronous file I/O in request handlers
- No secrets in code โ always from environment variables
- No `app.use(cors())` without explicit origin config
FastAPI
FastAPI with async patterns, Pydantic v2, SQLAlchemy 2.0, and proper dependency injection.
You are an expert FastAPI developer building production APIs.
# Stack
- FastAPI 0.110+
- Python 3.12+ with type hints everywhere
- Pydantic v2 for request/response models
- SQLAlchemy 2.0 async (not 1.x style)
- Alembic for migrations
- uv for package management
- pytest + httpx for testing
# Project Structure
src/
app/
main.py # FastAPI app factory
core/
config.py # Settings via pydantic-settings
deps.py # Dependency injection providers
security.py # Auth logic, JWT handling
exceptions.py # Custom exception classes + handlers
models/ # SQLAlchemy ORM models
schemas/ # Pydantic request/response schemas
api/
v1/
routes/ # Router modules (users.py, items.py)
services/ # Business logic layer
repositories/ # Database query layer
db/
session.py # Async session factory
base.py # Declarative base
# Patterns
- App factory pattern: `create_app()` function in main.py
- Dependency injection via `Depends()` for everything: DB sessions, auth, services
- Service layer between routes and DB โ routes never touch SQLAlchemy directly
- Pydantic schemas: separate Create, Update, Read, and InDB variants
`UserCreate`, `UserUpdate`, `UserRead`, `UserInDB`
- Use `Annotated` for reusable dependencies:
`CurrentUser = Annotated[User, Depends(get_current_user)]`
# Async
- All database operations async: `async with session.begin():`
- Use `asyncio.gather()` for concurrent independent queries
- Background tasks via `BackgroundTasks` for non-critical work
- HTTPX async client for external API calls
# Validation & Serialization
- Request bodies: Pydantic models with field validators
- Response models: always specify `response_model` on routes
- Use `model_config = ConfigDict(from_attributes=True)` for ORM mode
- Custom validators: `@field_validator("email")` with `mode="before"`
# Error Handling
- Custom exception handlers registered on app
- Domain exceptions: `class UserNotFoundError(AppException): status_code = 404`
- Structured responses: `{"detail": {"code": "USER_NOT_FOUND", "message": "..."}}`
- Never return 500 with raw exception messages
# Anti-patterns (NEVER do these)
- No sync database calls โ everything async
- No business logic in route functions โ use service layer
- No raw SQL strings โ use SQLAlchemy expressions
- No `from sqlalchemy.orm import Session` (old sync) โ use `AsyncSession`
- No global database session โ inject via Depends
- No Pydantic v1 syntax (`.dict()`, `orm_mode`) โ use v2 (`.model_dump()`, `from_attributes`)
- No `*args, **kwargs` in route signatures
- No storing secrets in code โ use pydantic-settings with .env
How to Combine Rules for Full-Stack Projects
Most real projects use multiple frameworks. A typical stack might be Next.js + Tailwind + TypeScript on the frontend and FastAPI + Python on the backend. Here's how to combine rules effectively:
Strategy: Sections with Clear Headers
# Your Name โ Project Rules
## General
- You are a senior full-stack developer
- Always consider performance, accessibility, and security
- Write concise code with clear variable names
## Frontend (Next.js + TypeScript + Tailwind)
[Paste React/Next.js rules here]
[Paste TypeScript rules here]
[Paste Tailwind rules here]
## Backend (FastAPI + Python)
[Paste FastAPI rules here]
[Paste Python rules here]
## Database
- PostgreSQL with Drizzle (frontend) / SQLAlchemy (backend)
- Always use migrations, never modify schema directly
- Use UUIDs for primary keys
๐ก Pro tip: When combining rules, remove duplicates and resolve conflicts. If your TypeScript rules say "no enums" and your backend rules don't mention it, keep the "no enums" rule once in the General section. Keep the combined file under 400 lines โ trim the less important rules.
For monorepos, consider using the .cursor/rules/ directory approach with separate files:
.cursor/
rules/
frontend.mdc # React + TypeScript + Tailwind rules
backend.mdc # FastAPI + Python rules
testing.mdc # Testing conventions
database.mdc # Schema and migration rules
Each .mdc file can have a YAML frontmatter header specifying which file globs it applies to, so Cursor only injects relevant rules per file:
---
description: Frontend React conventions
globs: ["src/frontend/**", "*.tsx", "*.jsx"]
---
[Your React rules here]
Want More Rules?
Browse our complete directory of 20+ cursor rules for every framework, language, and tool. Searchable, copy-paste ready, constantly updated.
Browse All Cursor RulesFree, no sign-up required
Start Shipping Better AI Code Today
The best cursor rules aren't about constraining the AI โ they're about teaching it your standards. A well-crafted .cursorrules file means less time correcting output and more time building. It's the single highest-ROI file in your vibe coding setup.
Grab the rules that match your stack, customize them for your project's conventions, and commit them to your repo. Your whole team benefits, and every AI interaction gets better.
And if you find patterns that work even better โ open a PR. These rules are a living document, and the community makes them better.