Back to blog

AI in Development: How GitHub Copilot and Cursor Are Changing the Way We Code in 2025

Hey HaWkers, 78% of organizations already use or plan to use AI in software development in 2025 (source: recent research). Tools like GitHub Copilot, Cursor, Claude Code, and others are revolutionizing developer productivity.

But are these tools really worth it? Or are they just hype? How can you make the most of them without becoming dependent?

The Current Landscape of AI-Assisted Development

Main Tools in 2025

// Comparison of AI development tools

const aiDevelopmentTools = {
  githubCopilot: {
    provider: "GitHub (Microsoft/OpenAI)",
    models: ["GPT-4", "Codex"],
    integration: "VS Code, JetBrains, Neovim",
    pricing: "$10/month (individual), $19/month (business)",
    strengths: [
      "Best inline autocomplete",
      "Native GitHub integration",
      "Multi-language support",
      "Context-aware suggestions",
    ],
    weaknesses: ["Less control over model", "No advanced chat (without X)"],
    marketShare: "65%",
  },

  cursor: {
    provider: "Anysphere (ex-OpenAI engineers)",
    models: ["GPT-4", "Claude Sonnet 3.5", "Custom models"],
    integration: "VS Code fork (standalone)",
    pricing: "$20/month (Pro), $40/month (Business)",
    strengths: [
      "Multi-file editing",
      "Codebase-aware chat",
      "Composer mode (generates complete features)",
      "Choice of models (GPT-4, Claude, etc)",
    ],
    weaknesses: ["Need to switch editors", "More expensive than Copilot"],
    marketShare: "20%",
  },

  claudeCode: {
    provider: "Anthropic",
    models: ["Claude Sonnet 4.5"],
    integration: "Terminal, Web interface",
    pricing: "Included in Claude Pro plan ($20/month)",
    strengths: [
      "Best model for complex coding tasks",
      "Executes terminal commands",
      "Edits multiple files",
      "Advanced reasoning",
    ],
    weaknesses: ["No direct editor integration", "Less autocomplete"],
    marketShare: "8%",
  },

  tabnine: {
    provider: "Tabnine",
    models: ["Custom models + GPT"],
    integration: "VS Code, JetBrains, vim",
    pricing: "$12/month (Pro)",
    strengths: ["Privacy-first (trains on your private code)", "On-premise"],
    weaknesses: ["Quality inferior to leaders"],
    marketShare: "5%",
  },

  codewhisperer: {
    provider: "Amazon",
    models: ["Custom models"],
    integration: "VS Code, JetBrains, AWS Cloud9",
    pricing: "Free (individual tier), $19/month (Professional)",
    strengths: ["Free for individual use", "AWS integration"],
    weaknesses: ["Inferior quality", "AWS focus"],
    marketShare: "2%",
  },
};

GitHub Copilot: The Matured Pioneer

How It Works in Practice

// Real productivity example with GitHub Copilot

// 1. Intelligent autocomplete
// You type:
async function fetchUserData

// Copilot suggests (Tab to accept):
async function fetchUserData(userId: string): Promise<User> {
  try {
    const response = await fetch(`/api/users/${userId}`);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching user data:', error);
    throw error;
  }
}

// 2. Test generation (write descriptive comment)
// Generate unit tests for fetchUserData function with edge cases

// Copilot generates:
describe("fetchUserData", () => {
  it("should fetch user data successfully", async () => {
    const mockUser = { id: "123", name: "John", email: "john@example.com" };

    global.fetch = jest.fn(() =>
      Promise.resolve({
        ok: true,
        json: () => Promise.resolve(mockUser),
      })
    ) as jest.Mock;

    const result = await fetchUserData("123");
    expect(result).toEqual(mockUser);
  });

  it("should throw error on HTTP error", async () => {
    global.fetch = jest.fn(() =>
      Promise.resolve({
        ok: false,
        status: 404,
      })
    ) as jest.Mock;

    await expect(fetchUserData("123")).rejects.toThrow("HTTP error! status: 404");
  });

  it("should handle network errors", async () => {
    global.fetch = jest.fn(() =>
      Promise.reject(new Error("Network error"))
    ) as jest.Mock;

    await expect(fetchUserData("123")).rejects.toThrow("Network error");
  });
});

