Building a Hotel Review Feed with Claude Code
We gave Claude Code three prompts and got a working hotel review feed: an Express server, live Booking.com guest reviews, and a styled, paginated page. This tutorial shows the exact prompts, the code they produced, and a screenshot of the app after every step.
Table of contents

Plenty of Claude Code tutorials end with a todo app.
This one ends with something you could put in front of users: a live hotel review feed showing real guest reviews from Booking.com, with score badges, pros and cons, and pagination.
The whole Claude Code tutorial takes 3 prompts, 2 files, and about 20 minutes.
We built the app exactly as described below, screenshotted it after every prompt, and pasted the prompts verbatim, so you can see what you'll get before you type anything.
Of course, if you're using Codex or Cursor, this tutorial will work as well.
Key Takeaways
- Three prompts produce a working review feed. One scaffolds an Express proxy, one renders the reviews, one styles and paginates the page.
- The whole app is 2 files and about 100 lines.
server.jsproxies the reviews endpoint;public/index.htmlfetches and renders the data. - A server-side proxy keeps your API key private. The browser only talks to your Express server; only the server talks to the hotel reviews API.
- The data is live at request time. Every page load pulls current Booking.com guest reviews: scores, titles, positive and negative comments, room types.
- Expect one round of fixes. Claude Code got roughly 95% of this build right on the first pass; we pasted one CSS glitch back into the chat and it repaired itself.
What Is Claude Code?
Claude Code is Anthropic's coding agent.
You describe what you want in plain English in your terminal, and it writes, edits, and runs code in your project folder.
It's the tool most people mean when they talk about vibe coding: you describe outcomes and review results instead of typing every line yourself.
Install it once with npm install -g @anthropic-ai/claude-code, then run claude inside a project folder.
It requires a paid Claude plan; setup details are at claude.com/claude-code.
If you can describe a feature clearly, you can follow this tutorial.
What You're Building

A single-page review feed for one hotel.
Your browser asks your own Express server for reviews → the server fetches them from the reviews API and passes the JSON through.
The proxy exists for one reason: your API key stays on the server, where visitors can't read it.
Put the key in client-side JavaScript and anyone who opens DevTools owns it.
The review data comes from a hotel reviews API.
We used StayAPI's Booking.com reviews endpoint and pointed it at Marina Bay Sands in Singapore (hotel_id 245881).
Here's the build at a glance:
| Prompt | What it builds | What you see |
|---|---|---|
| 1: Scaffold | Express server, /api/reviews proxy, a page that dumps JSON |
Raw review JSON in the browser |
| 2: Render | A reviewCard function that turns JSON into HTML |
A plain list of real guest reviews |
| 3: Style | Cards, score badges, pros and cons colors, Load more button | The finished feed above |
Before You Start
Four things to have ready:
1. Node.js 20.6 or newer. The build uses Node's built-in fetch and --env-file, so Express stays the only dependency.
2. Claude Code installed and signed in. One command: npm install -g @anthropic-ai/claude-code.
3. A StayAPI key for the review data. Sign up at stayapi.com (free tier, no credit card) and grab your key.
4. A project folder with a .env file containing one line: STAYAPI_KEY=your_key_here.
Want to see the data before writing any code?
The free Booking.com reviews tool shows the exact JSON you'll be working with.
Prompt 1: Scaffold the Server and Prove the Data Flows
The first prompt sets up the whole architecture:
Build a minimal Node + Express app in this folder.
server.js: serve static files from public/ and add GET /api/reviews, which proxies
https://api.stayapi.com/v1/booking/hotel/reviews for hotel_id 245881, passing the
x-api-key header read from STAYAPI_KEY in .env. Forward a page query param.
public/index.html: fetch /api/reviews and dump the JSON into a <pre> so I can
confirm the data flows. Express should be the only dependency.
Claude Code created the folders, installed Express, and wrote this server.js:
const express = require('express');
const app = express();
const API_KEY = process.env.STAYAPI_KEY;
const HOTEL_ID = '245881'; // Marina Bay Sands
app.use(express.static('public'));
app.get('/api/reviews', async (req, res) => {
const page = req.query.page || 1;
const url = `https://api.stayapi.com/v1/booking/hotel/reviews?hotel_id=${HOTEL_ID}&language=en&page=${page}`;
const response = await fetch(url, { headers: { 'x-api-key': API_KEY } });
res.json(await response.json());
});
app.listen(3000, () => console.log('Review feed running at http://localhost:3000'));
That's the entire backend.
Start it with node --env-file=.env server.js, open localhost:3000, and the browser fills with review JSON:

