As developers, we learn best by building real projects. I wanted to challenge myself to create something that felt like a production-ready full-stack app — not just another todo list.
That’s how I built Elan Royale, a luxury restaurant reservation system where users can book a table, make a deposit, and receive instant confirmation.
This project not only helped me practice Next.js, Prisma, and full-stack development, but also gave me something powerful to showcase in my portfolio.
⸻
🥂 The Problem I Wanted to Solve
Restaurants often rely on manual reservations (phone calls, paper logs) which can be messy and lead to errors. I wanted to create a modern solution that:
• Lets users easily reserve a table online.
• Collects a deposit using Stripe payments.
• Automatically confirms and stores the booking.
This was the idea behind Elan Royale.
⸻
🛠 Tech Stack
I picked technologies that are used in real production apps:
• Next.js 15 → for server-side rendering and API routes.
• Prisma ORM → to model and interact with the database.
• TailwindCSS → for fast, modern, responsive styling.
• Stripe → for payment gateway integration.
• Vercel → for smooth deployment and hosting.
⸻
⚙️ Building the System
Here’s how I built it step by step:
- Setting up Next.js
I started by creating a Next.js app using the App Router. This gave me a strong foundation with server-side rendering and API routes.
- Designing the UI
Using TailwindCSS, I designed a clean, modern interface.
• A Hero section to showcase the restaurant’s luxury feel.
• A Reservation Form with fields for name, email, phone, party size, date/time, and notes.
Reserve a Table
- Database with Prisma
I defined the reservation schema in Prisma:
model Reservation {
id String @id @default(cuid())
name String
email String
phone String
partySize Int
reservationTime DateTime
area String
notes String?
createdAt DateTime @default(now())
}
This made it easy to create and query reservations in the database.
- API Routes
I created an API route (/api/reservations) to handle saving reservations into the database.
export async function POST(req: Request) {
const body = await req.json();
const reservation = await prisma.reservation.create({ data: body });
return NextResponse.json(reservation, { status: 201 });
}
- Stripe Payment Integration
Before confirming a reservation, the system redirects users to Stripe Checkout to pay a deposit.
• User fills the form → saved in DB.
• Stripe Checkout opens → user pays.
• On success, they are redirected to /confirmation.
const paymentRes = await fetch("/api/create-checkout-session", { ... });
const data = await paymentRes.json();
window.location.href = data.url;
- Confirmation Page
After payment, users land on a Confirmation Page showing reservation details.
🎉 Reservation Confirmed!
Thank you for booking with Elan Royale.
⚡ Challenges I Faced & How I Solved Them
1. Prisma errors → Fixed by handling missing/invalid input properly in API.
2. Hero image loading slowly → Solved by switching to next/image for optimization.
3. useSearchParams error in Next.js 15 → Solved by wrapping in to support client-side params.
🎨 Final Result
✅ Users can make a reservation online.
✅ Payment deposit handled with Stripe.
✅ Confirmation page with booking details.
✅ Fully deployed to Vercel.
🔗 Live Demo: [elan-royale.vercel.app]
🔗 GitHub Repo: github.com/Aisha-Aliyu/elan-royale.git
⸻
💡 Lessons Learned
• Next.js App Router makes full-stack projects much cleaner.
• Prisma is powerful for database modeling and migrations.
• Stripe integration is smooth but requires careful error handling.
• Deployment on Vercel is fast and beginner-friendly.
⸻
✅ Conclusion
This project showed me how to bring together frontend, backend, database, and payments into one seamless full-stack app.
If you’d like to check it out, here’s the live demo and GitHub repo.
I’m also open to collaborations and freelance opportunities in full-stack web development — feel free to connect! 🚀
Top comments (0)