// 3. Assisted refactoring
// Copilot detects duplicated code and suggests extracting function
function calculateDiscount(price: number, userType: string): number {
  if (userType === "premium") {
    return price * 0.8; // 20% discount
  } else if (userType === "regular") {
    return price * 0.95; // 5% discount
  }
  return price;
}

// Copilot suggests refactor to strategy pattern when you start typing
interface DiscountStrategy {
  calculate(price: number): number;
}

class PremiumDiscountStrategy implements DiscountStrategy {
  calculate(price: number): number {
    return price * 0.8;
  }
}

class RegularDiscountStrategy implements DiscountStrategy {
  calculate(price: number): number {
    return price * 0.95;
  }
}

class NoDiscountStrategy implements DiscountStrategy {
  calculate(price: number): number {
    return price;
  }
}

Use Cases Where Copilot Shines

// 1. Boilerplate and repetitive code
// Writing API routes in Next.js

// You type:
// POST /api/users - create new user

// Copilot generates complete structure:
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import db from "@/lib/db";

const createUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  password: z.string().min(8),
});

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();

    // Validate input
    const validatedData = createUserSchema.parse(body);

    // Check if user exists
    const existingUser = await db.user.findUnique({
      where: { email: validatedData.email },
    });

    if (existingUser) {
      return NextResponse.json(
        { error: "User already exists" },
        { status: 400 }
      );
    }

    // Hash password
    const hashedPassword = await bcrypt.hash(validatedData.password, 10);

    // Create user
    const user = await db.user.create({
      data: {
        ...validatedData,
        password: hashedPassword,
      },
    });

    return NextResponse.json(
      { id: user.id, name: user.name, email: user.email },
      { status: 201 }
    );
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({ error: error.errors }, { status: 400 });
    }

    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}

// 2. Complex SQL queries
// Generate SQL query to get top 10 products by revenue in last 30 days

const query = `
  SELECT
    p.id,
    p.name,
    SUM(oi.quantity * oi.price) as total_revenue
  FROM products p
  JOIN order_items oi ON p.id = oi.product_id
  JOIN orders o ON oi.order_id = o.id
  WHERE o.created_at >= NOW() - INTERVAL '30 days'
    AND o.status = 'completed'
  GROUP BY p.id, p.name
  ORDER BY total_revenue DESC
  LIMIT 10;
`;

// 3. Regex patterns
// Validate Brazilian CPF format

function validateCPF(cpf: string): boolean {
  // Remove non-digits
  const cleanCPF = cpf.replace(/\D/g, "");

  // CPF must have 11 digits
  if (cleanCPF.length !== 11) return false;

  // Check for known invalid CPFs (all same digit)
  if (/^(\d)\1{10}$/.test(cleanCPF)) return false;

  // Validate check digits
  let sum = 0;
  for (let i = 0; i < 9; i++) {
    sum += parseInt(cleanCPF.charAt(i)) * (10 - i);
  }
  let checkDigit = 11 - (sum % 11);
  if (checkDigit >= 10) checkDigit = 0;
  if (checkDigit !== parseInt(cleanCPF.charAt(9))) return false;

  sum = 0;
  for (let i = 0; i < 10; i++) {
    sum += parseInt(cleanCPF.charAt(i)) * (11 - i);
  }
  checkDigit = 11 - (sum % 11);
  if (checkDigit >= 10) checkDigit = 0;
  if (checkDigit !== parseInt(cleanCPF.charAt(10))) return false;

  return true;
}

Cursor: The New Challenger

Composer Mode: Generating Complete Features

// Cursor Composer: you describe the feature and it generates multiple files

// Prompt in Cursor Composer:
// "Create a shopping cart feature with add/remove items, quantity update,
// and total calculation. Include TypeScript types, React components, and tests."

// Cursor automatically generates:

// types/cart.ts
export interface CartItem {
  id: string;
  productId: string;
  name: string;
  price: number;
  quantity: number;
  imageUrl: string;
}

export interface Cart {
  items: CartItem[];
  total: number;
  itemCount: number;
}

// hooks/use-cart.ts
import { create } from "zustand";
import { persist } from "zustand/middleware";

