---
title: "How I Improved My Blog with Vercel Agent Skills and React Best Practices"
date: "2026-01-16"
slug: "improving-projects-with-agent-skills-react-best-practices"
author: "Dany Paredes"
canonical: "https://danywalls.com/improving-projects-with-agent-skills-react-best-practices"
description: "How to use Vercel Agent Skills in Cursor, Claude Code, and AI IDEs to automatically apply 40+ React 19 and Next.js performance rules to eliminate waterfalls and optimize re-renders."
---


Early this year, Vercel released a dedicated **Agent Skill** containing their internal playbook for **React Best Practices**.

I thought: *Who better than Vercel to teach AI assistants how to write top-tier React? They built Next.js and pushed the React Server Components ecosystem forward.* I wondered how their collective engineering wisdom could audit and improve my blog.

So I ran one command, and the findings completely transformed how I review and optimize React code with AI.

In this guide, I'll walk you through how **Agent Skills** work, the most critical performance anti-patterns the agent flagged in my codebase with before/after code examples, and how you can run this audit in your own projects in under two minutes.

---

## The Problem: "Working" Code vs. "Optimized" Code

My blog was already running Next.js 16 and React 19. The build passed cleanly, ESLint reported 0 errors, and pages loaded smoothly. But as developers, we know that passing tests don't guarantee peak performance.

I had several nagging questions:
- Was I accidentally creating request waterfalls in Server Components?
- Were client-side state hooks triggering unnecessary re-render cascades?
- Could bundle sizes for dynamic routes be trimmed down?
- Were interactive elements adhering to strict WCAG accessibility standards?

These aren't syntax errors that break your build. They are silent performance bottlenecks that compound over time and degrade Core Web Vitals.

Now let's explore how Agent Skills solve this problem.

---

## What Are Agent Skills and Why Do They Matter?

Generic AI models often hallucinate legacy React patterns—like unnecessary `useEffect` data fetching or manual `useCallback` wrapping everywhere.

**Agent Skills** bridge this gap. They are curated, structured instruction sets that teach AI assistants (like Cursor, Claude Code, and Antigravity) exact engineering guidelines:

| Priority Tier | Focus Area | Real-World Impact |
| :--- | :--- | :--- |
| 🚨 **CRITICAL** | Eliminate Request Waterfalls | Concurrency with `Promise.all` instead of serial `await` |
| ⚡ **HIGH** | Server Components & Data Fetching | Reduced client bundle size & instant TTFB |
| 🎯 **MEDIUM** | Re-render Optimization | Derived state with `useMemo` instead of sync `useEffect` |
| 🎨 **LOW** | Code Cleanliness | Naming conventions & idiomatic TypeScript |

By adding the **[vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills)** repository, the AI gains instant access to 40+ battle-tested rules ordered strictly by impact.

Let's look at how simple the setup is.

---

## Installing the Skill in 30 Seconds

Installing the Vercel React Best Practices skill requires a single command:

```bash
npx add-skill vercel-labs/agent-skills
```

Once installed, your AI agent automatically references the skill files inside your editor.

Now let's look at the real-world anti-patterns the agent caught in my code.

---

## 3 Critical React Anti-Patterns the Agent Caught

### 1. Eliminating Async Request Waterfalls (Impact: CRITICAL)

The agent immediately flagged a sequential `await` waterfall in one of my server data loaders:

#### ❌ Before (Sequential Waterfall: ~650ms)
```typescript
// Each request waits for the previous one to finish!
export async function getDashboardData(userId: string) {
  const profile = await fetchUserProfile(userId);      // 200ms
  const posts = await fetchUserPosts(userId);          // 300ms
  const analytics = await fetchUserAnalytics(userId);  // 150ms

  return { profile, posts, analytics };
}
```

#### ✅ After (Parallel Execution: ~300ms)
```typescript
// All requests run concurrently!
export async function getDashboardData(userId: string) {
  const [profile, posts, analytics] = await Promise.all([
    fetchUserProfile(userId),
    fetchUserPosts(userId),
    fetchUserAnalytics(userId),
  ]);

  return { profile, posts, analytics };
}
```

By resolving requests in parallel with `Promise.all`, total latency dropped from **650ms down to 300ms** (the time of the slowest single request).

---

### 2. Replacing Unnecessary `useEffect` with Derived State (Impact: HIGH)

In a search filter component, I had written a `useEffect` to synchronize filtered items into local state:

#### ❌ Before (Redundant Re-render Cycle)
```tsx
function PostFilter({ posts }: { posts: Post[] }) {
  const [query, setQuery] = useState('');
  const [filtered, setFiltered] = useState<Post[]>([]);

  useEffect(() => {
    // ⚠️ Redundant: Causes an extra re-render on every keystroke!
    setFiltered(posts.filter(p => p.title.toLowerCase().includes(query.toLowerCase())));
  }, [query, posts]);

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <PostList items={filtered} />
    </div>
  );
}
```

#### ✅ After (Instant Single-Pass Derived State)
```tsx
function PostFilter({ posts }: { posts: Post[] }) {
  const [query, setQuery] = useState('');

  // ✅ Clean: Calculated on the fly during render with zero extra render passes!
  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    return q ? posts.filter(p => p.title.toLowerCase().includes(q)) : posts;
  }, [query, posts]);

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <PostList items={filtered} />
    </div>
  );
}
```

---

### 3. Dynamic Lazy Loading for Heavy Interactive Modals (Impact: HIGH)

My search modal was importing search index utilities directly into the root layout, increasing initial bundle size.

The agent suggested dynamic client imports:

```tsx
// Dynamically load the search modal only when requested by the user
import dynamic from 'next/dynamic';

const SearchModal = dynamic(
  () => import('@/components/search-modal').then((mod) => mod.SearchModal),
  { ssr: false }
);
```

This shaved **42KB** of JavaScript from the initial page payload for first-time visitors.

---

## How to Audit Your Own Project

To run an automated audit on your project:

1. **Install the Skill**:
   ```bash
   npx add-skill vercel-labs/agent-skills
   ```
2. **Prompt Your AI Assistant**:
   > *"Perform a full codebase audit using the Vercel React Best Practices skill. List all CRITICAL and HIGH priority performance violations with code diffs."*
3. **Review and Validate**:
   Always run your test suite and production build after applying changes:
   ```bash
   npm run lint
   npm run build
   ```

---

## Conclusion & Next Steps

Agent skills turn AI coding assistants from generic autocomplete engines into specialized senior engineers adhering to strict, high-performance standards.

By applying Vercel's React guidelines:
- We eliminated server-side request waterfalls.
- We removed unnecessary re-render cycles caused by state synchronization.
- We reduced initial client bundle footprints.

If you are building modern full-stack web applications, check out these related guides on my blog:

- [What is Agent Observability? Why and When It Matters](https://danywalls.com/what-is-agent-observability)
- [How to Create One-Click MCP Installation Links for Cursor and VS Code](https://danywalls.com/create-one-click-mcp-installation-links-cursor-vscode)
- [Prompt Injection in Agentic Apps: 4 Layers of Defense](https://danywalls.com/prompt-injection-agentic-apps-4-layers-defense)
- [Next.js on Google Cloud Run: Production Caching and Secrets](https://danywalls.com/nextjs-on-cloud-run-production-guide)

