Skip to main content

MDC Rules Best Practices and Troubleshooting in Cursor

Cursor MDC Rules

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

RequirementDetails
ExtensionMust be .mdc (not .md)
Front matterMust use YAML format between --- delimiters
LocationMust be in .cursor/rules/ directory
globsArray of file patterns this rule applies to
alwaysApplyBoolean - 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

RangeCategoryExample
001-099Core rules (apply to all files)Coding standards, formatting
100-199Integration rules (specific domains)API, database, auth
200-299Pattern/role rulesTesting, documentation
300-399Technology-specificReact, 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:

  1. Fully close Cursor (not just the window - quit the application)
  2. Reopen Cursor
  3. 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
  • globs pattern 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:

  1. Rules with more specific glob patterns take precedence
  2. Rules with alwaysApply: true are evaluated first
  3. 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)