Every time I started a new project, I'd spend the first hour telling the AI the same things.
Use Tailwind, not inline styles. Don't import lodash. Keep components under 150 lines. Handle errors explicitly, don't swallow them. You know the list. Your list probably looks a lot like mine.
That's not prompting. That's just yelling at a wall until it remembers your preferences. There's a better way.
What Cursor Rules Actually Are
Cursor lets you drop a .cursorrules file (or use the newer .cursor/rules directory) into the root of your project. Everything in that file gets injected into the system context before any conversation starts.
This means the model already knows your constraints before you type a single word. You don't ask. It just knows.
Think of it less like a config file and more like an onboarding doc for a contractor who reads it once and never forgets it.
The Mistake Everyone Makes First
The first thing people do is dump everything in. Stack preferences, naming conventions, commit message format, accessibility rules, tone of comments, preferred libraries, folder structure. All of it.
Then they wonder why the model starts ignoring half of it.
Context windows have budgets. When you flood the rules file, you're spending your budget before the actual work starts. The model isn't skipping your rules on purpose. It's just deprioritizing lower-signal content under pressure.
The fix is to be ruthless about what goes in the rules file vs. what you put in a one-off prompt when it actually matters.
What Actually Belongs in Rules
I keep three categories in my rules files:
- Hard constraints. Things the model should never do. No default exports. No any types in TypeScript unless explicitly allowed. No direct DOM manipulation outside specific utility files. These need to be enforced every single time, so they live here.
- Stack facts. What's in the project. Next.js 14 app router, not pages. Prisma for the ORM. Resend for email. Zod for validation. The model makes better guesses when it knows the terrain.
- Style patterns. Not your whole style guide. Just the decisions that are easy to get wrong. Server components by default, client components only when you need interactivity. Co-locate styles with components. Keep business logic out of route handlers.
That's it. Everything else either goes in context-specific prompts or you handle it in review.
A Real Example from One of My Projects
Here's a stripped version of what I use for a SaaS dashboard project:
You are working in a Next.js 14 app using the App Router.
Stack: TypeScript, Tailwind CSS, Prisma, Zod, Resend, Stripe.
Rules:
- All data fetching happens in server components or server actions. Never fetch in client components.
- Validate all user input with Zod before it touches the database.
- Never use `any` in TypeScript. Use `unknown` and narrow.
- Keep route handlers thin. Business logic lives in /lib.
- Components go in /components. Shared types go in /types.
- Prefer named exports over default exports.
- Error handling must be explicit. No empty catch blocks.
Short. Specific. Every line earns its place.
When I generate a new server action now, I don't get a client-side fetch call that breaks on SSR. When I ask for a form handler, it already reaches for Zod. It just works the way my project works.
Layering Rules for Monorepos and Multi-App Projects
If you're running a monorepo with multiple apps or packages, you can layer rules files. Put the global rules at the repo root. Put app-specific rules in each app directory.
Cursor picks up both. So your web app gets the global TypeScript rules plus its own Next.js patterns, while your API service gets the global rules plus its own Express or Hono-specific constraints.
This is underused. Most people set one rule file and forget it exists.
Updating Rules as the Project Evolves
Your rules file is not a contract you sign once. It's a living document.
When you catch the model making the same wrong assumption three times, that's a signal. Either the rule isn't clear enough, or you haven't written the rule yet. Either way, the fix is five minutes of editing.
I treat rule file updates the same way I treat updating documentation. When something breaks a second time, I write it down. The third time should never happen.
Rules Aren't a Replacement for Prompting
One thing worth saying clearly: rules handle the repeatable, known stuff. They don't replace good prompts for complex tasks.
When I'm asking Cursor to help me think through an architecture decision or debug something weird, I still write a real prompt with context. Rules are the background layer. The prompt is the foreground.
The combination is where the speed comes from. The model already knows your stack, your constraints, your patterns. Now you can use the prompt for the actual thinking instead of repeating setup instructions for the hundredth time.
The rules file is the foundation. The prompt scaffolds are what actually make it fast. Both are covered in depth inside Inner Circle if you want the full setup.
Keep building
- Cursor Rules Generator from the prompt library
- Cursor Composer: Rename a Concept Across the Codebase from the prompt library
- How I Run My Entire Business by Talking to It
- The full Vaylo prompt library, new drops weekly
