Windsurf Rules: Master Flow-Based AI Development (2026)

Windsurf Rules: Master Flow-Based AI Development (2026)

Windsurf is the world's first AI-native IDE that uses a unique "Flows" system to maintain persistent context throughout your development session. Unlike traditional rules files, Windsurf's approach is more dynamic and conversational, but you still need clear guidelines to get the best results.

This guide provides ready-to-use rules and patterns that make Windsurf's Cascade AI work optimally for your projects.

Understanding Windsurf's Flow System

Windsurf is fundamentally different from other AI coding tools:

  • Flows: Persistent context that remembers your entire session
  • Cascade AI: Multi-step reasoning for complex tasks
  • Supercomplete: Context-aware autocomplete that predicts multi-line edits
  • Command Mode: Give Windsurf autonomous control for complete tasks
  • Chat Mode: Collaborative back-and-forth for guidance

The key is feeding Windsurf the right context at the start and updating it as you work.

Setting Up Your Project Flow

Initial Context Setup

When starting a new session, initialize your Flow with this template:

I'm working on [PROJECT_NAME], a [PROJECT_DESCRIPTION].

Tech Stack:
- [Language/Framework]
- [Database]
- [Key libraries]

Architecture:
- [Brief architecture description]

Current Focus:
- [What you're working on right now]

Please follow the coding standards and patterns I'll describe below.

Creating a Project Rules Document

While Windsurf doesn't have a traditional .rules file, you can create a .windsurf/context.md file in your repository:

# Windsurf Project Context

[Your rules go here - Windsurf can reference this file]

Ready-to-Use Windsurf Rules

General Flow Context Rules

## Flow Management

- Maintain context throughout the entire coding session
- Update Flow when switching between features or modules
- Reference previous decisions made in this session
- Ask for clarification before making architectural changes
- Keep track of TODO items and next steps within the Flow

Code Style Flow Rules

## Code Style Standards

Follow these conventions in all generated code:

### Naming
- Variables and functions: camelCase
- Classes and components: PascalCase
- Constants: UPPER_SNAKE_CASE
- Private methods: prefix with underscore
- Boolean variables: start with is/has/should/can

### Function Guidelines
- Maximum 50 lines per function
- Single responsibility principle
- Maximum 3 parameters (use options object for more)
- Maximum 3 levels of nesting
- Use early returns to reduce complexity

### Code Organization
- Group related functionality together
- Import order: external → internal → relative → types → styles
- One component per file (except small related components)
- Colocate tests with implementation

TypeScript/JavaScript Flow Rules

## TypeScript/JavaScript Standards

### Type Safety
- Strict mode enabled always
- No `any` types - use `unknown` if type is truly uncertain
- Define interfaces for all object shapes
- Use `type` for unions, aliases, and intersections
- Optional chaining (`?.`) and nullish coalescing (`??`) preferred

### Modern JavaScript
- Use `const` by default, `let` only when reassignment needed
- Arrow functions for callbacks and short functions
- Template literals over string concatenation
- Async/await over raw promises
- Destructuring for object and array access
- Spread operator for object/array copying

### Example Pattern
```typescript
// ✅ Preferred
interface UserData {
  id: string;
  name: string;
  email: string;
}

const fetchUser = async (id: string): Promise<UserData> => {
  const response = await api.get(`/users/${id}`);
  return response.data;
};

// ❌ Avoid
function fetchUser(id: any) {
  return new Promise((resolve, reject) => {
    api.get('/users/' + id).then(function(response) {
      resolve(response.data);
    });
  });
}

### React Flow Rules

```markdown
## React Development Patterns

### Component Structure
- Functional components only (no classes)
- TypeScript interfaces for all props
- Named exports preferred
- Props interface defined separately

### Component Template
```typescript
interface ComponentNameProps {
  prop1: string;
  prop2: number;
  onAction?: () => void;
}

export const ComponentName = ({ prop1, prop2, onAction }: ComponentNameProps) => {
  // 1. Hooks (always at top level)
  const [state, setState] = useState<Type>(initialValue);
  const queryResult = useQuery(...);
  
  // 2. Derived state and computations
  const derivedValue = useMemo(() => compute(state), [state]);
  
  // 3. Event handlers
  const handleClick = useCallback(() => {
    // handler logic
    onAction?.();
  }, [onAction]);
  
  // 4. Effects (if needed)
  useEffect(() => {
    // effect logic
    return () => cleanup();
  }, [dependencies]);
  
  // 5. Early returns for loading/error states
  if (queryResult.isLoading) return <LoadingSpinner />;
  if (queryResult.error) return <ErrorMessage />;
  
  // 6. Main render
  return (
    <div>
      {/* Component content */}
    </div>
  );
};

Performance Optimization

  • React.memo for components that render often with same props
  • useMemo for expensive calculations
  • useCallback for functions passed to child components
  • Lazy load routes and large components
  • Virtual scrolling for long lists (>100 items)

State Management

  • Local UI state: useState
  • Server state: React Query / SWR
  • Global client state: Zustand (only when necessary)
  • Form state: React Hook Form
  • URL state: Next.js router or React Router

### Python Flow Rules

```markdown
## Python Development Standards

### Style Guide
- Follow PEP 8 strictly
- Maximum line length: 88 characters (Black formatter)
- Use type hints for all function signatures
- Docstrings in Google style for all public functions

### Modern Python Patterns
```python
from typing import List, Dict, Optional
from dataclasses import dataclass

@dataclass
class User:
    """User data model."""
    id: str
    email: str
    name: str
    is_active: bool = True

def process_users(
    users: List[User],
    filter_active: bool = True
) -> List[Dict[str, str]]:
    """
    Process user list and return formatted data.
    
    Args:
        users: List of User objects to process
        filter_active: Whether to filter for active users only
        
    Returns:
        List of dictionaries with formatted user data
        
    Raises:
        ValueError: If users list is empty
    """
    if not users:
        raise ValueError("Users list cannot be empty")
    
    filtered = [u for u in users if not filter_active or u.is_active]
    return [{"id": u.id, "display": f"{u.name} ({u.email})"} for u in filtered]

Error Handling

  • Never use bare except:
  • Use specific exception types
  • Always provide context in error messages
  • Use context managers for resource management
  • Raise custom exceptions for domain errors

### Testing Flow Rules

```markdown
## Testing Standards

### Test Coverage
- Minimum 80% code coverage
- Test happy path, edge cases, and error conditions
- Integration tests for critical user flows
- E2E tests for business-critical features

### Test Structure (AAA Pattern)
```typescript
describe('UserService', () => {
  describe('createUser', () => {
    it('should create user with valid data', async () => {
      // Arrange
      const userData = { name: 'John', email: 'john@example.com' };
      const mockDb = createMockDb();
      const service = new UserService(mockDb);
      
      // Act
      const result = await service.createUser(userData);
      
      // Assert
      expect(result.success).toBe(true);
      expect(result.data.email).toBe(userData.email);
      expect(mockDb.insert).toHaveBeenCalledWith(userData);
    });
    
    it('should reject invalid email format', async () => {
      // Arrange
      const userData = { name: 'John', email: 'invalid-email' };
      const service = new UserService(createMockDb());
      
      // Act
      const result = await service.createUser(userData);
      
      // Assert
      expect(result.success).toBe(false);
      expect(result.error).toContain('Invalid email');
    });
  });
});

Testing Best Practices

  • Descriptive test names that explain what is being tested
  • Mock external dependencies (APIs, databases)
  • Tests should be independent and idempotent
  • Use test fixtures for complex setup
  • Fast tests (unit tests < 100ms, integration < 1s)

### API Design Flow Rules

```markdown
## API Development Standards

### RESTful Conventions
- Use resource-based URLs with plural nouns
- HTTP methods: GET (read), POST (create), PUT (update), DELETE (remove)
- Version APIs in URL: `/api/v1/`
- Consistent response format across all endpoints

### Response Format
```typescript
// Success response
{
  success: true,
  data: {
    // Response payload
  },
  meta?: {
    pagination?: {
      page: number,
      pageSize: number,
      totalPages: number,
      totalItems: number
    }
  }
}

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

Endpoint Patterns

GET    /api/v1/users           - List users (with pagination)
GET    /api/v1/users/:id       - Get specific user
POST   /api/v1/users           - Create new user
PUT    /api/v1/users/:id       - Update entire user
PATCH  /api/v1/users/:id       - Partial update user
DELETE /api/v1/users/:id       - Delete user

GET    /api/v1/users/:id/posts - Get user's posts (nested resource)

Status Codes

  • 200: Success
  • 201: Created
  • 204: No content (successful deletion)
  • 400: Bad request (validation error)
  • 401: Unauthorized (not authenticated)
  • 403: Forbidden (not authorized)
  • 404: Not found
  • 409: Conflict (duplicate resource)
  • 422: Unprocessable entity (semantic error)
  • 500: Internal server error

### Database Flow Rules

```markdown
## Database Standards

### Schema Design
- Use UUIDs for primary keys (or BigInt for huge scale)
- Add `created_at` and `updated_at` to all tables
- Implement soft deletes with `deleted_at` nullable timestamp
- Use foreign keys with proper constraints
- Create indexes for frequently queried columns

### Query Patterns
```typescript
// ✅ Use ORM/Query Builder
const users = await db
  .select('*')
  .from('users')
  .where('deleted_at', null)
  .where('is_active', true)
  .orderBy('created_at', 'desc')
  .limit(50);

// ❌ Avoid raw SQL strings (SQL injection risk)
const users = await db.raw(`SELECT * FROM users WHERE email = '${email}'`);

// ✅ If raw SQL needed, use parameterized queries
const users = await db.raw('SELECT * FROM users WHERE email = ?', [email]);

Transactions

  • Use transactions for operations affecting multiple tables
  • Keep transactions short to avoid locks
  • Always handle transaction rollback on errors

Migrations

  • Never edit existing migrations
  • Always create new migration for schema changes
  • Test migrations on copy of production data
  • Include both up and down migrations

### Security Flow Rules

```markdown
## Security Standards

### Environment & Secrets
- Never commit secrets, API keys, or passwords to git
- Use environment variables for all sensitive config
- Different .env files for dev/staging/prod
- Add .env to .gitignore immediately

### Input Validation
```typescript
// ✅ Validate all user input
import { z } from 'zod';

const UserSchema = z.object({
  email: z.string().email(),
  age: z.number().min(18).max(120),
  name: z.string().min(2).max(100)
});

// This throws if validation fails
const validatedData = UserSchema.parse(untrustedInput);

SQL Injection Prevention

  • Always use parameterized queries
  • Never concatenate user input into SQL strings
  • Use ORM/query builder properly

XSS Prevention

  • Sanitize user input before rendering
  • Use Content Security Policy headers
  • Escape HTML in user-generated content

Authentication & Authorization

  • Hash passwords with bcrypt (cost factor 12+)
  • Use JWT for stateless auth or sessions for stateful
  • Implement rate limiting on auth endpoints
  • Require re-authentication for sensitive operations

HTTPS & Headers

  • Always use HTTPS in production
  • Set security headers (helmet.js for Express)
  • Implement CORS properly
  • Set appropriate cache headers

### Error Handling Flow Rules

```markdown
## Error Handling Patterns

### Async Error Handling
```typescript
// ✅ Always use try-catch with async/await
async function fetchUserData(id: string): Promise<Result<User>> {
  try {
    const response = await api.get(`/users/${id}`);
    return { success: true, data: response.data };
  } catch (error) {
    console.error('Failed to fetch user:', error);
    
    if (error.response?.status === 404) {
      return { success: false, error: 'User not found' };
    }
    
    return { 
      success: false, 
      error: 'Failed to fetch user data. Please try again.' 
    };
  }
}

Custom Error Classes

class ValidationError extends Error {
  constructor(
    message: string,
    public field: string,
    public value: any
  ) {
    super(message);
    this.name = 'ValidationError';
  }
}

class NotFoundError extends Error {
  constructor(resource: string, id: string) {
    super(`${resource} with id ${id} not found`);
    this.name = 'NotFoundError';
  }
}

Error Logging

  • Log errors with full context
  • Include stack traces in development
  • Sanitize sensitive data before logging
  • Use structured logging (JSON format)
  • Different log levels: error, warn, info, debug

### Performance Flow Rules

```markdown
## Performance Optimization

### Frontend Performance
- Lazy load routes and components
- Code splitting for large bundles
- Optimize images (WebP format, next/image)
- Implement virtual scrolling for long lists
- Use CDN for static assets
- Cache API responses appropriately
- Minimize main thread blocking

### Database Performance
- Add indexes for WHERE, JOIN, ORDER BY columns
- Use connection pooling
- Implement query result caching
- Paginate large datasets
- Avoid N+1 queries (use eager loading)
- Monitor slow queries

### API Performance
- Implement response caching (Redis)
- Use compression (gzip/brotli)
- Rate limiting to prevent abuse
- Batch similar requests when possible
- Implement proper pagination

Documentation Flow Rules

## Documentation Standards

### Code Documentation
```typescript
/**
 * Calculates the discounted price with tax applied.
 * 
 * This function first applies the discount percentage to the base price,
 * then adds the appropriate tax based on the tax rate.
 * 
 * @param basePrice - The original price before any modifications
 * @param discountPercent - Discount as a percentage (0-100)
 * @param taxRate - Tax rate as a decimal (e.g., 0.08 for 8%)
 * @returns The final price after discount and tax
 * 
 * @throws {Error} If basePrice is negative
 * @throws {Error} If discountPercent is not between 0 and 100
 * 
 * @example
 * ```typescript
 * const finalPrice = calculatePrice(100, 10, 0.08);
 * // Result: 97.2 (100 - 10% discount, then + 8% tax)
 * ```
 */
function calculatePrice(
  basePrice: number,
  discountPercent: number,
  taxRate: number
): number {
  if (basePrice < 0) throw new Error('Base price cannot be negative');
  if (discountPercent < 0 || discountPercent > 100) {
    throw new Error('Discount must be between 0 and 100');
  }
  
  const discounted = basePrice * (1 - discountPercent / 100);
  return discounted * (1 + taxRate);
}

Project Documentation

  • README.md with setup instructions
  • Architecture decision records (ADRs)
  • API documentation (OpenAPI/Swagger)
  • Changelog for version tracking
  • Contributing guidelines

## How to Use These Rules in Windsurf

### Method 1: Initial Flow Context

Start each session by providing context:

Hi Windsurf! I'm working on an e-commerce platform.

Tech Stack: React, TypeScript, Next.js 14, PostgreSQL, Prisma

Follow these standards:

  • Functional React components
  • TypeScript strict mode
  • RESTful API design
  • 80% test coverage

Currently working on: User authentication flow

Let's begin!


### Method 2: Create Context File

Create `.windsurf/context.md`:

```markdown
# Project Context for Windsurf

[Paste relevant rules from this guide]

## Current Sprint Goals
- [ ] Implement user authentication
- [ ] Add payment processing
- [ ] Create admin dashboard

Reference it: "Follow the guidelines in .windsurf/context.md"

Method 3: Update Flow Mid-Session

When changing focus:

Update Flow: We've completed the auth system. 
Now focusing on payment integration with Stripe.
Continue following our coding standards.

Method 4: Use Command Mode for Big Tasks

Give Windsurf autonomy:

Command Mode: Create a complete user profile editing feature following our React and TypeScript standards. Include:
- Profile form component
- Image upload with preview
- Form validation with Zod
- API integration
- Loading and error states
- Unit tests

Windsurf-Specific Tips

Leverage Cascade AI

Windsurf's Cascade AI can handle multi-step reasoning:

"Create a blog post feature. Think through:
1. Database schema design
2. API endpoints needed
3. React components structure
4. State management approach
5. Testing strategy

Then implement following our project standards."

Use Supercomplete Effectively

Supercomplete learns from your patterns:

  • Be consistent with your code style
  • Windsurf will predict multi-line edits matching your patterns
  • Accept good suggestions, reject bad ones to train it

Command vs Chat Mode

Use Command Mode when:

  • Creating new features from scratch
  • Refactoring across multiple files
  • You trust Windsurf with autonomous decisions

Use Chat Mode when:

  • Exploring options
  • Need to discuss approach
  • Want step-by-step collaboration
  • Unsure about implementation details

Framework-Specific Rules

## Next.js Standards

- Use App Router (not Pages Router)
- Server Components by default
- Add 'use client' only when needed (hooks, browser APIs)
- Use Server Actions for mutations
- Implement loading.tsx and error.tsx
- Proper metadata for SEO

File Structure

app/
  ├── (auth)/
  │   ├── login/
  │   │   └── page.tsx
  │   └── register/
  │       └── page.tsx
  ├── dashboard/
  │   ├── layout.tsx
  │   ├── page.tsx
  │   ├── loading.tsx
  │   └── error.tsx
  └── api/
      └── v1/
          └── users/
              └── route.ts

Django Rules

## Django Standards

- Follow MVT pattern strictly
- Use class-based views for CRUD
- Django REST framework for APIs
- Serializers for all API responses
- Use Django ORM (avoid raw SQL)
- Proper migrations for all model changes

Project Structure

project/
  ├── apps/
  │   ├── users/
  │   │   ├── models.py
  │   │   ├── views.py
  │   │   ├── serializers.py
  │   │   └── tests/
  │   └── posts/
  ├── config/
  │   ├── settings/
  │   └── urls.py
  └── manage.py

Troubleshooting

Windsurf Not Following Your Style?

Solution: Be more explicit in initial Flow setup. Provide examples of your preferred patterns.

Context Getting Lost?

Solution: Periodically update your Flow with "Still following our TypeScript standards..." to reinforce context.

Too Many Changes at Once?

Solution: Switch from Command Mode to Chat Mode for more control. Break tasks into smaller pieces.

Suggestions Don't Match Project?

Solution: Reference specific files: "Following the pattern in UserService.ts, create OrderService"

Complete Example: E-commerce Project Setup

Here's a complete Flow initialization for a new e-commerce project:

Hi Windsurf! Starting a new e-commerce platform project.

## Tech Stack
- Frontend: React 18, TypeScript, Next.js 14, Tailwind CSS
- Backend: Node.js, Express, PostgreSQL
- ORM: Prisma
- Testing: Vitest, React Testing Library
- State: React Query for server state, Zustand for global client state

## Architecture
Clean architecture with layers:
- /app - Next.js pages and routes
- /components - Reusable React components
- /lib - Business logic and services
- /db - Database schemas and migrations

## Coding Standards
- TypeScript strict mode
- Functional components only
- Max 50 lines per function
- 80% test coverage
- RESTful API with /api/v1/ prefix

## Current Focus
Building the core product catalog feature with:
- Product listing with pagination
- Product detail pages
- Search and filtering
- Shopping cart

Follow these standards in all generated code. Let's start with the product database schema.

Related Resources

Enjoyed this article?

Share it with your network

Listings related to Windsurf Rules: Master Flow-Based AI Development (2026)