If you have been using Cursor for more than a few days, you have already noticed the problem: each new chat starts blank. The AI does not know your stack, your naming conventions, your file structure, or your preferences. You end up re-explaining the same context over and over, "we use TypeScript, we prefer server components, always add error handling", and every session feels like briefing a contractor who just walked in the door.
Cursor rules solve this. They are persistent instructions that load automatically with every conversation, every autocomplete suggestion, and every agent task. Done well, they transform Cursor from a capable AI editor into something that feels purpose-built for your specific project.
This guide covers everything: the current .cursor/rules directory and .mdc format as of 2026, the difference between rule types, the anatomy of a rule that actually works, 15 ready-to-use templates, rules for specific tools like Supabase and Stripe, how to organize rules for large projects, and the most common pitfalls.
Key Takeaways
- Cursor rules use the .cursor/rules directory with .mdc files, replacing the legacy single .cursorrules file for better scope control and token efficiency
- There are four rule activation modes: Always Apply, Auto Attached (globs), Agent Requested (description-based), and Manual (@rule-name), choosing the right one is critical for rules to fire when expected
- Keep always-apply rules under 200 words to avoid the "token tax", every token loads in every single request, consuming your context window budget
- The 15 ready-to-use templates cover the full stack: React components, API routes, Supabase, Stripe payments, Prisma, shadcn/ui, testing, security, and performance
- Commit your .cursor/rules directory to version control so the entire team shares the same AI behavior, coding standards, and output consistency
- Rules are not set-and-forget: evolve them with your project, if you explain the same thing to Cursor three times, it belongs in a rule
Learn this hands-on
Ready to ship a real production app, not just pick a model? Check out the Master Course: Build and Ship a Production-Ready App with Lovable and Cursor.
Why Cursor Rules Matter More Than Most Developers Realize
According to the 2025 Stack Overflow Developer Survey, 84% of developers now use or plan to use AI coding tools in their workflow, up from 76% the year before. But adoption alone does not equal productivity. The developers getting the most out of Cursor are not just using better prompts. They are building better context infrastructure, and cursor rules are the foundation of that.
Without rules, you spend a significant portion of your AI budget on re-establishing context. With well-crafted rules, that context is already present before you type a single word. The AI understands your project's architecture, your team's standards, the tools you are using, and the patterns you want to enforce. Every prompt starts from a position of shared understanding rather than a blank slate.
As Michael Truell, CEO & Co-founder at Cursor, explains: "We think the way developers will build software in the future is by describing intent, and the AI handles the implementation details."
Understanding the Current Format: .cursor/rules vs .cursorrules
There are two places cursor rules can live, and the distinction matters.
The Legacy .cursorrules File
The original approach was a single file named .cursorrules at the project root. Everything lived in one flat file: coding standards, framework conventions, architecture rules, testing preferences. It worked, and it still works today. If you have an existing .cursorrules file, Cursor continues to read it.
The limitation is that a single file has no scope control. Every rule loads for every conversation regardless of relevance. Writing a SQL migration? Your React component guidelines load too. This is wasteful on context tokens, what the Cursor community calls the "token tax", and makes rules harder to maintain as projects grow.
The Modern .cursor/rules Directory
The current recommended approach is the .cursor/rules directory with individual .mdc files. This is the format Cursor standardized on and the one their documentation now leads with.
The structure looks like this:
your-project/
├── .cursor/
│ └── rules/
│ ├── general-coding-standards.mdc
│ ├── react-components.mdc
│ ├── api-routes.mdc
│ ├── database-supabase.mdc
│ ├── testing.mdc
│ └── security.mdc
├── src/
└── package.json
Each .mdc file is version-controlled, independently scoped, and loaded only when relevant. This is the format all new projects should use.
The Anatomy of a .mdc Rule File
Every .mdc file has two parts: a YAML frontmatter block that controls when the rule activates, and a markdown body that contains the actual instructions.
---
description: Rules for React component development
globs: ["src/components/**/*.tsx", "src/components/**/*.ts"]
alwaysApply: false
---
# React Component Rules
Always use functional components with TypeScript interfaces.
Never use default exports, use named exports only.
The frontmatter fields control everything:
description: A plain-language summary of when this rule should be used. This is what the agent reads to decide whether to include the rule when it has been set to agent-requested mode.
globs: File path patterns that trigger automatic rule attachment. When you open or edit a file matching these patterns, the rule loads automatically.
alwaysApply: When set to true, the rule loads for every single conversation regardless of context. Use sparingly, this is your global config, not your per-feature config.
The Four Rule Activation Modes
This is where most developers get confused. Cursor rules have four distinct behaviors, and choosing the wrong one is the most common cause of rules not firing when expected.
1. Always Apply
alwaysApply: true
The rule loads in every conversation without exception. Use this for foundational project context: what tech stack you are using, what the project does, team-wide standards that apply everywhere. Keep always-apply rules short, every token they consume is consumed in every single request.
Best for: Project context, universal coding standards, language/framework version pinning.
2. Auto Attached
alwaysApply: false
globs: ["src/api/**/*.ts"]
The rule loads automatically when files matching the glob patterns are in context. When you are working in src/api/, your API rules are present. When you move to src/components/, they are not. This is the most efficient mode for domain-specific rules.
Best for: Component libraries, API routes, database files, test files, anything with clear file boundaries.
3. Agent Requested
description: "Use when creating or modifying Stripe payment flows, webhooks, or subscription logic"
alwaysApply: false
No globs. A description only. The agent reads the description and decides whether the rule is relevant to the current task. If you ask Cursor to "add a Stripe checkout flow," it reads the description, recognizes the relevance, and loads the rule.
Best for: Tool-specific rules (Stripe, SendGrid, Twilio), workflow rules, rules for tasks that cut across multiple file types.
4. Manual
No description, no globs, no alwaysApply. The rule is only included when you explicitly reference it using @rule-name in your prompt.
Best for: Reference rules you only need occasionally, rules for rare tasks, documentation-style rules.
Rule Length: The Token Tax Problem
Every rule token is included in every request that activates that rule. A 500-word always-apply rule might cost you 700 tokens before you have typed a single character. Across hundreds of daily requests, that compounds fast.
The practical guidelines:
- Always-apply rules: Keep under 200 words. This is your elevator pitch about the project.
- Auto-attached rules: 200-500 words is reasonable. These are scoped, so the cost is bounded.
- Agent-requested rules: Can be longer (500-800 words) since they only load when explicitly relevant.
- Manual rules: No strict limit, they are on-demand.
The instinct is to write comprehensive rules. The effective approach is to write precise ones. Ten focused rules outperform one sprawling document.
15 Ready-to-Use Cursor Rule Templates
1. Project Foundation (Always Apply)
---
description: Core project context
alwaysApply: true
---
This is a Next.js 15 SaaS application using TypeScript, Tailwind CSS, Supabase for auth and database, and Stripe for payments.
Always use TypeScript. Never use `any` type, use `unknown` with type guards.
Prefer server components unless client-side interactivity is required.
All database access goes through the /lib/db directory.
Environment variables are validated at startup in /lib/env.ts.
2. React Components (Auto Attached)
---
description: React component development standards
globs: ["src/components/**/*.tsx", "app/**/*.tsx"]
alwaysApply: false
---
Use functional components with TypeScript interfaces.
Use named exports only, no default exports.
Props interface naming: ComponentNameProps.
Use shadcn/ui components from /components/ui before building custom ones.
Install new shadcn components with: npx shadcn@latest add [component-name]
Avoid inline styles, use Tailwind utility classes exclusively.
Keep components under 150 lines. Extract sub-components when they grow.
3. Tailwind CSS Standards (Auto Attached)
---
description: Tailwind CSS styling conventions
globs: ["**/*.tsx", "**/*.jsx"]
alwaysApply: false
---
Use Tailwind utility classes, never inline styles or external CSS files.
Follow mobile-first responsive design: base → sm → md → lg → xl.
Use the cn() utility from /lib/utils for conditional classes.
Color usage: primary actions use the brand color tokens, not arbitrary hex values.
Spacing follows the 4px grid: use p-4, gap-6, mt-8, not arbitrary values.
4. API Routes (Auto Attached)
---
description: API route development standards
globs: ["app/api/**/*.ts", "pages/api/**/*.ts"]
alwaysApply: false
---
Every API route must validate the request body using Zod before processing.
Authentication check must be the first operation in every protected route.
Return consistent error shapes: { error: string, code: string }.
Use HTTP status codes correctly: 400 for validation, 401 for auth, 403 for authorization, 500 for server errors.
Never log sensitive data (passwords, tokens, full request bodies).
Rate limiting is handled by the middleware in /middleware.ts.
5. Testing Standards (Auto Attached)
---
description: Testing guidelines and conventions
globs: ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"]
alwaysApply: false
---
Use Vitest for unit tests, React Testing Library for component tests.
Test behavior, not implementation. Test what a user sees and does.
Each test file covers exactly one module or component.
Use descriptive test names: "returns 401 when user is not authenticated".
Mock external dependencies (APIs, databases) in all unit tests.
Aim for 80% coverage on critical paths: auth, payments, data mutations.
6. Security Rules (Auto Attached)
---
description: Security standards for all code
globs: ["app/api/**/*.ts", "lib/**/*.ts"]
alwaysApply: false
---
Never hardcode secrets, API keys, or credentials.
Always validate and sanitize user input before processing.
Use parameterized queries, never string-interpolate SQL.
Authentication tokens must be stored in httpOnly cookies, never localStorage.
Always check authorization (ownership/permissions), not just authentication.
Sanitize any data that will be rendered as HTML to prevent XSS.
7. Supabase Database (Auto Attached)
Related Course on Vibe Coding Academy
---
description: Supabase client usage and database patterns
globs: ["lib/db/**/*.ts", "lib/supabase/**/*.ts", "app/api/**/*.ts"]
alwaysApply: false
---
Use the Supabase server client for all server-side operations (never the browser client on the server).
Import the server client from /lib/supabase/server.ts.
Row Level Security is enabled on all tables. Never bypass RLS with the service role key unless explicitly required for admin operations.
Always handle the { data, error } response pattern, never destructure without checking error.
Use Supabase Storage for file uploads, not local disk.
Database migrations live in /supabase/migrations and must be reviewed before applying to production.
8. Stripe Payments (Agent Requested)
Related Course on Vibe Coding Academy

