Sitemap

AI-Driven Next.js: From Component Generation to Fail-Safe Data Fetching

7 min readJun 30, 2025

--

As a software consultant, I constantly explore tools that enhance productivity and streamline development processes. Recently, I experimented with using AI agents to build an entire app using React and Next.js application from initial setup and coding to hosting and deployment.

Spoiler alert: The results were a remarkable boost to my velocity

Why Use AI Agents for Coding?

  • Speed: Instantly generates boilerplate and reduces repetitive coding.
  • Quality: Produces clean, reusable components.
  • Focus: Allows me to concentrate and focus on strategic architecture and solving problems.

The Complete Toolkit & Setup

Here’s the comprehensive stack I utilized:

  • v0: Web app design with v0 AI
  • AI Agent: Open AI GPT-4.0, Claude 3.5 Sonnet
  • Frontend Framework: React & Next.js 15 (optimal for modern, scalable web apps)
  • Styling: Tailwind CSS (quick, utility-first styling)
  • Hosting & Deployment: Vercel (built-in CI/CD optimized for Next.js apps)

My demo project: FitLife — a fitness class booking app.

Step-by-Step AI-driven Development

Step 1: UX Design

I used vercel’s v0 AI to build some mockups for me to start with. I was able to use that as a starting point and iterate through ideas. Here is what v0 was able to give me for the FitLife app.

UX Mockups from v0

Isn’t it pretty neat! I was quite impressed by what it was able to generate so I could have a good starting point.

Project Folder Structure

Step 2: Initial Project Setup

Prompt:

Set up a new React Next.js app with Tailwind CSS.

AI quickly provided clear setup commands:

npx create-next-app@latest fitlife-app --use-npm --example with-tailwindcss

Step 3: Generate React

Prompt:

Generate a set of reusable React components for a fitness class booking app built with Next.js and Tailwind CSS. Include components for InstructorCard, BookingConfirmation, ClassSearch, ClassCard, ClassScheduleGrid, and LoadingSpinner with clean code and utility-first styling.Instructor Bio Card Component.

Instructor Bio Card Component

export default function InstructorCard({ instructor }) {
return (
<div className="p-4 border rounded shadow-md">
<h3 className="text-lg font-semibold">{instructor.name}</h3>
<p className="text-gray-600">{instructor.bio}</p>
</div>
);
}

Booking Confirmation Component

export default function BookingConfirmation({ booking }) {
return (
<div className="bg-green-100 p-4 rounded">
<h2 className="text-2xl font-bold">Booking Confirmed!</h2>
<p>Class: {booking.classTitle}</p>
<p>Date: {booking.date}</p>
<p>Instructor: {booking.instructor}</p>
</div>
);
}

Class Search Component

import { useState } from 'react';

export default function ClassSearch({ onSearch }) {
const [query, setQuery] = useState('');
return (
<div className="my-4">
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && onSearch(query)}
placeholder="Search classes..."
className="border p-2 rounded w-full"
/>
</div>
);
}

Class Card Component

export default function ClassCard({ cls }) {
return (
<div className="border rounded p-4 shadow-md">
<h2 className="text-xl font-bold">{cls.title}</h2>
<p className="text-gray-700">{cls.description}</p>
<p className="text-sm text-gray-500">{cls.schedule}</p>
</div>
);
}

Class Schedule Grid Component

import ClassCard from './ClassCard';

export default function ClassScheduleGrid({ classes }) {
return (
<div className="grid grid-cols-3 gap-4">
{classes.map((cls) => (
<ClassCard key={cls.id} cls={cls} />
))}
</div>
);
}

Loading Spinner Component

export default function LoadingSpinner() {
return (
<div className="flex items-center justify-center py-8">
<div className="w-8 h-8 border-4 border-blue-500 border-dashed rounded-full animate-spin"></div>
</div>
);
}

Classes Page Using Server Components

import { fetchClasses } from '@/lib/classes';
import ClassScheduleGrid from '@/components/ClassScheduleGrid';

export default async function ClassesPage() {
const classes = await fetchClasses();
return (
<div className="container mx-auto">
<h1 className="text-3xl font-bold my-4">Available Classes 🏋️‍♂️</h1>
<ClassScheduleGrid classes={classes} />
</div>
);
}

Step 4: Creating a Dynamic Class Schedule Page

Prompt:

Generate a dynamic class schedule page using React Server Components.

AI-generated code snippet:

// app/classes/page.jsx
import { fetchClasses } from '@/lib/classes';
import ClassScheduleGrid from '@/components/ClassScheduleGrid';
import ClassSearch from '@/components/ClassSearch';
import InstructorCard from '@/components/InstructorCard';
import BookingConfirmation from '@/components/BookingConfirmation';
import LoadingSpinner from '@/components/LoadingSpinner';

export default async function ClassesPage() {
const classes = await fetchClasses();

const handleSearch = (query) => {
console.log('Searching for:', query);
};

const sampleBooking = {
classTitle: 'Yoga Flow',
date: '2025-06-30',
instructor: 'Jane Doe',
};

const sampleInstructor = {
name: 'Jane Doe',
bio: 'Certified Yoga Instructor with 5 years of experience teaching vinyasa and restorative yoga.',
};

return (
<div className="container mx-auto">
<h1 className="text-3xl font-bold my-4">Available Classes 🏋️‍♂️</h1>
<ClassSearch onSearch={handleSearch} />
<ClassScheduleGrid classes={classes} />
<h2 className="text-2xl font-bold mt-8">Instructor</h2>
<InstructorCard instructor={sampleInstructor} />
<h2 className="text-2xl font-bold mt-8">Booking Confirmation Example</h2>
<BookingConfirmation booking={sampleBooking} />
</div>
);
}

