From Idea to Web App: Building ExamGenius with Vibe Coding and Claude
In the dynamic world of software development, finding more efficient ways to bring ideas to life has always been a constant pursuit. Recently, I completed a project that radically transformed my perspective on web app development: ExamGenius, an application that generates practice exams from documents uploaded by students, using generative AI. What makes this project special isn't just its functionality, but how it was built: using a "Vibe Coding" approach with Anthropic's Claude as my development copilot. In this article, I'll share this development experience, the challenges we faced, and how generative AI is changing the software development landscape. What is "Vibe Coding"? Before diving into the technical details, let me explain what I mean by "Vibe Coding." It's a collaborative programming approach where a human and an AI work together, with the human providing strategic direction, requirements, and adjustments, while the AI handles much of the code generation and implementation of design patterns. It's different from simply using a coding assistant. With Vibe Coding, you're building an entire system in collaboration with AI, discussing architecture, making design decisions, and reviewing code together, almost like pair programming with an extremely competent digital partner. ExamGenius: The Project ExamGenius is a web application that allows students to upload one or more PDF documents or photographs of textbooks or notes. The application uses AI to extract the text and generate a personalized practice exam that can be downloaded in PDF format. Key requirements included: A serverless microservices architecture on AWS Compliance with 12-factor app principles Modern frontend developed with Next.js Backend based on Lambda, S3, Step Functions, and Bedrock Technical Architecture The solution we built consists of two main components: Serverless Backend We built a robust microservices architecture using AWS Lambda with the following components: Upload Service: Receives documents and stores them in S3, initiating a Step Functions workflow. Extract Service: Uses AWS Textract to extract text from PDF documents and images. Generate Service: Employs AWS Bedrock (Claude) to generate exams based on extracted content. PDF Service: Converts the generated exam to downloadable PDF format. Status Service: Provides real-time progress updates. All infrastructure was defined as code using Terraform, following IaC best practices. Next.js Frontend The frontend uses Next.js 14 with App Router and follows a modern design with: Tailwind CSS for styling React Query for state management and synchronization Radix UI for accessible components React Hook Form for form handling We implemented an attractive, responsive design that guides the user through the exam generation process and displays real-time progress updates. The Vibe Coding Process with Claude Now, let's look at the actual process of building ExamGenius. Unlike traditional development, where I would have started by writing detailed documentation, setting up repositories, and manually creating each component, with Claude we adopted a more fluid and exploratory approach. 1. Initial Definition I started with a simple definition: I want to create a GenAI-based web application called "ExamGenius" that allows students to upload one or more PDF documents or photographs of textbooks or notebooks and based on this information creates a practice exam that can be downloaded as a PDF. Claude immediately proposed a serverless microservices architecture on AWS, with key components like AWS Bedrock, Textract, S3, Lambda, and Step Functions. From there, we began to iterate. 2. Architecture and Flow Definition Within minutes, Claude produced detailed diagrams using Mermaid to visualize both the microservices architecture and the application workflow: 3. Backend Development With the architecture agreed upon, we proceeded to build each Lambda service. Claude generated complete and well-structured code for each component, including: Proper error handling Step Functions configuration Terraform code for infrastructure Packaging scripts Interestingly, Claude could maintain an extraordinarily coherent context across multiple services, ensuring everything integrated correctly. 4. Frontend Development In parallel, we developed a modern frontend using Next.js. Claude surprised me with its ability to follow current best practices: Component-based React App Router Custom hooks for business logic Asynchronous loading pattern with loading/success/error states Real-time visual feedback of progress Here's an example of an upload component that Claude generated: 'use client'; import React, { useState, useCallback } from 'react'; import { useDropzone } from 'react-dropzone'; import { FileUp, X, AlertCircle, FileText } from 'lucide-react';

