GitHub Copilot Rules: Best Practices for AI Coding (2026)

GitHub Copilot Rules: Best Practices for AI Coding (2026)

GitHub Copilot is one of the most popular AI coding assistants, but many developers don't know how to configure it for consistent, high-quality suggestions. While Copilot doesn't have a native .cursorrules file like Cursor, you can achieve similar results using workspace instructions and strategic comments.

This guide provides ready-to-use rules that make Copilot work better for your projects.

How GitHub Copilot Reads Context

Before diving into rules, understand how Copilot gets context:

  • Workspace files: Reads .github/copilot-instructions.md if present
  • File comments: Uses comments at the top of files
  • Open tabs: Considers code from other open files
  • Inline comments: Reads nearby comments for context
  • Codebase patterns: Learns from your existing code style

The key is placing instructions where Copilot can find them.

Setting Up Your Copilot Instructions File

Create .github/copilot-instructions.md in your repository root:

# GitHub Copilot Instructions

This file provides context for GitHub Copilot to generate better code suggestions for this project.

[Your rules go here]

Copilot will automatically reference this file when generating suggestions.

Ready-to-Use GitHub Copilot Rules

General Code Style Rules

## Code Style

- Use descriptive variable names (no single letters except loop counters)
- Prefer functional programming patterns over imperative
- Keep functions under 50 lines
- Maximum 3 levels of nesting
- Use early returns to reduce nesting
- Write self-documenting code that minimizes need for comments

TypeScript/JavaScript Rules

## TypeScript/JavaScript Standards

- Always use TypeScript strict mode
- Prefer `const` over `let`, never use `var`
- Use named exports instead of default exports
- Async functions should always handle errors with try-catch
- Use optional chaining (`?.`) and nullish coalescing (`??`)
- Prefer arrow functions for callbacks and short functions
- Use template literals instead of string concatenation

### Type Definitions
- Define interfaces for all object shapes
- Use `type` for unions and intersections
- Avoid `any`, use `unknown` when type is truly unknown
- Make types as specific as possible

React Rules

## React Conventions

- Use functional components only (no class components)
- Hooks must follow React rules (top level, consistent order)
- Extract custom hooks for reusable stateful logic
- Use TypeScript interfaces for component props
- Prefer named exports for components
- Keep components single-purpose and focused
- Use composition over inheritance

### Component Structure
```typescript
// Preferred component structure:
interface Props {
  prop1: string;
  prop2: number;
}

export const ComponentName = ({ prop1, prop2 }: Props) => {
  // Hooks first
  const [state, setState] = useState();
  
  // Event handlers
  const handleClick = () => {};
  
  // Render
  return <div>...</div>;
};

Performance

  • Use React.memo for expensive components
  • Use useMemo for expensive calculations
  • Use useCallback for functions passed to child components
  • Lazy load routes and large components

### Python Rules

``` markdown
## Python Standards

- Follow PEP 8 style guide
- Use type hints for all function signatures
- Prefer list comprehensions over map/filter when readable
- Use f-strings for string formatting
- Handle exceptions explicitly, never bare `except:`
- Use context managers (`with` statement) for resource management
- Docstrings for all public functions (Google style)

### Example Function
```python
def process_data(items: list[dict]) -> list[str]:
    """
    Process a list of data items and return formatted strings.
    
    Args:
        items: List of dictionaries containing data to process
        
    Returns:
        List of formatted string representations
        
    Raises:
        ValueError: If items list is empty
    """
    if not items:
        raise ValueError("Items list cannot be empty")
    
    return [f"{item['name']}: {item['value']}" for item in items]

### Testing Rules

```markdown
## Testing Standards

- Write tests for all business logic
- Use descriptive test names that explain what is being tested
- Follow Arrange-Act-Assert pattern
- Test happy path, edge cases, and error conditions
- Aim for 80% code coverage minimum
- Mock external dependencies
- Keep tests independent and idempotent

### Test Structure (Jest/Vitest)
```typescript
describe('ComponentName', () => {
  it('should render correctly with valid props', () => {
    // Arrange
    const props = { name: 'Test' };
    
    // Act
    render(<ComponentName {...props} />);
    
    // Assert
    expect(screen.getByText('Test')).toBeInTheDocument();
  });
  
  it('should handle error state gracefully', () => {
    // Test error condition
  });
});

### Error Handling Rules

```markdown
## Error Handling

- Always use try-catch for async operations
- Provide descriptive error messages with context
- Log errors with appropriate severity levels
- Never swallow errors silently
- Return meaningful error responses to users
- Use custom error classes for domain-specific errors

