Przejdź do głównej zawartości

Custom Rules & Templates: Standardizing Team Excellence

Ta treść nie jest jeszcze dostępna w Twoim języku.

Custom Rules & Templates: Standardizing Team Excellence

Section titled “Custom Rules & Templates: Standardizing Team Excellence”

Custom rules and templates in Cursor transform AI assistance from generic help into a precision tool tailored to your team’s specific needs. They ensure consistency, enforce standards, and capture institutional knowledge.

Rules are instructions that shape how Cursor’s AI behaves in your project. They can:

  • Enforce coding standards specific to your team
  • Capture domain knowledge about your business logic
  • Prevent common mistakes by encoding lessons learned
  • Accelerate development with project-specific patterns

Cursor applies rules in a specific order:

graph TD A[Global Rules
~/.cursor/rules] --> B[Workspace Rules
.cursor/rules/] B --> C[Project Rules
projectname.rules] C --> D[Inline Rules
@rules in chat] style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#bbf,stroke:#333,stroke-width:2px style C fill:#bfb,stroke:#333,stroke-width:2px style D fill:#fbf,stroke:#333,stroke-width:2px
  • Folder.cursor/ - rules/ - README.md - architecture.md - coding-standards.md - security.md - performance.md - testing.md - domain/ - authentication.md - payments.md - user-management.md - technology/ - react-patterns.md - nodejs-backend.md - database-queries.md
# [Rule Category]: [Specific Topic]
## Context
Brief description of when and why this rule applies.
## Requirements
- Specific requirement 1
- Specific requirement 2
- Specific requirement 3
## Examples
### Good Example
```language
// Code that follows the rule
```
// Code that violates the rule

Explanation of why this rule exists and its benefits.

Cases where this rule might not apply.

### Real-World Rule Examples
<Tabs>
<TabItem label="Architecture Rules">
```markdown
# Architecture: Service Layer Pattern
## Context
All business logic must be implemented in service classes, not in controllers or models.
## Requirements
- Controllers only handle HTTP concerns (request/response)
- Services contain all business logic
- Services are stateless and testable
- Services inject dependencies via constructor
- One service per domain entity
## Examples
### Good Example
```typescript
// UserController.ts
export class UserController {
constructor(private userService: UserService) {}
async createUser(req: Request, res: Response) {
const userData = req.body;
const user = await this.userService.create(userData);
res.json(user);
}
}
// UserService.ts
export class UserService {
constructor(
private userRepo: UserRepository,
private emailService: EmailService
) {}
async create(data: CreateUserDto): Promise<User> {
// Business logic here
const user = await this.userRepo.save(data);
await this.emailService.sendWelcome(user);
return user;
}
}
```
### Bad Example
```typescript
// UserController.ts - WRONG: Business logic in controller
export class UserController {
async createUser(req: Request, res: Response) {
const user = new User(req.body);
// Business logic should not be here!
if (await this.checkDuplicateEmail(user.email)) {
throw new Error('Email exists');
}
await db.users.insert(user);
await sendEmail(user.email, 'Welcome!');
res.json(user);
}
}
```
## Rationale
- Separation of concerns
- Easier testing (mock services)
- Reusable business logic
- Clear boundaries between layers
```
</TabItem>
<TabItem label="Security Rules">
```markdown
# Security: Input Validation
## Context
All user input must be validated before processing.
## Requirements
- Use validation library (Joi, Yup, Zod)
- Validate at controller level
- Sanitize strings to prevent XSS
- Use parameterized queries for SQL
- Never trust client-side validation alone
## Examples
### Good Example
```typescript
import { z } from 'zod';
const CreateUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/),
name: z.string().min(2).max(100).transform(sanitizeHtml),
age: z.number().int().min(18).max(120)
});
async createUser(req: Request, res: Response) {
try {
const validated = CreateUserSchema.parse(req.body);
const user = await this.userService.create(validated);
res.json(user);
} catch (error) {
if (error instanceof z.ZodError) {
res.status(400).json({ errors: error.errors });
}
}
}
```
### Bad Example
```typescript
// WRONG: No validation
async createUser(req: Request, res: Response) {
const user = await this.userService.create(req.body);
res.json(user);
}
// WRONG: SQL injection vulnerability
const query = `SELECT * FROM users WHERE email = '${email}'`;
```
## Exceptions
- Internal service-to-service calls may skip validation
- But always validate at system boundaries
```
</TabItem>
<TabItem label="Performance Rules">
```markdown
# Performance: Database Query Optimization
## Context
Optimize all database queries for performance.
## Requirements
- Always use indexes for WHERE clauses
- Paginate results over 100 records
- Use SELECT with specific columns, not SELECT *
- Batch operations when possible
- Monitor slow queries
## Examples
### Good Example
```typescript
// Optimized query with index usage
async findActiveUsers(page: number, limit: number = 50) {
return this.db.users
.select(['id', 'name', 'email', 'lastActive'])
.where('status', 'active')
.where('lastActive', '>', thirtyDaysAgo)
.orderBy('lastActive', 'desc')
.limit(limit)
.offset(page * limit);
}
// Batch operation
async updateMultipleUsers(updates: UserUpdate[]) {
const chunks = chunk(updates, 1000);
for (const batch of chunks) {
await this.db.transaction(async (trx) => {
await Promise.all(
batch.map(update =>
trx.users.update(update.id, update.data)
)
);
});
}
}
```
### Bad Example
```typescript
// WRONG: No pagination, SELECT *
async getAllUsers() {
return this.db.query('SELECT * FROM users');
}
// WRONG: N+1 query problem
const users = await getUsers();
for (const user of users) {
user.posts = await getPosts(user.id);
}
```
```
</TabItem>
</Tabs>
## Advanced Rule Patterns
### Dynamic Rules with Context
```markdown
# Dynamic Rule: API Response Format
## Context
API responses must follow our standard format, which varies by environment.
## Implementation
```typescript
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: {
code: string;
message: string;
details?: any;
};
metadata: {
timestamp: string;
version: string;
environment: 'dev' | 'staging' | 'prod';
};
}
// In development, include debug info
if (process.env.NODE_ENV === 'development') {
response.metadata.debug = {
query: req.query,
headers: req.headers,
processingTime: Date.now() - startTime
};
}