In the dynamic world of software development, finding more efficient ways to bring ideas to life has always been a constant pursuit. Recently, I completed a project that radically transformed my perspective on web app development: ExamGenius, an application that generates practice exams from documents uploaded by students, using generative AI.
What makes this project special isn't just its functionality, but how it was built: using a "Vibe Coding" approach with Anthropic's Claude as my development copilot. In this article, I'll share this development experience, the challenges we faced, and how generative AI is changing the software development landscape.
What is "Vibe Coding"?
Before diving into the technical details, let me explain what I mean by "Vibe Coding." It's a collaborative programming approach where a human and an AI work together, with the human providing strategic direction, requirements, and adjustments, while the AI handles much of the code generation and implementation of design patterns.
It's different from simply using a coding assistant. With Vibe Coding, you're building an entire system in collaboration with AI, discussing architecture, making design decisions, and reviewing code together, almost like pair programming with an extremely competent digital partner.
ExamGenius: The Project
ExamGenius is a web application that allows students to upload one or more PDF documents or photographs of textbooks or notes. The application uses AI to extract the text and generate a personalized practice exam that can be downloaded in PDF format.
Key requirements included:
- A serverless microservices architecture on AWS
- Compliance with 12-factor app principles
- Modern frontend developed with Next.js
- Backend based on Lambda, S3, Step Functions, and Bedrock
Technical Architecture
The solution we built consists of two main components:
Serverless Backend
We built a robust microservices architecture using AWS Lambda with the following components:
- Upload Service: Receives documents and stores them in S3, initiating a Step Functions workflow.
- Extract Service: Uses AWS Textract to extract text from PDF documents and images.
- Generate Service: Employs AWS Bedrock (Claude) to generate exams based on extracted content.
- PDF Service: Converts the generated exam to downloadable PDF format.
- Status Service: Provides real-time progress updates.
All infrastructure was defined as code using Terraform, following IaC best practices.
Next.js Frontend
The frontend uses Next.js 14 with App Router and follows a modern design with:
- Tailwind CSS for styling
- React Query for state management and synchronization
- Radix UI for accessible components
- React Hook Form for form handling
We implemented an attractive, responsive design that guides the user through the exam generation process and displays real-time progress updates.
The Vibe Coding Process with Claude
Now, let's look at the actual process of building ExamGenius. Unlike traditional development, where I would have started by writing detailed documentation, setting up repositories, and manually creating each component, with Claude we adopted a more fluid and exploratory approach.
1. Initial Definition
I started with a simple definition:
I want to create a GenAI-based web application called "ExamGenius" that allows
students to upload one or more PDF documents or photographs of textbooks or notebooks
and based on this information creates a practice exam that can be downloaded as a PDF.
Claude immediately proposed a serverless microservices architecture on AWS, with key components like AWS Bedrock, Textract, S3, Lambda, and Step Functions. From there, we began to iterate.
2. Architecture and Flow Definition
Within minutes, Claude produced detailed diagrams using Mermaid to visualize both the microservices architecture and the application workflow:
3. Backend Development
With the architecture agreed upon, we proceeded to build each Lambda service. Claude generated complete and well-structured code for each component, including:
- Proper error handling
- Step Functions configuration
- Terraform code for infrastructure
- Packaging scripts
Interestingly, Claude could maintain an extraordinarily coherent context across multiple services, ensuring everything integrated correctly.
4. Frontend Development
In parallel, we developed a modern frontend using Next.js. Claude surprised me with its ability to follow current best practices:
- Component-based React App Router
- Custom hooks for business logic
- Asynchronous loading pattern with loading/success/error states
- Real-time visual feedback of progress
Here's an example of an upload component that Claude generated:
'use client';
import React, { useState, useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import { FileUp, X, AlertCircle, FileText } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
import { validateFile } from '@/utils/validation';
import { formatFileSize } from '@/utils/format';
import { useUpload } from '@/hooks/use-upload';
export function UploadForm({ onSuccess, className }) {
const [files, setFiles] = useState([]);
const { uploadFiles, isUploading, error, result } = useUpload();
const onDrop = useCallback((acceptedFiles) => {
const validFiles = acceptedFiles.filter(file => validateFile(file).valid);
setFiles(prevFiles => [...prevFiles, ...validFiles]);
}, []);
// Remaining implementation...
}
5. Iteration and Refinement
One of the most valuable aspects of the Vibe Coding approach was the ability to iterate quickly. When we realized that the jobs/status
endpoint was missing to query the status of jobs, for example, I simply mentioned the issue and Claude generated a complete implementation, including proper IAM permissions handling.
Challenges and Learnings
This approach wasn't without challenges:
1. CORS Issues
We faced typical CORS problems when developing locally. Claude not only correctly identified the issue but proposed multiple solutions:
- Configure CORS in API Gateway
- Set up CORS in Lambda responses
- Implement a temporary proxy in Next.js
2. IAM Permissions
A frequent challenge in AWS applications is the correct configuration of permissions. When the status Lambda couldn't list Step Functions executions, Claude identified that we needed a more specific IAM policy:
{
Effect = "Allow"
Action = [
"states:ListExecutions"
]
Resource = [
aws_sfn_state_machine.exam_generation_workflow.arn
]
}
3. Styles Loading
When we had issues with styles loading in the frontend, Claude provided comprehensive solutions, including checks of the global.css file, Tailwind configuration, and import alternatives.
Comparison with Traditional Development
To put the value of this approach in perspective, let's compare the time and resources used:
Traditional Development:
- Creation of detailed documentation: 1-2 days
- Repository and environment setup: 0.5 days
- AWS backend development: 5-7 days
- Frontend development: 4-5 days
- Testing and integration: 2-3 days Total: 12.5-17.5 days (100-140 hours)
Vibe Coding with Claude:
- Initial definition and architecture: 2 hours
- Backend development: 8 hours
- Frontend development: 6 hours
- Iteration and corrections: 4 hours Total: 20 hours
This comparison is revealing: the time required was reduced by approximately 85%, without compromising code quality or best practices.
Conclusions: The Future of Software Development
This experience has led me to several important conclusions:
1. The Developer Role is Evolving
Instead of writing every line of code, the future developer might focus more on:
- Clearly defining problems
- Making strategic architectural decisions
- Validating and refining generated code
- Providing the business context that AI lacks
2. Democratization of Development
AI tools like Claude are democratizing software development, allowing individuals with limited technical knowledge to build complex solutions.
3. Code Quality
Contrary to what might be expected, the generated code followed good practices, was well-structured and documented, and used modern patterns.
4. Speed with Quality
Perhaps most impressively: we didn't have to choose between speed and quality. We got both.
Is This the Future?
ExamGenius is just one example of what's possible with AI-assisted programming. While this approach has limitations (especially in very large or highly specialized projects), it clearly shows a future where developers and AI work in tandem, combining human creativity and context with AI speed and precision.
The next time you have an idea for a web application, consider the Vibe Coding approach. It's not about replacing developers but empowering them, allowing them to focus on what they do best: solving real problems for real users.
Have you experimented with similar approaches in your development? What have been your experiences with AI programming tools? Share your thoughts in the comments.