interface CartStore extends Cart {
  addItem: (item: Omit<CartItem, "quantity">) => void;
  removeItem: (productId: string) => void;
  updateQuantity: (productId: string, quantity: number) => void;
  clearCart: () => void;
}

export const useCart = create<CartStore>()(
  persist(
    (set) => ({
      items: [],
      total: 0,
      itemCount: 0,

      addItem: (item) =>
        set((state) => {
          const existingItem = state.items.find(
            (i) => i.productId === item.productId
          );

          if (existingItem) {
            return {
              items: state.items.map((i) =>
                i.productId === item.productId
                  ? { ...i, quantity: i.quantity + 1 }
                  : i
              ),
            };
          }

          return {
            items: [...state.items, { ...item, quantity: 1 }],
          };
        }),

      removeItem: (productId) =>
        set((state) => ({
          items: state.items.filter((i) => i.productId !== productId),
        })),

      updateQuantity: (productId, quantity) =>
        set((state) => ({
          items: state.items.map((i) =>
            i.productId === productId ? { ...i, quantity } : i
          ),
        })),

      clearCart: () => set({ items: [], total: 0, itemCount: 0 }),
    }),
    { name: "cart-storage" }
  )
);

// components/cart.tsx
"use client";

import { useCart } from "@/hooks/use-cart";
import { CartItem } from "./cart-item";

export function Cart() {
  const { items, total, itemCount } = useCart();

  if (items.length === 0) {
    return (
      <div className="p-6 text-center">
        <p>Your cart is empty</p>
      </div>
    );
  }

  return (
    <div>
      <h2>Shopping Cart ({itemCount} items)</h2>

      <div className="space-y-4">
        {items.map((item) => (
          <CartItem key={item.id} item={item} />
        ))}
      </div>

      <div className="border-t pt-4 mt-4">
        <div className="flex justify-between text-xl font-bold">
          <span>Total:</span>
          <span>${total.toFixed(2)}</span>
        </div>

        <button className="w-full mt-4 bg-blue-600 text-white py-2 rounded">
          Proceed to Checkout
        </button>
      </div>
    </div>
  );
}

// __tests__/cart.test.ts
import { renderHook, act } from "@testing-library/react";
import { useCart } from "@/hooks/use-cart";

describe("useCart", () => {
  beforeEach(() => {
    const { result } = renderHook(() => useCart());
    act(() => {
      result.current.clearCart();
    });
  });

  it("should add item to cart", () => {
    const { result } = renderHook(() => useCart());

    act(() => {
      result.current.addItem({
        id: "1",
        productId: "prod-1",
        name: "Test Product",
        price: 29.99,
        imageUrl: "/test.jpg",
      });
    });

    expect(result.current.items).toHaveLength(1);
    expect(result.current.items[0].quantity).toBe(1);
  });

  it("should increment quantity when adding existing item", () => {
    const { result } = renderHook(() => useCart());

    const item = {
      id: "1",
      productId: "prod-1",
      name: "Test Product",
      price: 29.99,
      imageUrl: "/test.jpg",
    };

    act(() => {
      result.current.addItem(item);
      result.current.addItem(item);
    });

    expect(result.current.items).toHaveLength(1);
    expect(result.current.items[0].quantity).toBe(2);
  });

  // ... more tests
});

Codebase-Aware Chat

// Cursor understands your ENTIRE codebase

// You ask in chat:
// "Where is user authentication handled? Show me the flow from login to token storage."

// Cursor analyzes your code and responds:
/*
User authentication flow:

1. Login form submission:
   - app/login/page.tsx:45
   - Calls handleLogin() function

2. API call to authenticate:
   - lib/auth.ts:12
   - POST /api/auth/login with credentials

3. Server-side verification:
   - app/api/auth/login/route.ts:23
   - Validates credentials against database
   - Generates JWT token using lib/jwt.ts:8

4. Token storage:
   - lib/auth.ts:34
   - Stores in httpOnly cookie
   - Also stores in localStorage for client-side checks

5. Session management:
   - middleware.ts:15
   - Validates token on each request
   - Refreshes if expiring soon

Key files:
- app/login/page.tsx
- lib/auth.ts
- app/api/auth/login/route.ts
- middleware.ts
*/

