I Vibe Coded a Web App — and Was Genuinely Impressed
Author’s note: this article was written with the assistance of ChatGPT. Also, as the field of AI assisted coding and debugging is moving very fast, this article could be outdated in 6–9 months.
Introduction
I honestly don’t know Next.js. I did spend some time in the past building web frontends with Apache Struts, PHP but Typescript based web frameworks are a mystery to me. However, I managed to vibe code a simple bookstore web app using AI, and honestly? I was impressed.
This article walks through how I used AI tools — mainly Cursor and ChatGPT — to build a functional bookstore web application powered by the Simple Books API. From frontend UI to backend integration, and even bug fixing, AI was involved in almost every step.
Background & Goals
Before this, I had only done two vibe coding exercises: one during the AI Makerspace onboarding challenge where I was introduced to the power of Cursor, and the other after watching a GitHub Copilot 101 tutorial.
My goal: build a simple bookstore web app using an existing API (a very common use case) using a tool like Cursor and see how easy it would be. I chose the Simple Books API (freely available) and decided to use Next.js — a framework I barely knew — and Tailwind CSS for styling.
You can find the code for this and instructions on how to run it here: GitHub Repo
The Build Process
Initial Setup
I started by structuring the project with frontend
and api
folders and initializing a README.md
. I exported the Postman collection for the Simple Books API and added it to the api
folder.
Then, I asked Cursor to:
- Review the Postman collection to understand the API
- Generate a Swagger YAML file
- Make the Swagger viewable via a web page
- Update the README accordingly
Frontend with Next.js
Prompt to Cursor:
Build the following NextJS web UI and have the files stored in the “frontend” folder with the following requirements:
a) The main page is a bookstore metaphor with a single dropdown list labeled “fiction” and “non-fiction”. Add any images to the page to aptly describe it. There should also be a big label that says this page is a “Bookstore”. A button after the dropdown list labeled “List all books” should call the “List of Books” endpoint of the API to obtain the list of books as a JSON array, then display them on the next page.
b) This page should have a big label “List of books” and show the books in a table with the column “Name” (maps to “name” in the response). Each row should include a hidden field mapping to “id”. Clicking on a book name should call the “Get a single book” endpoint using the “id” and display its details (name, author, isbn, price, current-stock) on a new page labeled “Book details”.
c) The “Book details” page should display the fields mentioned and have a button labeled “Order this book” which leads to the “Book order” page.
d) The order page should contain an input labeled “Customer name” and a button “Order book”. When clicked, it should call the “Order Book” endpoint with the customer name and book id. If successful, show a popup “Order successful”; else, show “There was an error, please retry”. All pages except the main one should have a link to return to the main page. The main page should have a link to a “List all orders” page.
e) The “Order list” page should call the “Get all book orders” endpoint and display a table with: “Customer Name” (maps to “customerName”), “Book Name” (requires calling the book API with “bookId”), and “Order ID” (maps to “id”). Clicking an Order ID should redirect to an “Order Details” page.
f) The “Order Details” page should show details from the order: “Order ID”, “Customer Name”, and “Book Name” (fetched again using the bookId). Add a button labeled “Delete order” that calls the “Delete an order” endpoint with the Order ID to delete that order.
Cursor generated code for all of these components. It even adjusted the UI for dark mode automatically.
If you run the app or even take a closer look at the screenshot at the top of the page, you will notice that requirements (a) and (b) are not fulfilled. It was initially but after the code was refactored to be adjusted for dark mode, Cursor modified the UI to this new approach (which is IMO better).
Debugging Challenges
The initial version of the web app did have issues/bugs:
- Book listing didn’t work: Cursor walked me through debugging with Chrome DevTools. Turned out to be a CORS issue. Cursor offered three solutions, and the Next.js proxy fix worked.
- Order creation issue: The app showed a success popup but no order was listed. After testing with
curl
, we figured out the API needed a token. The instructions on how to create the token is on the README. - Missing token for order listing: Same root cause. Cursor helped move the token to an
.env
file and updated the code and README accordingly.
Extras
- Used ChatGPT to generate the main page image
- Cursor added it to the main page
- Cursor also advised on GitHub setup and added the screenshot to the README
- I also got Cursor to figure out how store the API token in an
.env
file, modify the code to account for this and add instructions on the README to account for it
Cursor vs Copilot
When I tried this initially with GitHub Copilot, I got stuck right at the CORS problem. Copilot couldn’t help me troubleshoot it effectively.
Cursor, on the other hand, provided step-by-step debugging instructions and even rolled back failed fixes. It felt more like a coding partner than just an auto-complete tool.
Final Thoughts
So, what do I think about the whole experience?
- Not production-ready (yet): I wouldn’t deploy this to production without a proper security review. I suspect there are vulnerabilities I’m unaware of. In the future, I expect we’ll have AI tools that can run automated static code analysis to flag these issues — once that’s in place, the gap will narrow even further.
- Testing still matters: Despite the help from AI, it still took time to manually test the app to ensure everything worked as expected. There are emerging tools for AI-assisted testing, and I’m planning to explore some of them using this app as a sandbox.
- CI/CD next? I’m curious how far this approach can go. Could you build an entire CI/CD pipeline vibe-coding style? I think it’s possible — and that’s going to be the next step in this journey.