Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.thesozocrm.com/llms.txt

Use this file to discover all available pages before exploring further.

Cursor AI & Clean Code Guide

This guide covers how to effectively use Cursor AI coding assistant while maintaining clean code, good architecture, and team standards.

Using Cursor AI Effectively

When to Use Cursor

✅ Great For

  • Boilerplate code generation
  • Refactoring repetitive code
  • Writing tests
  • Documentation
  • Debugging assistance
  • Code explanations

❌ Not For

  • Replacing code reviews
  • Skipping understanding
  • Blindly accepting suggestions
  • Complex business logic without review
  • Security-sensitive code without validation

Cursor Best Practices

Never blindly accept AI suggestions!
  • Review every line of generated code
  • Understand what it does before committing
  • Test thoroughly before pushing
  • Ask questions if something is unclear
// ❌ Bad: Accepting AI code without review
// AI generated this, looks good, ship it!

// ✅ Good: Review and understand
// AI suggested this approach. Let me verify:
// 1. Does it handle edge cases?
// 2. Is it consistent with our patterns?
// 3. Are there security concerns?
// 4. Does it need tests?
Be specific about what you want:❌ Vague: “Fix this bug”✅ Specific: “Fix the infinite loop in useRegionAggregates hook. The issue is that regionAggregates is in the useEffect dependency array, causing re-renders. Use a stable reference key instead.”✅ Better: “Refactor this component to use useMemo instead of useState for derived values. The grouped deals should only recalculate when deals or searchTerm change, not on every render.”
Give Cursor the full picture:When asking for help, include:
  • What you’re trying to accomplish
  • What’s not working
  • Relevant code snippets
  • Error messages
  • Expected behavior
// ✅ Good prompt:
// "I'm working on the GhostTeamDailyBreakdown component.
// The hourly results aren't showing up. The data exists in Firestore
// (I checked the console), but the UI shows all zeros.
// Here's the component code: [paste code]
// Here's the service method: [paste code]"
Don’t expect perfect code on first try:
  • First response might be close but not perfect
  • Ask follow-up questions
  • Request specific improvements
  • Refine until it matches our standards
Example conversation:
  1. “Generate a service for ghost hourly results”
  2. “Add error handling with proper logging”
  3. “Make it follow our service pattern from ghostDailyResultsService”
  4. “Add JSDoc comments for all methods”
Use Cursor as a learning tool:
  • Ask “Why did you suggest this approach?”
  • Request explanations of complex code
  • Learn new patterns and techniques
  • Understand trade-offs
Don’t just copy-paste - understand the reasoning!

Cursor Prompt Templates

I'm working on [feature/component name].