// And shows code snippets from each relevant file!

Practical Comparison: Copilot vs Cursor vs Claude Code

Real Scenario: Implementing Comment Feature

// Task: "Implement comment system with replies, likes, and moderation"

// === GITHUB COPILOT ===
// Strengths: Excellent for line-by-line autocomplete
// You write descriptive comments and it generates code incrementally

// Comment component with nested replies
interface Comment {
  id: string;
  // Copilot autocompletes entire interface
  content: string;
  authorId: string;
  parentId: string | null;
  likes: number;
  createdAt: Date;
  replies: Comment[];
}

// Time: ~15 minutes (writing incrementally)
// Quality: High, but requires constant guidance
// Advantage: Perfect GitHub integration

// === CURSOR COMPOSER ===
// Strengths: Generates complete feature at once

// You describe in Composer:
// "Create comment system with nested replies (max 3 levels),
// likes, reporting, and admin moderation panel"

// Cursor generates in ~2 minutes:
// - types/comment.ts
// - hooks/use-comments.ts
// - components/comment-thread.tsx
// - components/comment-form.tsx
// - components/comment-moderation.tsx
// - app/api/comments/route.ts
// - __tests__/comments.test.tsx

// Time: ~2-3 minutes
// Quality: High, but may need adjustments
// Advantage: Speed for complete features

// === CLAUDE CODE ===
// Strengths: Complex reasoning, debugging, architecture

// You describe the problem:
// "I need a scalable comment system. Users report performance issues
// when posts have 1000+ comments. Design efficient solution."

// Claude Code analyzes and proposes:
/*
Architecture recommendation:

1. Database optimization:
   - Denormalize reply_count and like_count
   - Index on (post_id, created_at, parent_id)
   - Partition by date for old comments

2. API design:
   - Paginated endpoints (20 comments/page)
   - Lazy load nested replies on demand
   - Separate endpoint for like counts

3. Caching strategy:
   - Redis cache for hot posts (1000+ views/day)
   - Cache comment tree structure
   - Invalidate on new comment/like

4. Frontend optimization:
   - Virtual scrolling for long threads
   - Optimistic updates for likes
   - Skeleton loading for better UX

I'll implement this. Should I proceed?
*/

// Time: ~5-10 minutes (includes architecture explanation)
// Quality: Excellent for architectural decisions
// Advantage: Thinking + execution

When to Use Each Tool

const toolRecommendations = {
  useGithubCopilot: [
    "Daily autocomplete (line by line)",
    "Generate boilerplate quickly",
    "Write unit tests",
    "Refactor existing code",
    "Document code (JSDoc, comments)",
  ],

  useCursor: [
    "Generate complete features quickly",
    "Edit multiple files simultaneously",
    "Understand new/complex codebase",
    "Migrate code between frameworks",
    "Prototype MVPs quickly",
  ],

  useClaudeCode: [
    "Complex debugging",
    "Architectural decisions",
    "Code review and optimization",
    "Understand legacy code",
    "Plan large refactoring",
  ],

  idealSetup: "Use all 3 together as needed",
};

Impact on Productivity: Real Data

Developer Metrics in 2025

// Surveys and studies from 2025

const productivityMetrics = {
  githubCopilotStudy: {
    source: "GitHub/Microsoft Research 2025",
    participants: 5000,
    findings: {
      codeCompletionAcceptance: "35-45%", // Developers accept suggestions
      timeToComplete: "-40% vs without Copilot",
      bugIntroduction: "No significant increase",
      developerSatisfaction: "88% report higher satisfaction",
      mostUsedFor: [
        "Boilerplate (89%)",
        "Tests (76%)",
        "Documentation (71%)",
      ],
    },
  },

  cursorUserSurvey: {
    source: "Stack Overflow Survey 2025",
    participants: 2000,
    findings: {
      productivityIncrease: "55% report >30% gain",
      featureDeliverySpeed: "2-3x faster for MVPs",
      learningCurve: "2-3 weeks to master",
      switchFromVSCode: "85% wouldn't go back",
    },
  },

  industryTrends: {
    aiAdoptionRate: "78% of companies",
    companiesMandatingAI: "42% mandate AI tools usage",
    budgetAllocation: "$500-2000/dev/year for AI tools",
    roiEstimate: "3-5x return on productivity",
  },
};

