MDC Rules Best Practices and Troubleshooting in Cursor

MDC (Markdown Configuration) rules are Cursor's powerful way to enforce coding standards, project conventions, and AI behavior guidelines. When configured correctly, they dramatically improve code quality and consistency. This guide covers best practices for creating, organizing, and troubleshooting MDC rules.
What Are MDC Rules?
MDC rules are Markdown files with YAML front matter that tell Cursor how to behave when working with specific files or in specific contexts. They can:
- Enforce coding standards
- Define project architecture patterns
- Specify documentation requirements
- Control AI behavior for specific file types
File Format Requirements
MDC rules must follow this exact format:
---
description: 'Rule description here'
globs: ['src/**/*.ts', 'tests/**/*.ts']
alwaysApply: false
---
# Rule Title
Your rule content here...
## Specific Guidelines
- Guideline 1
- Guideline 2
Critical Requirements
| Requirement | Details |
|---|---|
| Extension | Must be .mdc (not .md) |
| Front matter | Must use YAML format between --- delimiters |
| Location | Must be in .cursor/rules/ directory |
| globs | Array of file patterns this rule applies to |
| alwaysApply | Boolean - whether to apply without file matching |
Naming Convention
Use a numbered prefix system for organization:
.cursor/rules/
001-core-coding-standards.mdc
002-typescript-conventions.mdc
003-react-patterns.mdc
100-api-design.mdc
101-database-models.mdc
200-testing-requirements.mdc
201-documentation-rules.mdc
Numbering System
| Range | Category | Example |
|---|---|---|
001-099 | Core rules (apply to all files) | Coding standards, formatting |
100-199 | Integration rules (specific domains) | API, database, auth |
200-299 | Pattern/role rules | Testing, documentation |
300-399 | Technology-specific | React, Vue, Angular |
Writing Effective Rules
Be Specific and Actionable
Bad:
Write good code.
Good:
## Error Handling
All async functions must use try/catch blocks:
```typescript
async function fetchUser(id: string): Promise<User> {
try {
const response = await api.get(`/users/${id}`);
return response.data;
} catch (error) {
logger.error(`Failed to fetch user ${id}`, error);
throw new UserNotFoundError(id);
}
}
### Include Examples
Always show both correct and incorrect examples:
```markdown
## State Management
✅ DO: Use React Query for server state
```typescript
const { data, isLoading } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId)
});
❌ DON'T: Use useEffect for data fetching
// Avoid this pattern
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
### Use Glob Patterns Effectively
```yaml
# Apply to all TypeScript files
globs: ['**/*.ts', '**/*.tsx']
# Apply only to backend code
globs: ['src/server/**/*.ts', 'src/api/**/*.ts']
# Apply to specific test files
globs: ['**/*.test.ts', '**/*.spec.ts']
# Exclude certain files
globs: ['src/**/*.ts', '!src/generated/**']
Common Rule Categories
1. Code Style Rules
---
description: 'Enforce consistent code style'
globs: ['src/**/*.ts', 'src/**/*.tsx']
alwaysApply: true
---
# Code Style Standards
## Imports
- Group imports: React, external libs, internal modules, types
- Use absolute imports for src/ modules
- Sort alphabetically within groups
## Naming
- Components: PascalCase (UserProfile)
- Hooks: camelCase starting with 'use' (useAuth)
- Constants: UPPER_SNAKE_CASE
- Files: kebab-case (user-profile.tsx)
2. Architecture Rules
---
description: 'Enforce clean architecture patterns'
globs: ['src/**/*.ts']
alwaysApply: false
---
# Architecture Guidelines
## Layer Dependencies
- Domain layer: No external dependencies
- Application layer: Depends only on domain
- Infrastructure layer: Depends on application
## File Organization
src/ domain/ # Business logic, entities application/ # Use cases, DTOs infrastructure/ # DB, API, external services presentation/ # UI components
3. Testing Rules
---
description: 'Testing requirements and patterns'
globs: ['**/*.test.ts', '**/*.test.tsx']
alwaysApply: true
---
# Testing Standards
## Required Tests
- Unit tests for all utility functions
- Component tests for all React components
- Integration tests for API endpoints
- E2E tests for critical user flows
## Test Structure
Follow AAA pattern:
1. Arrange: Set up test data and mocks
2. Act: Execute the function being tested
3. Assert: Verify the results
Troubleshooting Common Issues
Issue 1: Changes Not Saving
Symptom: You edit an .mdc file, save it, but Cursor doesn't apply the changes.
Solution:
- Fully close Cursor (not just the window - quit the application)
- Reopen Cursor
- The changes should now be applied
Why this happens: MDC rules are cached when Cursor starts. They don't hot-reload.
Issue 2: Rules Not Being Applied
Symptom: Cursor ignores your rules when editing files.
Checklist:
- File extension is
.mdc(not.md) - File is in
.cursor/rules/directory - Front matter has valid YAML syntax
-
globspattern matches your target files - No syntax errors in the Markdown content
Debug command:
# Check if Cursor recognizes your rules
ls -la .cursor/rules/
# Verify file extensions
file .cursor/rules/*
Issue 3: Conflicting Rules
Symptom: Multiple rules give contradictory instructions.
Resolution order:
- Rules with more specific glob patterns take precedence
- Rules with
alwaysApply: trueare evaluated first - Later rules in alphabetical order override earlier ones
Best practice: Use the priority field (if supported):
---
description: 'High priority rule'
globs: ['src/**/*.ts']
priority: 100
---
Issue 4: Rules Too Long
Symptom: Cursor doesn't follow all instructions in a long rule.
Solution: Split into multiple focused rules:
.cursor/rules/
001-general-style.mdc # Short, general guidelines
002-error-handling.mdc # Specific to error handling
003-performance.mdc # Performance optimizations
Advanced Techniques
Conditional Rules
Use globs to apply different rules to different parts of your codebase:
# Frontend rules
globs: ['src/components/**/*.tsx', 'src/pages/**/*.tsx']
---
Use React hooks pattern. Prefer functional components.
# Backend rules
globs: ['src/server/**/*.ts', 'src/api/**/*.ts']
---
Use dependency injection. Follow SOLID principles.
Rule Inheritance
Create a base rule and extend it:
---
description: 'Base TypeScript standards'
globs: ['**/*.ts', '**/*.tsx']
alwaysApply: true
---
# Base TypeScript Rules
- Use strict TypeScript configuration
- No `any` types without justification comment
- Prefer `interface` over `type` for object shapes
---
description: 'React-specific extensions'
globs: ['src/**/*.tsx']
alwaysApply: false
---
# React Rules
In addition to base TypeScript rules:
- Use functional components with hooks
- Props interfaces must be exported
- Use React.FC sparingly (prefer explicit props typing)
Dynamic Rules with Variables
Some advanced setups support template variables:
---
description: 'Project-specific conventions'
globs: ['**/*.ts']
---
# Project Conventions
## API Base URL
Use: {{API_BASE_URL}}
## Authentication
Token header: {{AUTH_HEADER_NAME}}
Quick Reference: MDC Rule Template
---
description: ''
globs: ['']
alwaysApply: false
---
# Title
## Section 1
- Guideline 1
- Guideline 2
## Section 2
```typescript
// Example code
References
## Related Resources
- [Using Cursor Rules Effectively](using-cursor-rules-effectively.mdx)
- [Best Practices for Cursor Rules](best-practices-for-cursor-rules.mdx)
- [CursorRules Setup Guide](cursorrules-setup-guide.mdx)