A full-stack MERN (MongoDB, Express, React, Node.js) application for Sri Lanka vacation rental management. StayHub enables users to discover, book, and list accommodations with a seamless, modern interface.
- JWT-based user authentication with 1-hour token expiration
- Role-based access control (Guest, Host, Admin)
- Secure password hashing with bcryptjs
- Token persistence in localStorage
- Hosts can create, edit, and delete listings
- Multi-image upload support (max 3 images per listing)
- Drag-and-drop file upload interface
- Atomic upload (images upload with listing creation)
- Category support (beach, mountain, city, villa, apartment, cabin, boutique, other)
- Availability status management (Live/Hidden)
- Google Cloud Storage (GCS) integration for scalable image hosting
- Automatic fallback to local storage for development/permission issues
- Public URLs and signed URL generation
- Image optimization and validation
- Browse all available listings
- Search and filter functionality (keyword + category)
- Dedicated listing details page with full information, host profile, and image gallery
- Protected guest booking flow
- Guest: Browse listings, make bookings
- Host: Create and manage multiple listings
- Admin: Full platform management and oversight
- Node.js v22.4.1 or higher
- npm v10+ or yarn
- MongoDB Atlas account (free tier available)
- Google Cloud Platform account (for GCS, optional)
git clone https://github.com/Deathbot545/StayHub.git
cd StayHubcd backend
npm installCreate .env file in the backend/ directory:
PORT=5001
MONGO_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/stayhub?retryWrites=true&w=majority
JWT_SECRET=your_super_secret_jwt_key_change_this
CLIENT_URL=http://localhost:5173
# Google Cloud Storage (Optional)
GCP_PROJECT_ID=your-gcp-project-id
GCS_BUCKET=your-gcs-bucket-name
GOOGLE_APPLICATION_CREDENTIALS=./stayhub-489907-0e76df346af1.jsonStart the backend:
npm run devBackend runs on http://localhost:5001
cd frontend/stayhub-frontend
npm installStart the development server:
npm run devFrontend runs on http://localhost:5173
Open your browser and navigate to:
http://localhost:5173
StayHub/
βββ backend/ # Node.js + Express API
β βββ middleware/
β β βββ auth.js # JWT verification & authorization
β βββ models/
β β βββ User.js
β β βββ Listing.js
β β βββ Booking.js
β βββ routes/
β β βββ auth.js # Sign up, login, logout
β β βββ listings.js # CRUD for listings with image upload
β β βββ bookings.js # Booking management
β β βββ admin.js # Admin operations
β β βββ uploads.js # Batch image upload
β βββ services/
β β βββ gcs.js # Google Cloud Storage wrapper
β βββ server.js # Express app & initialization
β βββ seed.js # Database seeding script
β βββ package.json
β
βββ frontend/
β βββ stayhub-frontend/ # React + Vite
β βββ src/
β β βββ components/ # Reusable components
β β β βββ Navbar.jsx
β β β βββ SearchBar.jsx
β β β βββ Results.jsx
β β β βββ ProtectedRoute.jsx
β β βββ pages/ # Page components
β β β βββ Home.jsx
β β β βββ Listings.jsx
β β β βββ MyListings.jsx # Host dashboard
β β β βββ SignUp.jsx
β β β βββ SignIn.jsx
β β βββ lib/
β β β βββ api.js # API fetch wrapper
β β β βββ AuthContext.jsx # Global auth state
β β βββ App.jsx
β β βββ main.jsx
β βββ vite.config.js # Vite config with API proxy
β βββ package.json
β
βββ README.md # This file
POST /api/auth/signup- Register new userPOST /api/auth/login- User loginPOST /api/auth/logout- User logout (frontend-only)
GET /api/listings- Get all public listingsGET /api/listings/:id- Get one public listing with host detailsGET /api/listings/mine- Get user's listings (Host/Admin only)POST /api/listings- Create new listing with images (Host/Admin only)PATCH /api/listings/:id- Update listing (Host/Admin only)DELETE /api/listings/:id- Delete listing (Host/Admin only)
POST /api/bookings- Create bookingGET /api/bookings- Get user's bookingsPUT /api/bookings/:id- Update booking status
GET /api/admin/users- List all users (Admin only)GET /api/admin/bookings- View all bookings (Admin only)
- Runtime: Node.js 22.4.1
- Framework: Express 5.x
- Database: MongoDB Atlas
- ODM: Mongoose
- Authentication: JWT (jsonwebtoken)
- Password Hashing: bcryptjs
- File Upload: Multer
- Cloud Storage: Google Cloud Storage SDK
- CORS: cors middleware
- Library: React 19.2.0
- Build Tool: Vite
- Routing: React Router 7.13.1
- HTTP Client: Fetch API
- State Management: React Context API (AuthContext)
- Styling: CSS (BEM methodology)
- Package Manager: npm
- Development Server: Vite dev server with hot reload
- Backend Hot Reload: nodemon
- Version Control: Git + GitHub
| Variable | Description | Example |
|---|---|---|
PORT |
Backend server port | 5001 |
MONGO_URI |
MongoDB Atlas connection string | mongodb+srv://user:pass@cluster.mongodb.net/stayhub |
JWT_SECRET |
Secret key for JWT signing | your-secret-key-min-32-chars |
CLIENT_URL |
Frontend URL for CORS | http://localhost:5173 |
GCP_PROJECT_ID |
Google Cloud Project ID | stayhub-489907 |
GCS_BUCKET |
GCS bucket name | stayhub_bucket |
GOOGLE_APPLICATION_CREDENTIALS |
Path to GCS service account key | ./stayhub-489907-0e76df346af1.json |
npm run dev # Start dev server with nodemon
npm start # Production start
npm test # Run tests (if configured)npm run dev # Start Vite dev server
npm run build # Build for production
npm run preview # Preview production build- Set environment variables on hosting platform (Heroku, Railway, Render, etc.)
- Ensure MongoDB Atlas allows connections from production IP
- Configure GCS service account for production environment
- Deploy with
npm start
npm run build # Creates optimized dist/ folder
# Deploy dist/ to hosting (Vercel, Netlify, GitHub Pages, etc.)β Implemented
- JWT tokens with 1-hour expiration
- Password hashing with bcryptjs
- Role-based access control via middleware
- CORS enabled for frontend origin only
- Credentials excluded from version control (.gitignore)
- API request authorization headers
- Use HTTPS in production
- Implement refresh tokens for better UX
- Add rate limiting for auth endpoints
- Regular security audits of dependencies
- Secure GCS service account with minimal IAM permissions
- Rotate JWT_SECRET periodically
- Verify
/uploads-localproxy is configured invite.config.js - Check backend
.envhas correctGCS_BUCKETname - Ensure images are in
backend/uploads/listings/
- Verify connection string in
.env - Whitelist your IP in MongoDB Atlas Network Access
- Check database name matches connection string
- Service account needs
storage.objects.createIAM role - If unavailable, app automatically falls back to local storage
- Check
GOOGLE_APPLICATION_CREDENTIALSpath is correct
- Ensure backend is running on port 5001
- Check Vite proxy config points to correct backend URL
- Verify CORS is enabled in backend (should hit all origins in dev)
This project is open source and available under the MIT License.
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
For questions or issues, please:
- Open an issue on GitHub Issues
- Check existing documentation in backend/ and frontend/ READMEs
- Review code comments for implementation details
- Admin dashboard with analytics
- Payment integration (Stripe/PayPal)
- Email notifications for bookings
- Reviews and ratings system
- Wishlist functionality
- Real-time messaging between guests and hosts
- Calendar availability picker
- Mobile app (React Native)
- Multi-language support
Made with β€οΈ for travelers exploring Sri Lanka
Last Updated: March 11, 2026