**Context:**
- [What you're building]
- [Why you're building it]
- [Any constraints or requirements]

**Current Issue:**
- [What's not working]
- [Error messages if any]
- [Expected vs actual behavior]

**Relevant Code:**
[Paste relevant code snippets]

**What I Need:**
- [Specific request]
- [Follow our project patterns]
- [Include error handling]

Clean Code Principles

Code Quality Standards

Code should read like well-written prose:
// ❌ Bad: Unclear intent
const d = new Date();
const f = d.getFullYear();
const m = d.getMonth() + 1;
const r = await fetch(`/api/data?y=${f}&m=${m}`);

// ✅ Good: Clear and self-documenting
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
const monthlyData = await fetchMonthlyData(currentYear, currentMonth);
Rules:
  • Use descriptive variable names
  • Avoid abbreviations (unless universally understood)
  • Extract complex expressions into named variables
  • Use constants for magic numbers
Each function/component should do ONE thing well:
// ❌ Bad: Does too much
async function handleDealSubmit(formData) {
  // Validate
  if (!formData.customerName) return;
  // Format
  const formatted = formatDealData(formData);
  // Save
  await saveDeal(formatted);
  // Update UI
  setDeals([...deals, formatted]);
  // Send email
  await sendNotification(formatted);
  // Log
  logger.info('Deal saved');
}

// ✅ Good: Single responsibility
async function handleDealSubmit(formData) {
  const validated = validateDealForm(formData);
  if (!validated.isValid) {
    showValidationErrors(validated.errors);
    return;
  }
  
  const deal = await saveDeal(formData);
  await notifyDealCreated(deal);
  return deal;
}
Extract repeated logic into reusable functions:
// ❌ Bad: Repeated logic
const formatDeal1 = (deal) => {
  return {
    id: deal.id,
    name: deal.customerName?.trim() || 'Unknown',
    amount: deal.amount || 0,
    date: deal.date || new Date().toISOString()
  };
};

const formatDeal2 = (deal) => {
  return {
    id: deal.id,
    name: deal.customerName?.trim() || 'Unknown',
    amount: deal.amount || 0,
    date: deal.date || new Date().toISOString()
  };
};

// ✅ Good: Reusable function
function formatDeal(deal) {
  return {
    id: deal.id,
    name: deal.customerName?.trim() || 'Unknown',
    amount: deal.amount || 0,
    date: deal.date || new Date().toISOString()
  };
}
Make intentions clear:
// ❌ Bad: Implicit behavior
const dealerFee = selectedDeal?.dealerFeePercentageNew || "29.16";
// What if dealerFeePercentageNew is 0? This breaks!

// ✅ Good: Explicit checks
const dealerFee = selectedDeal?.dealerFeePercentageNew !== undefined 
  ? selectedDeal.dealerFeePercentageNew 
  : "29.16";

// ✅ Even better: Named constant
const DEFAULT_DEALER_FEE = "29.16";
const dealerFee = selectedDeal?.dealerFeePercentageNew ?? DEFAULT_DEALER_FEE;
Rules:
  • Use explicit undefined/null checks
  • Avoid truthy/falsy checks for numbers (0 is valid!)
  • Use named constants instead of magic values
  • Make edge cases obvious
Always handle errors gracefully:
// ❌ Bad: Silent failure
try {
  await riskyOperation();
} catch (error) {
  // User has no idea what happened
}

// ✅ Good: Comprehensive error handling
try {
  await riskyOperation();
  toast.success('Operation completed successfully');
} catch (error) {
  logger.error('Operation failed:', error);
  const errorMessage = handleError(error, 'Operation Name');
  toast.error(`❌ ${errorMessage}`);
  // Optionally: Report to error tracking
  reportError(error, { context: 'Operation Name' });
}
Rules:
  • Never swallow errors silently
  • Always provide user feedback
  • Log errors for debugging
  • Handle edge cases explicitly
Write efficient code:
// ❌ Bad: Unnecessary re-renders
const [grouped, setGrouped] = useState([]);

useEffect(() => {
  setGrouped(groupDealsByStage(deals, searchTerm));
}, [deals, searchTerm]);
// This causes infinite loops if grouped is used elsewhere!

// ✅ Good: Memoize derived values
const grouped = useMemo(() => {
  return groupDealsByStage(deals, searchTerm);
}, [deals, searchTerm]);
// Only recalculates when dependencies change
Rules:
  • Use useMemo for expensive calculations
  • Use useCallback for stable function references
  • Avoid unnecessary state updates
  • Don’t put derived values in state

Code Review Checklist

Before submitting code (AI-generated or not), check:

Architectural Design Principles

Project Structure

src/
├── features/              # Feature-based organization
│   ├── deals/            # Deal management feature
│   │   ├── components/   # Feature-specific components
│   │   ├── hooks/        # Feature-specific hooks
│   │   ├── pages/        # Feature pages
│   │   └── services/     # Feature-specific services
│   └── admin/            # Admin features
├── shared/               # Shared across features
│   ├── components/      # Reusable UI components
│   ├── hooks/           # Shared hooks
│   ├── services/        # Shared business logic
│   └── utils/           # Utility functions
└── core/                # Core app infrastructure
    ├── auth/            # Authentication
    ├── layout/           # Layout components
    └── routing/          # Route configuration

Design Patterns

Separate business logic from UI:
// ✅ Good: Service handles business logic
// services/dealService.js
class DealService {
  async createDeal(dealData) {
    // Validation
    const validated = this.validateDeal(dealData);
    if (!validated.isValid) {
      throw new ValidationError(validated.errors);
    }
    
    // Business logic
    const deal = this.formatDealForStorage(dealData);
    
    // Data persistence
    const docRef = await addDoc(collection(db, 'deals'), deal);
    
    // Return formatted result
    return { id: docRef.id, ...deal };
  }
}

// Component uses service
const handleSubmit = async (formData) => {
  try {
    const deal = await dealService.createDeal(formData);
    toast.success('Deal created!');
    return deal;
  } catch (error) {
    toast.error(handleError(error, 'Create Deal'));
  }
};
Benefits:
  • Reusable business logic
  • Easier to test
  • Clear separation of concerns
Extract component logic into reusable hooks:
// ✅ Good: Logic in custom hook
// hooks/useDeals.js
function useDeals(filters) {
  const [deals, setDeals] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    async function fetchDeals() {
      try {
        setLoading(true);
        const data = await dealService.getDeals(filters);
        setDeals(data);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    }
    fetchDeals();
  }, [filters]);
  
  return { deals, loading, error };
}

// Component is clean
function DealList({ filters }) {
  const { deals, loading, error } = useDeals(filters);
  
  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorMessage error={error} />;
  
  return <DealGrid deals={deals} />;
}
Build complex UIs from simple components:
// ✅ Good: Composed components
function DealCard({ deal }) {
  return (
    <Card>
      <DealHeader deal={deal} />
      <DealDetails deal={deal} />
      <DealActions deal={deal} />
    </Card>
  );
}

function DealHeader({ deal }) {
  return (
    <div className="deal-header">
      <h3>{deal.customerName}</h3>
      <StatusBadge status={deal.status} />
    </div>
  );
}

// ❌ Bad: Monolithic component
function DealCard({ deal }) {
  return (
    <div className="deal-card">
      <div className="deal-header">
        <h3>{deal.customerName}</h3>
        <span className={`status ${deal.status}`}>{deal.status}</span>
      </div>
      {/* 200 more lines... */}
    </div>
  );
}
Make components testable and flexible:
// ✅ Good: Dependencies injected
function DealList({ dealService = defaultDealService }) {
  // Can swap dealService for testing
}

// In tests
const mockService = { getDeals: jest.fn() };
render(<DealList dealService={mockService} />);

// ❌ Bad: Hard dependencies
function DealList() {
  const deals = await dealService.getDeals(); // Can't test easily
}

File Organization Rules

Feature-Based

Group related code together:
  • Components
  • Hooks
  • Services
  • Tests All in the same feature folder

Shared Code

Only put in shared/ if:
  • Used by 2+ features
  • Core infrastructure
  • Truly reusable

One Component Per File

Each component gets its own file:
  • DealCard.jsx
  • DealCard.test.jsx
  • DealCard.styles.css (if needed)

Index Exports

Use index files for clean imports:
// features/deals/index.js
export { default as DealCard } from './DealCard';
export { default as DealList } from './DealList';

// Usage
import { DealCard, DealList } from '@/features/deals';

Common Anti-Patterns to Avoid

// ❌ Bad: Infinite loop
const [data, setData] = useState([]);

useEffect(() => {
  setData(processData(data)); // data changes, triggers effect again!
}, [data]);

// ✅ Good: Stable dependencies
const processedData = useMemo(() => {
  return processData(rawData);
}, [rawData]);
// ❌ Bad: Direct mutation
deals.push(newDeal);
setDeals(deals);

// ✅ Good: Immutable update
setDeals([...deals, newDeal]);
// ❌ Bad: Missing dependencies
useEffect(() => {
  fetchData(userId); // userId not in deps!
}, []); // Empty array

// ✅ Good: Complete dependencies
useEffect(() => {
  fetchData(userId);
}, [userId]);
// ❌ Bad: Passing props through many levels
<App user={user}>
  <Layout user={user}>
    <Header user={user}>
      <UserMenu user={user} />
    </Header>
  </Layout>
</App>

// ✅ Good: Use context or state management
<UserProvider value={user}>
  <App>
    <Layout>
      <Header>
        <UserMenu /> {/* Gets user from context */}
      </Header>
    </Layout>
  </App>
</UserProvider>

Cursor + Code Review Workflow

Step-by-Step Process

1

1. Use Cursor for Initial Code

  • Ask Cursor to generate code
  • Review the generated code
  • Understand what it does
  • Ask follow-up questions if needed
2

2. Refine with Cursor

  • Request specific improvements
  • Ask for error handling
  • Request tests
  • Ensure it follows our patterns
3

3. Manual Review

  • Read through the code yourself
  • Test locally
  • Check edge cases
  • Verify error handling
4

4. Self-Review Checklist

  • Run through the code review checklist
  • Fix any issues you find
  • Remove debug code
  • Add comments where needed
5

5. Submit PR

  • Write clear PR description
  • Link to Linear issue
  • Request code review
  • Be ready to explain your code

Quick Reference

Cursor Prompt Cheat Sheet

TaskPrompt Template
Generate component”Create a React component for [name] that [does X]. Follow our project patterns from [similar component].”
Refactor code”Refactor this code to [goal]. Maintain existing functionality but [improvement].”
Add error handling”Add comprehensive error handling to this function. Include user feedback and logging.”
Write tests”Write unit tests for [function/component]. Test happy path, edge cases, and error scenarios.”
Fix bug”Fix [specific bug]. The issue is [description]. Here’s the code: [paste]“
Explain code”Explain what this code does and why it’s structured this way.”

Code Quality Checklist

  • Readable and self-documenting
  • Single responsibility
  • No code duplication
  • Explicit error handling
  • Loading states provided
  • Edge cases handled
  • Performance optimized
  • Tests written
  • No debug code
  • Follows project patterns

Resources

Clean Code Book

Robert C. Martin’s classic

React Patterns

Common React patterns

Project Docs

Check /docs folder for project-specific guides

Remember: Cursor is a powerful tool, but you’re still the developer. Review, understand, and own your code! Last Updated: November 12, 2025