2026-05-19 · 9 min read
How to Write Cursor Rules That Actually Work
Most .cursorrules files I see are too generic to help. They say things like "write clean code" or "follow best practices," which sounds fine but gives Cursor almost nothing specific to follow.
A useful rules file should describe how this project works. It should tell Cursor what stack you use, where important files live, what patterns to copy, and what mistakes to avoid.
What Are Cursor Rules?
Cursor rules are project instructions that guide how Cursor answers questions and edits code. In older setups, many people used a .cursorrules file in the project root. In newer Cursor workflows, rules can also live in .cursor/rules/, but the idea is the same: give the assistant local context it should always remember.
I think of rules as the short onboarding note I would give to a new developer. If someone joined my project for one day, what would they need to know before touching files? That is what belongs in the rules.
Rules are not magic. They will not make Cursor understand a messy codebase perfectly. But they can reduce repeated explanations. Instead of telling Cursor every time that this is a Next.js App Router project using Tailwind and MDX, I write it once.
The best rules are concrete. "Use Server Components by default in src/app" is better than "write modern React." "Do not add new dependencies without asking" is better than "keep the app lightweight."
I usually add rules after I understand the project. If I write them too early, I tend to include guesses. If I write them after a few real edits, I know which instructions actually matter.
Why Most Cursor Rules Files Are Useless
Most rules files fail because they are copied from someone else's project. A rules file for a Python data pipeline does not help a Next.js blog. A rules file for a large team app may be too heavy for a solo side project.
The second problem is vague language. Cursor cannot reliably act on "be careful" or "use good architecture." I need to say what careful means in this repo. For example: "Before editing a shared component, search for all imports and mention likely affected pages."
The third problem is rule overload. If I paste fifty rules into the project, the important ones disappear. Cursor may follow some, ignore others, or spend too much attention on instructions that do not matter for the task.
I try to keep rules short enough that I would actually read them myself. If the file feels like a company handbook, it is probably too long. A good first version can be 20 to 40 lines.
The final problem is rules that never get updated. A project changes. The stack changes. Folder names change. If the rules still describe an old architecture, Cursor will make worse suggestions. I treat rules like code: small, specific, and updated when they become wrong.
The 5 Rules Every Project Needs
The first rule should name the stack. Cursor should know whether the project is Next.js, Django, FastAPI, Rails, or something else. It should also know the language, styling system, test setup, and package manager.
The second rule should describe the file structure. I usually mention the routes directory, components directory, data layer, test folder, and content folder if the project has one. This stops Cursor from inventing new places for code.
The third rule should describe the default implementation style. For example, "prefer small server-side helpers over client-side fetches" or "use existing component patterns before creating new abstractions." These rules affect real edits.
The fourth rule should state what not to change. This is underrated. If I do not want Cursor touching generated files, environment files, migrations, or shared design tokens without asking, I say that.
The fifth rule should define verification. I tell Cursor which commands matter. For a Next.js project, that might be npm run lint and npm run build. For a Python project, it might be pytest and ruff check.
Here is the pattern I use:
Project context:
- This is a Next.js App Router project using TypeScript and Tailwind CSS.
- Routes live in src/app.
- Shared components live in src/components.
- Blog content lives in content/posts as MDX.
Implementation rules:
- Prefer Server Components unless interactivity requires a Client Component.
- Reuse existing components and styling patterns before creating new ones.
- Do not add dependencies without explaining why.
- Do not edit generated files or environment files unless explicitly asked.
Verification:
- After meaningful code changes, run npm run lint.
- Run npm run build when routes, metadata, or MDX rendering changes.
This is not fancy. That is why it works. It tells Cursor what kind of project it is in and what behavior I expect.
Rules for Next.js Projects
Next.js projects need rules because there are many ways to build the same feature. Without guidance, Cursor might add a Client Component where a Server Component would be simpler, or create a fetch pattern that does not match the app.
My first Next.js rule is usually about App Router. I tell Cursor that routes live in src/app, metadata should use the App Router metadata API, and dynamic pages should use the existing project pattern. That prevents old Pages Router suggestions.
I also mention styling. If the project uses Tailwind, I tell Cursor to use Tailwind classes and existing layout patterns. If there is a design system, I mention where it lives and ask Cursor to reuse it.
Data loading rules matter too. I do not want random client-side fetches if the rest of the app uses Server Components. A useful rule is: "Fetch data in Server Components by default. Use Client Components only for state, browser APIs, or interactive UI."
For content sites, I add MDX rules. I tell Cursor where posts live, which frontmatter fields are required, and how slugs are generated. That makes it much easier to add new posts without breaking the blog.
A good Next.js rules file is not a Next.js tutorial. It is a description of how your specific Next.js project works.
Rules for Python Projects
Python rules look different because the common mistakes are different. I usually care about environment setup, formatting, type hints, error handling, and tests.
For a Python API, I tell Cursor which framework is used, where routes live, where service logic belongs, and how database access is handled. I do not want route handlers filled with business logic if the project already has a service layer.
For data scripts, I care about reproducibility. I tell Cursor not to hardcode local paths, not to print secrets, and to make input/output paths explicit. I also tell it to keep scripts runnable from the command line.
Formatting rules help. If the project uses ruff, black, mypy, or pytest, I name those tools. Cursor is more likely to produce code that fits the project if it knows the checks.
Here is a small Python rule set I would actually use:
Python project rules:
- Use Python 3.12 syntax.
- Prefer typed functions for public helpers.
- Keep FastAPI route handlers thin; put business logic in services.
- Do not swallow exceptions silently.
- Use pytest for tests and keep fixtures in tests/conftest.py.
- Run ruff check and pytest after meaningful changes.
Again, the goal is not to list every Python opinion. The goal is to preserve the local shape of the project.
Example: My Personal .cursorrules File
This is the kind of .cursorrules file I would start with for a small Next.js blog or SaaS project. I would edit it after the first few real features.
You are helping maintain a small solo-developer Next.js project.
Project stack:
- Next.js App Router with TypeScript.
- Tailwind CSS for styling.
- Content posts are MDX files in content/posts.
- Shared React components live in src/components.
- App routes live in src/app.
Coding style:
- Prefer simple, readable code over clever abstractions.
- Reuse existing components, utilities, and route patterns before adding new ones.
- Keep components server-side by default.
- Add "use client" only when browser state, event handlers, or browser APIs require it.
- Do not add a dependency unless the task clearly needs it.
Content rules:
- MDX posts must include title, description, date, and tags in frontmatter.
- Dates should use YYYY-MM-DD.
- Keep writing direct, first-person, and practical.
Safety rules:
- Do not edit .env files.
- Do not edit generated files.
- Do not rename routes without asking.
- Before changing shared components, check where they are imported.
Verification:
- Run npm run lint after code changes.
- Run npm run build after route, metadata, or MDX changes.
The important part is that this file is specific. It mentions the stack, file locations, content rules, safety rules, and verification commands. Cursor has enough direction to behave better.
I would not copy this file exactly into every project. I would change it for the actual stack. If the project uses Prisma, I would mention Prisma. If it uses Supabase, I would mention Supabase. If it has a custom design system, I would name it.
Common Mistakes to Avoid
The first mistake is writing rules for an imaginary perfect project. Rules should describe the repo you have, not the repo you wish you had. If your project has a simple structure, do not invent a complex architecture in the rules file.
The second mistake is adding too many style opinions. Cursor does not need a full essay about clean code. It needs the few constraints that change the output. Keep the rules short enough to stay useful.
The third mistake is using rules to avoid reviewing diffs. Rules help Cursor start closer to the right answer, but they do not remove your responsibility. I still check every diff, especially when shared components, auth, billing, or database code changes.
The fourth mistake is forgetting negative instructions. If there are files Cursor should not touch, say so. If there are patterns you do not want, say so. "Do not create a second API client" can save a lot of cleanup.
The fifth mistake is never revisiting the file. I update rules when I notice repeated friction. If I keep telling Cursor the same thing in prompts, that instruction probably belongs in the rules.
My final advice is to start small. Write a rules file with the stack, structure, coding style, safety notes, and verification commands. Use it for a week. Then update it based on what Cursor still gets wrong.