A full-stack hotel booking web application replicating Booking.com. Stack: HTML + CSS + JS (Frontend) Β· Node.js + Express + MongoDB + JWT + Nodemailer (Backend)
hotel-booking/
βββ index.html β Complete frontend (single file SPA)
βββ server.js β Node.js + Express backend
βββ package.json β Dependencies
βββ .env.example β Environment variable template
βββ .env β Your secrets (never commit this!)
βββ .gitignore
βββ README.md
Make sure you have these installed on your computer:
# Check if installed
node --version
npm --version
# If not installed, download from:
# https://nodejs.org/en/download# Option A: Install MongoDB Community locally
# https://www.mongodb.com/try/download/community
# Option B (recommended for beginners): Use MongoDB Atlas FREE cloud
# https://www.mongodb.com/cloud/atlas/register
# β Create free cluster β Get connection string β paste in .env# 1. Clone or download the project folder
cd hotel-booking
# 2. Install all dependencies
npm install
# 3. Create your .env file from the template
cp .env.example .env
# 4. Open .env in any text editor and fill in:
# MONGO_URI β your MongoDB connection string
# JWT_SECRET β any long random string (e.g. "abc123xyz789secretkey")
# EMAIL_USER β your Gmail address
# EMAIL_PASS β Gmail App Password (see Step 3)To send real booking confirmation emails:
- Go to your Google Account β Security β 2-Step Verification β Turn ON
- Then go to: https://myaccount.google.com/apppasswords
- Create an App Password for "Mail"
- Copy the 16-character password
- Put it in
.envasEMAIL_PASS=xxxx xxxx xxxx xxxx
# Development mode (auto-restarts on file changes)
npm run dev
# OR production mode
npm startThen open your browser and go to:
http://localhost:5000
After starting the server, open a new terminal and run:
# Add sample hotel data to MongoDB
curl -X POST http://localhost:5000/api/seed
# OR open this URL in your browser:
# http://localhost:5000/api/seed (change to POST via Postman)| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/register | Register new user | No |
| POST | /api/login | Login, returns JWT token | No |
| GET | /api/me | Get current user info | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/hotels | List hotels with filters | No |
| GET | /api/hotels/:id | Get single hotel details | No |
Hotel filter query params:
GET /api/hotels?dest=Goa&maxPrice=10000&stars=4,5&score=8&amenities=wifi,pool&dist=2
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/bookings | Create booking + send email | Yes |
| GET | /api/bookings | Get user's bookings | Yes |
| DELETE | /api/bookings/:id | Cancel a booking | Yes |
{
"hotelId": "65abc123...",
"hotelName": "The Grand Palace Hotel",
"roomType": "Deluxe Room",
"checkIn": "2024-07-15",
"checkOut": "2024-07-18",
"guests": "2 adults",
"price": 5700,
"totalPrice": 17100,
"guestName": "Rahul Sharma",
"guestEmail": "rahul@example.com",
"guestPhone": "+91 98765 43210",
"specialReq": "High floor room, late check-in",
"allergies": "Nut allergy"
}The frontend (index.html) currently works standalone with in-memory data.
To connect it to the real backend API, replace these functions in index.html:
async function doLogin() {
const email = document.getElementById('loginEmail').value;
const pass = document.getElementById('loginPass').value;
try {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password: pass }),
});
const data = await res.json();
if (!res.ok) { document.getElementById('loginError').style.display='block'; return; }
localStorage.setItem('token', data.token);
setLoggedIn(data.user);
closeModal();
} catch(e) { console.error(e); }
}async function doRegister() {
const name = document.getElementById('regName').value;
const email = document.getElementById('regEmail').value;
const pass = document.getElementById('regPass').value;
const pass2 = document.getElementById('regPass2').value;
if (pass !== pass2) { document.getElementById('regError').style.display='block'; return; }
try {
const res = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, email, password: pass }),
});
const data = await res.json();
if (!res.ok) { document.getElementById('regError').textContent=data.error; document.getElementById('regError').style.display='block'; return; }
localStorage.setItem('token', data.token);
setLoggedIn(data.user);
closeModal();
} catch(e) { console.error(e); }
}async function renderHotels() {
const maxPrice = document.getElementById('priceRange').value;
const dest = document.getElementById('dest').value;
const url = `/api/hotels?dest=${encodeURIComponent(dest)}&maxPrice=${maxPrice}`;
const res = await fetch(url);
const hotels = await res.json();
// ... render as before
}async function confirmBooking() {
const token = localStorage.getItem('token');
const body = { /* collect all form fields */ };
const res = await fetch('/api/bookings', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
body: JSON.stringify(body),
});
const data = await res.json();
// Show confirmation page with data.ref
}# 1. Push your code to GitHub first
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/YOUR_USERNAME/staybook.git
git push -u origin main
# 2. Go to https://render.com β New β Web Service
# 3. Connect your GitHub repo
# 4. Set these settings:
# Build Command: npm install
# Start Command: npm start
# Environment: Node
# 5. Add Environment Variables in Render dashboard:
# MONGO_URI = mongodb+srv://... (from MongoDB Atlas)
# JWT_SECRET = your_secret_here
# EMAIL_USER = your@gmail.com
# EMAIL_PASS = your_app_password
# NODE_ENV = production
# 6. Click Deploy!
# Your site will be live at: https://staybook.onrender.com# 1. Install Railway CLI
npm install -g @railway/cli
# 2. Login
railway login
# 3. Create project
railway init
# 4. Add MongoDB plugin in Railway dashboard
# 5. Set environment variables
railway variables set JWT_SECRET=your_secret
railway variables set EMAIL_USER=your@gmail.com
railway variables set EMAIL_PASS=your_app_pass
# 6. Deploy
railway up
# Your site will be live at the URL Railway provides# 1. SSH into your server
ssh root@YOUR_SERVER_IP
# 2. Install Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# 3. Install MongoDB
sudo apt-get install -y mongodb
sudo systemctl start mongodb
# 4. Install PM2 (keeps app running)
npm install -g pm2
# 5. Clone your repo
git clone https://github.com/YOUR_USERNAME/staybook.git
cd staybook
# 6. Install dependencies
npm install
# 7. Create .env
nano .env
# (paste your environment variables)
# 8. Start with PM2
pm2 start server.js --name staybook
pm2 startup # auto-start on reboot
pm2 save
# 9. Setup Nginx (reverse proxy)
sudo apt install nginx
sudo nano /etc/nginx/sites-available/staybookNginx config:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}sudo ln -s /etc/nginx/sites-available/staybook /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
# 10. Add SSL (free with Let's Encrypt)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com| Error | Fix |
|---|---|
ECONNREFUSED on MongoDB |
Start MongoDB: sudo systemctl start mongodb |
Invalid token on API |
Token expired β login again |
| Emails not sending | Check Gmail App Password, enable 2FA first |
Port 5000 in use |
Kill process: `lsof -ti:5000 |
Cannot find module |
Run npm install again |
| CORS error in browser | Make sure backend has cors() middleware |
npm run dev # Start with auto-reload (development)
npm start # Start normally (production)
npm install # Install all packages
# MongoDB (local)
mongosh # Open MongoDB shell
show dbs # List databases
use staybook # Switch to staybook db
db.hotels.find() # View all hotels
db.users.find() # View all users
db.bookings.find() # View all bookings
# PM2 (production)
pm2 list # Show running apps
pm2 logs staybook # View live logs
pm2 restart staybook # Restart app
pm2 stop staybook # Stop appCreate a .gitignore file:
node_modules/
.env
*.log
For help, open an issue or contact: support@staybook.com