### Example Pattern
```typescript
try {
  const result = await riskyOperation();
  return { success: true, data: result };
} catch (error) {
  console.error('Operation failed:', error);
  return { 
    success: false, 
    error: 'Failed to complete operation. Please try again.' 
  };
}

### API Design Rules

```markdown
## API Design Standards

- Use RESTful conventions for HTTP APIs
- Consistent response format across all endpoints
- Proper HTTP status codes (200, 201, 400, 401, 404, 500)
- Version APIs with `/v1/` prefix in URL
- Use plural nouns for resource names
- Validate all input data before processing

### Response Format
```typescript
// Success response
{
  success: true,
  data: { ... },
  meta?: { pagination, etc }
}

// Error response
{
  success: false,
  error: "Human-readable error message",
  code: "ERROR_CODE"
}

RESTful Endpoints

  • GET /api/v1/users - List users
  • GET /api/v1/users/:id - Get specific user
  • POST /api/v1/users - Create user
  • PUT /api/v1/users/:id - Update user
  • DELETE /api/v1/users/:id - Delete user

### Security Rules

```markdown
## Security Standards

- Never commit secrets, API keys, or passwords
- Use environment variables for all sensitive configuration
- Validate and sanitize all user input
- Use parameterized queries to prevent SQL injection
- Implement rate limiting on public endpoints
- Use HTTPS for all external communications
- Follow principle of least privilege
- Keep dependencies updated and scan for vulnerabilities

### Environment Variables
```typescript
// ✅ Correct
const apiKey = process.env.API_KEY;

// ❌ Never do this
const apiKey = "sk-1234567890abcdef";

### Database Rules

```markdown
## Database Standards

- Use ORMs for type-safe database queries
- Implement soft deletes (deletedAt timestamp) where appropriate
- Add createdAt and updatedAt to all tables
- Use transactions for operations affecting multiple tables
- Create indexes for frequently queried columns
- Normalize data to reduce redundancy
- Use database migrations for schema changes

### Example Migration
```typescript
export async function up(knex: Knex): Promise<void> {
  await knex.schema.createTable('users', (table) => {
    table.uuid('id').primary();
    table.string('email').notNullable().unique();
    table.string('name').notNullable();
    table.timestamp('created_at').defaultTo(knex.fn.now());
    table.timestamp('updated_at').defaultTo(knex.fn.now());
    table.timestamp('deleted_at').nullable();
  });
}

### Documentation Rules

```markdown
## Documentation Standards

- Use JSDoc/TSDoc for public APIs
- Include @param, @returns, and @example tags
- Document complex algorithms with inline comments
- Keep README.md updated with setup and usage instructions
- Document breaking changes in CHANGELOG.md
- Add comments for "why" not "what" (code should be self-documenting)

### JSDoc Example
```typescript
/**
 * Calculates the total price including tax and discount
 * 
 * @param basePrice - The original price before calculations
 * @param taxRate - Tax rate as decimal (e.g., 0.08 for 8%)
 * @param discountPercent - Discount percentage (e.g., 10 for 10% off)
 * @returns Final price after tax and discount
 * 
 * @example
 * ```typescript
 * const total = calculateTotal(100, 0.08, 10);
 * // Returns: 97.2 (100 - 10% discount + 8% tax)
 * ```
 */
function calculateTotal(
  basePrice: number, 
  taxRate: number, 
  discountPercent: number
): number {
  const discounted = basePrice * (1 - discountPercent / 100);
  return discounted * (1 + taxRate);
}

### Git Commit Rules

```markdown
## Git Conventions

- Use Conventional Commits format
- Write clear, descriptive commit messages
- Keep commits focused and atomic
- Reference issue numbers in commits

### Commit Format

():

```

Types

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, etc)
  • refactor: Code refactoring
  • test: Adding or updating tests
  • chore: Maintenance tasks

Examples

feat(auth): add password reset functionality

Implement password reset flow with email verification
and secure token generation

Closes #123

### Performance Rules

```markdown
## Performance Standards

- Optimize images (use WebP format, lazy loading)
- Implement pagination for large lists (>50 items)
- Use database indexes for frequent queries
- Cache expensive computations and API responses
- Minimize bundle size (code splitting, tree shaking)
- Avoid unnecessary re-renders in React
- Use CDN for static assets
- Implement proper loading states

### React Performance
```typescript
// ✅ Memoize expensive calculations
const expensiveResult = useMemo(() => {
  return heavyComputation(data);
}, [data]);

// ✅ Memoize callbacks
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

// ✅ Lazy load components
const HeavyComponent = lazy(() => import('./HeavyComponent'));

### Accessibility Rules

```markdown
## Accessibility Standards (WCAG 2.1 AA)