// Real-world case study (mid-size company)
const realWorldExample = {
  company: "SaaS Startup (15 devs)",
  before: {
    featuresPerSprint: 8,
    bugFixTime: "2-3 days average",
    onboardingTime: "3-4 weeks",
    codeReviewTime: "4-6 hours/PR",
  },
  afterAITools: {
    featuresPerSprint: 12, // +50%
    bugFixTime: "1-2 days", // -40%
    onboardingTime: "1-2 weeks", // -50%
    codeReviewTime: "2-3 hours/PR", // -40%
  },
  toolsUsed: ["GitHub Copilot (all)", "Cursor (4 devs)", "Claude Pro (2 devs)"],
  monthlyInvestment: "$450 (Copilot) + $240 (Cursor) = $690",
  estimatedROI: "~$25,000/month in productivity",
};

Best Practices for Using AI in Development

// Guide on how to make the most without developing bad habits

const bestPractices = {
  dosAndDonts: {
    do: [
      "✅ Use AI for boilerplate and repetitive tasks",
      "✅ Always review generated code (security, performance)",
      "✅ Use as learning tool (understand what was generated)",
      "✅ Customize prompts for your context",
      "✅ Combine multiple tools as needed",
    ],

    dont: [
      "❌ Blindly trust generated code",
      "❌ Use AI for critical systems without review",
      "❌ Copy/paste without understanding",
      "❌ Replace learning with AI (complement, don't substitute)",
      "❌ Ignore testing AI-generated code",
    ],
  },

  securityChecklist: [
    "Never include secrets/tokens in prompts",
    "Review suggested dependencies (known vulnerabilities?)",
    "Validate generated inputs (SQL injection, XSS, etc)",
    "Use linters and automatic scanners",
    "Human code review always necessary",
  ],

  learningApproach: [
    "Ask for explanations: 'Explain this code step by step'",
    "Compare approaches: 'Show alternative implementations'",
    "Learn patterns: 'Why is this pattern better?'",
    "Don't just accept suggestions - question and learn",
  ],
};

// Example of effective prompts
const effectivePrompts = {
  bad: "create an api",
  good: `Create a REST API endpoint for user registration with:
  - Input validation (Zod schema)
  - Password hashing (bcrypt)
  - Duplicate email check
  - Return JWT token
  - Error handling with proper HTTP status codes
  - TypeScript types
  - Unit tests`,

  bad: "fix this bug",
  good: `Debug this issue:

  Error: "Cannot read property 'name' of undefined"
  File: components/UserProfile.tsx:42

  Context:
  - User object comes from API
  - Sometimes API returns null
  - Need graceful handling

  Requirements:
  - Add proper null checks
  - Show loading state
  - Display error message if user not found`,
};

Conclusion: AI as Superpower, Not Substitute

AI-assisted development isn't about replacing developers — it's about amplifying capabilities.

Reality in 2025:

  • Productivity: Proven gains of 30-60%
  • Adoption: 78% of companies already using
  • Cost-benefit: 3-5x ROI
  • Career: Devs who master AI tools earn 15-25% more

Recommended tools:

  1. GitHub Copilot → Daily autocomplete (mandatory)
  2. Cursor → Quick features and codebase exploration (highly recommended)
  3. Claude Code → Architecture and complex debugging (differentiator)

If you want to understand more about how AI is transforming the market, I recommend checking out another article: Software Developer Career in 2025: AI Impact where you'll discover how to adapt to the new landscape.

Let's go!

📚 Want to Deepen Your JavaScript Knowledge?

This article covered AI tools, but mastering solid JavaScript is the foundation for everything.

Developers who invest in structured knowledge tend to have more opportunities in the market.

Complete Study Material

If you want to master JavaScript from basic to advanced, I've prepared a complete guide:

Investment options:

  • 3x $34.54 BRL on credit card
  • or $97.90 BRL cash

👉 Check out the JavaScript Guide

💡 Material updated with market best practices

Comments (0)

This article has no comments yet 😢. Be the first! 🚀🦅

Add comments