When generating API endpoints:

  1. Always use the ApiResponse wrapper
  2. Include appropriate error codes
  3. Add debug info in development only
  4. Log all errors with correlation IDs
### Technology-Specific Rules
<Tabs>
<TabItem label="React Rules">
```markdown
# React: Component Patterns
## Functional Components Only
Use functional components with hooks. No class components.
## Component Structure
```tsx
// 1. Imports
import React, { useState, useEffect } from 'react';
import { useUser } from '@/hooks/useUser';
import { Button } from '@/components/ui/Button';
import type { UserProps } from '@/types';
// 2. Types
interface ComponentProps {
userId: string;
onUpdate?: (user: User) => void;
}
// 3. Component
export function UserProfile({ userId, onUpdate }: ComponentProps) {
// 4. Hooks
const { user, loading, error } = useUser(userId);
const [isEditing, setIsEditing] = useState(false);
// 5. Effects
useEffect(() => {
// Effect logic
}, [userId]);
// 6. Handlers
const handleEdit = () => {
setIsEditing(true);
};
// 7. Render
if (loading) return <Spinner />;
if (error) return <ErrorDisplay error={error} />;
return (
<div>
{/* JSX */}
</div>
);
}
```
## State Management
- Use React Query for server state
- Use Zustand for client state
- Avoid prop drilling - use context sparingly
```
</TabItem>
<TabItem label="Node.js Rules">
```markdown
# Node.js: Backend Patterns
## Error Handling
```typescript
// Custom error classes
export class AppError extends Error {
constructor(
public statusCode: number,
public message: string,
public code: string
) {
super(message);
}
}
// Global error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
success: false,
error: {
code: err.code,
message: err.message
}
});
}
// Log unexpected errors
logger.error('Unexpected error:', err);
res.status(500).json({
success: false,
error: {
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred'
}
});
});
```
## Async Handler Pattern
```typescript
const asyncHandler = (fn: Function) => (
req: Request,
res: Response,
next: NextFunction
) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Usage
router.post('/users', asyncHandler(async (req, res) => {
const user = await userService.create(req.body);
res.json(user);
}));
```
```
</TabItem>
</Tabs>
## Template System
### Creating Reusable Templates
```markdown
# Template: New Microservice
When creating a new microservice, generate the following structure:
## Directory Structure

service-name/ ├── src/ │ ├── api/ │ │ ├── controllers/ │ │ ├── middlewares/ │ │ └── routes/ │ ├── core/ │ │ ├── domain/ │ │ ├── services/ │ │ └── repositories/ │ ├── infrastructure/ │ │ ├── database/ │ │ ├── cache/ │ │ └── messaging/ │ └── index.ts ├── tests/ │ ├── unit/ │ ├── integration/ │ └── e2e/ ├── .env.example ├── Dockerfile ├── docker-compose.yml └── package.json

## Base Files to Generate
1. **package.json** with our standard dependencies
2. **tsconfig.json** with our TypeScript settings
3. **Dockerfile** with multi-stage build
4. **.env.example** with required variables
5. **src/index.ts** with health check and graceful shutdown
6. Basic controller, service, and repository examples
7. Standard middleware (auth, logging, error handling)
8. Test setup with examples
// Template generator script
class TemplateGenerator {
async generateFromTemplate(templateName: string, variables: Record<string, any>) {
const template = await this.loadTemplate(templateName);
// Process template with variables
const processed = this.processTemplate(template, variables);
// Generate files
for (const file of processed.files) {
await this.createFile(file.path, file.content);
}
// Run post-generation hooks
await this.runHooks(processed.hooks);
}
private processTemplate(template: string, vars: Record<string, any>): ProcessedTemplate {
// Replace variables like {{serviceName}}
let content = template;
for (const [key, value] of Object.entries(vars)) {
const regex = new RegExp(`{{${key}}}`, 'g');
content = content.replace(regex, value);
}
// Handle conditionals
content = this.processConditionals(content, vars);
// Handle loops
content = this.processLoops(content, vars);
return this.parseToFiles(content);
}
}
  1. Establish Rule Ownership

    • Assign maintainers for each rule category
    • Create review process for rule changes
    • Version control all rules
  2. Rule Documentation

    # Rule Metadata
    - **Author**: @teamlead
    - **Created**: 2024-01-15
    - **Modified**: 2024-03-20
    - **Version**: 2.1
    - **Reviewers**: @senior-dev, @architect
    - **Affected Teams**: Backend, Frontend
  3. Rule Testing

    // Test that generated code follows rules
    describe('Architecture Rules Compliance', () => {
    test('Verify services follow dependency injection pattern', () => {
    // Create test prompt file
    const testPrompt = `
    Create a UserService following these rules:
    - Use constructor dependency injection
    - Inject Repository as a dependency
    - Do not instantiate dependencies with 'new'
    - Follow our architecture patterns from @Cursor Rules
    `;
    // Open in Cursor and manually verify the generated code
    // Use Agent mode (Ctrl+I) with the prompt above
    // Then run this test against the generated file:
    const generatedCode = fs.readFileSync('src/services/UserService.ts', 'utf8');
    expect(generatedCode).toMatch(/constructor\s*\(/);
    expect(generatedCode).toMatch(/private.*Repository/);
    expect(generatedCode).not.toMatch(/new.*Repository/);
    });
    });
  4. Rule Distribution

    • Sync rules across repositories
    • Include in onboarding documentation
    • Regular team training sessions
// Track rule compliance
class RuleComplianceTracker {
async analyzeCodebase() {
const violations = [];
// Check each rule
for (const rule of this.rules) {
const ruleViolations = await this.checkRule(rule);
violations.push(...ruleViolations);
}
// Generate report
return {
totalFiles: this.fileCount,
violations: violations,
complianceRate: this.calculateCompliance(violations),
byRule: this.groupByRule(violations),
byTeam: this.groupByTeam(violations),
};
}
}

Be Specific

Vague rules lead to inconsistent code. Include concrete examples.

Explain Why

Always include rationale. Developers follow rules they understand.

Show Examples

Good and bad examples make rules crystal clear.

Keep Updated

Review rules quarterly. Remove outdated ones, add new learnings.

  1. Over-Constraining

    ❌ Bad: "Never use forEach loops"
    ✅ Good: "Prefer map/filter/reduce for transformations. Use forEach for side effects only."
  2. Contradictory Rules

    ❌ Bad: Having both "Always use async/await" and "Use callbacks for performance"
    ✅ Good: Clear guidelines on when to use each approach
  3. Technology Lock-in

    ❌ Bad: "Always use library X for everything"
    ✅ Good: "Use library X for Y use case because Z"

Cursor can generate rules from your development sessions:

/generate-rules
Cursor will analyze this conversation and create rules based on:
- Patterns you've established
- Corrections you've made
- Preferences you've expressed
- Standards you've enforced
# Generated Rule: API Error Handling
Based on conversation from 2024-03-20
## Pattern Detected
You consistently correct API endpoints to:
1. Use try-catch blocks
2. Return standardized error responses
3. Log errors with context
4. Use appropriate HTTP status codes
## Recommended Rule
All API endpoints must implement error handling that:
- Catches all possible errors
- Returns AppError instances
- Logs with correlation IDs
- Never exposes internal errors to clients
## Code Template
[Generated template based on your corrections]
.github/workflows/rule-compliance.yml
name: Rule Compliance Check
on: [push, pull_request]
jobs:
check-rules:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Cursor Rule Checker
run: |
npx @company/cursor-rule-checker \
--rules .cursor/rules \
--source src \
--report compliance-report.json
- name: Comment PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const report = require('./compliance-report.json');
const comment = generateComplianceComment(report);
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

Master custom rules and templates:

  1. Audit Current Patterns - Identify repeated patterns in your codebase
  2. Create First Rule Set - Start with 5-10 essential rules
  3. Test with Team - Get feedback and iterate
  4. Expand Gradually - Add rules as patterns emerge

Rules and templates are living documents. They should evolve with your team’s learning and your project’s growth. Master this, and you’ll have AI assistance that truly understands your specific needs.