---
description: Use when creating or modifying Stripe checkout flows, webhooks, subscriptions, or payment logic
alwaysApply: false
---
Use the Stripe Node.js SDK, never raw fetch calls to the Stripe API.
Webhook endpoints must verify the Stripe signature using stripe.webhooks.constructEvent().
Never store full card data. Store only the Stripe customer ID and subscription ID.
Always test with Stripe test mode keys in development (sk_test_...).
Idempotency keys are required for payment creation requests.
Handle these webhook events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed.
Subscription status is the source of truth for feature access, check it on every protected request.
9. Prisma ORM (Auto Attached)
---
description: Prisma ORM patterns and conventions
globs: ["lib/prisma/**/*.ts", "prisma/**/*.ts", "app/api/**/*.ts"]
alwaysApply: false
---
Use the singleton Prisma client from /lib/prisma/client.ts.
Always use transactions for operations that modify multiple tables.
Use select to limit returned fields, never return full records when partial data is sufficient.
Prisma schema changes require a migration: npx prisma migrate dev.
Never run prisma migrate deploy in development, only in CI/CD.
Use Prisma's built-in pagination: take/skip for offset, cursor for cursor-based.
10. shadcn/ui Components (Agent Requested)
---
description: Use when adding, modifying, or composing shadcn/ui components
alwaysApply: false
---
Install components with npx shadcn@latest add [component-name], never copy-paste manually.
shadcn components live in /components/ui, never modify them directly.
Extend shadcn components by wrapping them in a new component in /components.
Use the Dialog component for modals, Sheet for sidepanels, Popover for inline overlays.
Form validation uses React Hook Form + Zod with the shadcn Form component.
Toast notifications use the Sonner integration, not the legacy Toast component.
11. Error Handling (Always Apply)
---
description: Error handling and logging conventions
alwaysApply: true
---
All async operations must use try/catch. No unhandled promise rejections.
User-facing errors must be human-readable, never raw error messages or stack traces.
Log errors server-side with context: user ID, route, timestamp.
Use the AppError class from /lib/errors.ts for structured error throwing.
The global error boundary in /app/error.tsx handles uncaught client errors.
12. TypeScript Strict Mode (Auto Attached)
---
description: TypeScript conventions and strict mode rules
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---
TypeScript strict mode is enabled. Honor it, no ts-ignore without explanation.
Use unknown over any. Narrow types with type guards before using them.
Define shared types and interfaces in /types, import from there, never redefine.
Prefer type unions over enums for simple string variants.
Use satisfies operator to validate against a type without widening it.
Generic function parameters should be named T, U for single-letter cases, or descriptive names for complex signatures.
13. Vibe Coding Workflow (Agent Requested)
---
description: Use when building new features end-to-end from prompt to deployment
alwaysApply: false
---
When building a new feature: schema first, then API, then UI.
Always generate the Supabase migration before writing any application code that depends on it.
Create a feature branch before starting. Commit at each working milestone.
Write the happy path first. Add error states and edge cases in a second pass.
Before calling a feature done: it renders without console errors, the API returns correct status codes, and auth protection is verified.
14. Code Review Checklist (Manual)
---
description: Pre-commit code review checklist
alwaysApply: false
---
Before committing, verify:
- No hardcoded secrets or API keys
- No console.log statements left in production paths
- TypeScript compiles with zero errors
- All new API routes have input validation
- Database queries use proper error handling
- Any new environment variables are documented in .env.example
- Component props are fully typed
15. Performance Standards (Auto Attached)
---
description: Performance optimization rules
globs: ["app/**/*.tsx", "src/**/*.tsx"]
alwaysApply: false
---
Images must use the Next.js Image component with explicit width/height.
Avoid importing entire libraries when named imports are available.
Use React.memo() for components that receive the same props frequently.
Lazy load below-the-fold components with next/dynamic.
Database queries must include LIMIT clauses, never fetch unbounded lists.
Client components must not trigger waterfalls: fetch data in server components and pass as props.
Organizing Rules in Large Projects
When a project grows past a handful of rules, organization becomes the challenge.
A folder structure that works well:
.cursor/rules/
├── core/
│ ├── project-context.mdc # always apply
│ └── typescript-standards.mdc # always apply
├── frontend/
│ ├── react-components.mdc
│ ├── tailwind.mdc
│ └── performance.mdc
├── backend/
│ ├── api-routes.mdc
│ ├── security.mdc
│ └── error-handling.mdc
├── tools/
│ ├── supabase.mdc
│ ├── stripe.mdc
│ ├── prisma.mdc
│ └── shadcn.mdc
└── workflow/
├── testing.mdc
├── vibe-coding.mdc
└── code-review.mdc
Cursor reads all .mdc files recursively from .cursor/rules/, so subdirectory organization is for your benefit, not Cursor's. Name files clearly, you will reference them by name when using manual rules.
For teams, commit the .cursor/rules/ directory to your repository. This is one of the most underused practices in collaborative vibe coding: shared rules mean shared AI behavior. Every developer on the team gets the same context, the same standards, the same output consistency.
Common Pitfalls and How to Debug Them
Rules not firing when expected. The most common cause is glob pattern misconfiguration. Cursor's glob syntax is strict. Test your patterns against actual file paths. src/**/*.tsx matches files in subdirectories; src/*.tsx only matches files directly in src/.
Conflicting rules. If two rules give contradictory instructions, one says "use default exports," another says "never use default exports", Cursor will follow the most recently loaded rule or produce inconsistent results. Audit for contradictions when adding new rules.
Always-apply rules killing context window. If Cursor feels slow or you are hitting context limits, look at your always-apply rules first. A 1,000-word always-apply rule is expensive. Trim aggressively, or convert it to auto-attached with appropriate globs.
Agent not picking up agent-requested rules. The description must clearly describe the use case. "Stripe payment flows" is actionable. "Use for payment stuff" is not. Write descriptions as if explaining to a human when to use the rule.
Migrating from .cursorrules. You do not need to delete your .cursorrules file immediately, Cursor still reads it. Migrate incrementally: move sections to .mdc files one at a time, verifying behavior as you go, then remove the old file once everything is in the new format.
Next Steps
Cursor rules are not a set-and-forget feature. The best rule sets evolve with the project. When you find yourself re-explaining the same thing to Cursor three times, that is a signal it belongs in a rule. When a rule has not fired in weeks, it might be time to remove it.
The 15 templates above give you a working foundation for a modern full-stack project. Start with the always-apply project context rule and one or two auto-attached rules for your primary file types. Add from there as you notice gaps.
If you want to see cursor rules applied in a real end-to-end vibe coding workflow, from initial scaffolding to authentication, payments, and deployment, the Master Course walks through the complete process with real projects. The practical gap between "I know how cursor rules work" and "I have a production-quality rule system for my project" closes fast when you see it applied in context.
Related Course on Vibe Coding Academy
Building with Cursor and want to go further? Explore the full vibe coding curriculum at vibecodingacademy.ai.