Step 5: Error Handling

Prompt:

Add robust error handling to the class schedule page.

Improved code snippet:

// app/classes/page.jsx
import { fetchClasses } from '@/lib/classes';
import { fetchInstructor } from '@/lib/instructors';
import ClassScheduleGrid from '@/components/ClassScheduleGrid';
import ClassSearch from '@/components/ClassSearch';
import InstructorCard from '@/components/InstructorCard';
import BookingConfirmation from '@/components/BookingConfirmation';
import LoadingSpinner from '@/components/LoadingSpinner';

export default async function ClassesPage() {
let classes = [];
let instructor = null;
let errorMessage = '';

try {
classes = await fetchClasses();
} catch (err) {
console.error('Error fetching classes:', err);
errorMessage += 'Failed to load classes. ';
}

try {
instructor = await fetchInstructor();
} catch (err) {
console.error('Error fetching instructor:', err);
errorMessage += 'Failed to load instructor.';
}

// If either fetch failed, show an error banner
if (errorMessage) {
return (
<div className="container mx-auto p-4">
<p className="text-red-500 font-medium">{errorMessage}</p>
</div>
);
}

// If classes array is empty, show loading spinner
if (!classes.length) {
return (
<div className="container mx-auto p-4">
<LoadingSpinner />
</div>
);
}

// Client‐side search filtering
const handleSearch = (query) => {
// implement real filtering or API call
console.log('Searching for:', query);
};

// Prepare booking details from first class
const bookingDetails = {
classTitle: classes[0].title,
date: classes[0].schedule,
instructor: instructor.name,
};

return (
<div className="container mx-auto p-4">
<h1 className="text-3xl font-bold my-4">Available Classes 🏋️‍♂️</h1>
<ClassSearch onSearch={handleSearch} />
<ClassScheduleGrid classes={classes} />
<h2 className="text-2xl font-bold mt-8">Instructor</h2>
<InstructorCard instructor={instructor} />
<h2 className="text-2xl font-bold mt-8">Booking Confirmation</h2>
<BookingConfirmation booking={bookingDetails} />
</div>
);
}

Step 6: Fetching Class Data (API)

Code snippet (lib/classes.js):

export async function fetchClasses() {
const response = await fetch('/api/classes');
if (!response.ok) throw new Error('Failed to fetch classes');
return response.json();
}

Step 7: Class Booking Functionality

Prompt:

Implement booking functionality with server actions in Next.js.

AI-generated booking snippet:

// app/classes/actions.js
'use server';

export async function bookClass(classId, userId) {
try {
const response = await fetch(`/api/bookings`, {
method: 'POST',
body: JSON.stringify({ classId, userId }),
});

if (!response.ok) throw new Error('Booking failed');

return await response.json();
} catch (error) {
throw new Error(`Booking error: ${error.message}`);
}
}

Step 8: Deployment with Vercel

Prompt:

Provide detailed deployment steps for Next.js app on Vercel.

AI guidance:

# Install Vercel CLI
npm install -g vercel

# Deploy to Vercel
vercel

Simple and efficient!

AI’s Performance Evaluation

  • Development & Setup: Seamless and significantly faster than manual methods.
  • Quality of Generated Code: Surprisingly clean and production-ready.
  • Deployment Process: Effortless integration with cloud solutions like Vercel.

Trade-Offs to Consider

Reliance on AI Accuracy

AI-generated code can introduce subtle bugs or mismatches to your coding standards. Always review and test thoroughly.

Customization vs. Boilerplate

Agents excel at boilerplate, but highly bespoke UI or complex business logic often still requires hand-crafting.

Maintenance Overhead

You’ll need to maintain both the AI prompts and the resulting code. Updates to your prompt or AI model can change generated code unexpectedly.

Hallucination Risk

AI agents may “hallucinate” APIs or syntax that compile but don’t actually do what you expect. Guard every fetch and component with robust error handling.

Security & Compliance

Generated snippets may omit security best practices (e.g., input sanitization, auth checks). You must audit for vulnerabilities.

Vendor Lock-In

Relying on a specific AI service can create lock-in. If pricing or policies change, you may need to switch providers and re-evaluate prompts and outputs.

Learning Curve

There’s overhead in designing effective prompts, fine-tuning agents, and integrating them into CI/CD, so plan for an initial investment of time.

Lessons Learned

  • AI Tools Enhance Workflow: They drastically reduce the initial setup and repetitive coding tasks.
  • Human Insight Remains Crucial: Strategic oversight ensures robust and effective solutions.

Conclusion

Utilizing AI to build React Next.js components and features significantly accelerates development, allowing more room for strategic decisions. While human oversight is essential for architecture, security, and complex logic, AI-driven coding is a powerful productivity tool when used judiciously.

Work With Me

I’m Adhithi Ravichandran a seasoned Software Consultant. If you are looking to:

  • Accelerate React projects with best-in-class architecture
  • Integrate AI-powered workflows into your web apps
  • Train your team on modern front-end and AI agent techniques
  • Audit or enhance existing codebases for performance, scalability, and resilience

…let’s talk!

Connect with me:

Whether you need hands-on coding help, strategic guidance, or a full-team workshop, I’d love to explore how AI and Next.js can transform your next project. Drop me a message, and let’s build something amazing together!

--

--

Adhithi Ravichandran
Adhithi Ravichandran

Written by Adhithi Ravichandran

Founder and Software Consultant @ Surya Consulting, Inc. | 📚 Author | 🎤 Keynote Speaker | 🤖 AI Solutions for React Projects

No responses yet