- Use semantic HTML elements
- Provide alt text for all images
- Ensure keyboard navigation works for all interactive elements
- Maintain color contrast ratio of at least 4.5:1
- Add ARIA labels where semantic HTML isn't enough
- Support screen readers
- Don't rely on color alone to convey information
- Ensure focus indicators are visible

### Accessible Component Example
```tsx
<button
  onClick={handleDelete}
  aria-label="Delete user profile"
  className="delete-btn"
>
  <TrashIcon aria-hidden="true" />
</button>

## How to Use These Rules

### Method 1: Workspace Instructions File

Create `.github/copilot-instructions.md` and paste relevant rules:

```markdown
# Copilot Instructions

## Project: E-commerce Platform

[Paste relevant rules here based on your tech stack]

Method 2: File-Level Comments

Add rules at the top of your files:

// Copilot Instructions:
// - Use functional React components with TypeScript
// - Follow error handling patterns from project guidelines
// - Keep functions under 50 lines

import React from 'react';

Method 3: Copilot Chat

When using Copilot Chat, reference your rules:

"Following our project's TypeScript rules, create a user service that..."

Customizing Rules for Your Project

  1. Start with basics: Copy general code style and language-specific rules
  2. Add framework rules: Include React, Vue, Angular, etc. based on your stack
  3. Include project specifics: Add domain-specific patterns and conventions
  4. Keep it updated: Review and update rules as project evolves
  5. Share with team: Commit .github/copilot-instructions.md to version control

Tips for Better Copilot Suggestions

  1. Be specific: More context = better suggestions
  2. Use examples: Show Copilot the pattern you want
  3. Reference existing code: "Similar to the UserService class..."
  4. Iterate: If first suggestion isn't right, add more context
  5. Review always: Copilot is helpful but not perfect

Common Patterns by Framework

Next.js Project Rules

## Next.js Conventions

- Use App Router (not Pages Router)
- Server Components by default, add 'use client' only when needed
- Use Server Actions for mutations
- Implement proper loading.tsx and error.tsx
- Use next/image for all images
- Implement proper metadata for SEO

Express.js API Rules

## Express.js Standards

- Use async/await with express-async-errors
- Implement centralized error handling middleware
- Validate requests with express-validator
- Use helmet for security headers
- Implement rate limiting
- Structure: routes → controllers → services → repositories

Django Project Rules

## Django Conventions

- Follow Django's MVT pattern
- Use class-based views for CRUD operations
- Implement proper serializers for APIs
- Use Django ORM, avoid raw SQL
- Follow Django REST framework conventions
- Write migrations for all model changes

Troubleshooting

Copilot Not Following Rules?

  • Make sure .github/copilot-instructions.md exists in repo root
  • Try adding rules as file comments for immediate effect
  • Be more explicit in your comments
  • Reference specific examples from your codebase

Suggestions Too Generic?

  • Add more project-specific context
  • Include example code in your rules
  • Reference actual file names and patterns

Rules Conflicting?

  • Review your rules file for contradictions
  • Prioritize rules clearly (e.g., "Prefer X over Y")
  • Keep rules focused and specific

Example: Complete Instructions File

Here's a complete example for a React TypeScript project:

# GitHub Copilot Instructions

## Project Overview
E-commerce platform built with React, TypeScript, and Node.js

## Tech Stack
- Frontend: React 18, TypeScript, Tailwind CSS, React Query
- Backend: Node.js, Express, PostgreSQL, Prisma
- Testing: Vitest, React Testing Library

## Code Style
- TypeScript strict mode enabled
- Functional programming patterns preferred
- Maximum function length: 50 lines
- Use descriptive variable names

## React Conventions
- Functional components only
- Custom hooks for reusable logic
- Props interfaces defined separately
- Named exports

## API Design
- RESTful endpoints with /api/v1/ prefix
- Response format: { success, data, error }
- Proper HTTP status codes

## Error Handling
- Try-catch for all async operations
- Descriptive error messages
- Centralized error logging

## Testing
- 80% coverage target
- Test happy path and edge cases
- Use Testing Library best practices

## Security
- No hardcoded secrets
- Input validation with Zod
- Rate limiting on public endpoints

## Performance
- Lazy load routes
- React.memo for expensive components
- Paginate lists > 50 items

Related Resources

Enjoyed this article?

Share it with your network

Listings related to GitHub Copilot Rules: Best Practices for AI Coding (2026)