The endpoint returns 10 reviews per page by default.
Trimmed down, each one looks like this:
{
"success": true,
"hotel_id": "245881",
"data": {
"reviews_returned": 10,
"reviews": [
{
"score": 10,
"reviewed_date": "2026-07-23 17:31:48",
"guest": { "name": "Daniel", "country": "GB", "traveler_type": "Couple" },
"stay_details": { "room_type": "Sands Premier King", "nights": 1 },
"review": {
"title": "Dream come true.",
"positive": "The whole hotel, amazing.",
"negative": "Nothing",
"language": "en-gb"
}
}
],
"pagination": { "current_page": 1, "per_page": 10, "has_next_page": true }
}
}
Seeing raw JSON in the browser feels anticlimactic, but it's the most important checkpoint in the build.
Every problem after this point is a rendering problem, and rendering problems are the kind Claude Code fixes in one pass.
Prompt 2: Turn the JSON Into a Review List
The second prompt picks the fields worth showing:
Replace the JSON dump in index.html with a rendered list.
For each review show the guest name and country, the score, the review title,
the positive and negative comments, the room type, nights, and traveler type.
No styling yet, plain HTML is fine.
These are the fields the feed uses:
| Field | Example from our data | What it is |
|---|---|---|
| score | 10 |
Guest's overall rating out of 10 |
| guest.name | "Daniel" |
Reviewer's first name |
| guest.country | "GB" |
Reviewer's country code |
| review.title | "Dream come true." |
Review headline |
| review.positive | "The whole hotel, amazing." |
What the guest liked |
| review.negative | "Nothing" |
What the guest didn't like |
| staydetails.roomtype | "Sands Premier King" |
Room the guest stayed in |
| reviewed_date | "2026-07-23 17:31:48" |
When the review was posted |
The positive and negative comments arrive as separate fields, pre-split at the source.
That's a Booking.com schema quirk that saves you real work: sentiment comes labeled, no text analysis needed.
Claude Code wrote a reviewCard function in vanilla JavaScript, maybe 15 lines, and the page went from JSON to this:

Ugly, but real: actual guests, actual scores, actual complaints.
Structure first, paint second.
Prompt 3: Make It Look Like a Product
The last prompt handles design and pagination in one go:
Make it look like a real product.
Centered 680px column on a light gray background, white cards with rounded
corners, a dark blue score badge, green + and red - markers for the positive
and negative comments, stay details in small gray text.
Add a "Load more reviews" button that fetches the next page using the page
query param and hides itself when pagination.has_next_page is false.
The result is the feed from the top of this article.
Scrolled to the bottom, the pagination is working too:

The Load more button re-requests /api/reviews?page=2, appends the new cards, and checks pagination.has_next_page to decide whether to stay visible.
Marina Bay Sands has pages of reviews to page through, so it stays busy.
Total build: 2 files, about 100 lines, 3 prompts.
When the Vibe Coding Breaks
It won't go perfectly, and it didn't for us.
On this build, Claude's first pass at the stylesheet included a mangled hover color on the Load more button; we pasted the symptom back into Claude Code and it fixed the rule in seconds.
The lesson: describe the symptom, let the agent find the bug.
You don't need to read CSS to say "the button looks broken when I hover it."
Problems on the API side are usually one of these:
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 401 | Wrong API key | Check the x-api-key header and the key value in .env |
| HTTP 422 | Key never reached the server | Restart with node --env-file=.env server.js after editing .env |
| "No Reviews Found" (404) | Wrong or mistyped hotel_id |
Test the ID with curl or the free reviews tool first |
fetch is not defined |
Node older than 18 | Upgrade Node; this build assumes 20.6+ |
Two honest caveats before you ship anything.
The app has no error handling and no caching, and both are one more prompt away.
And if you only want to check one hotel's reviews once, you don't need an app at all; the free tool covers that.
Taking It Further
The proxy pattern you just built extends in every direction:
- More hotels. Loop over a list of hotel IDs and merge the feeds, or add a dropdown to switch properties.
- Sentiment tracking. The pre-split positive and negative fields feed directly into hotel review sentiment analysis without any NLP preprocessing.
- Other platforms. The same pattern works for TripAdvisor, Airbnb, Agoda, and Expedia reviews; only the endpoint path and field names change.
- No code at all. Platforms like N8N and Make.com can call the same API and push reviews into a spreadsheet or dashboard, no server required.
For a walkthrough of the API side with your own use case, book a demo.
FAQ
Do I need to know JavaScript to follow this?
No, and that's the point of the exercise.
Claude Code writes the JavaScript; your job is describing what you want and checking the result in the browser.
Reading the code afterward is a good habit, and this app is small enough to read in 5 minutes.
Can I build the same feed for a different hotel?
Yes, any public Booking.com property works.
Grab the hotel's URL from Booking.com and convert it with the URL to Hotel ID endpoint, then swap the HOTEL_ID constant in server.js.
Is the review data real-time?
Yes.
Each request fetches current data from the platform; there's no sync schedule or overnight batch to wait on.
Reviews posted this morning showed up in our feed this afternoon.
Can I pull reviews from other platforms into the same feed?
Public review APIs are rare across booking platforms, which is why hotel data APIs exist as a category.
StayAPI covers Booking.com, TripAdvisor, Airbnb, Agoda, Expedia, and Google Hotels reviews behind one key, so the same proxy pattern repeats per platform.
What does this stack cost to run?
Claude Code needs a paid Claude plan, and the review data has a free tier that covers a build like this.
Past the free tier, API pricing depends on request volume; check current pricing before committing to a big feed.
The Express app itself runs anywhere Node runs, including free hosting tiers.
Ready to simplify your hotel data?
Join other developers using StayAPI to build the next generation of travel applications. Get started for free today.