RentyWenty is a production-ready, full-stack web application that enables users to discover, list, and manage rental properties β including rooms, apartments, hotels, and more. Built on the MVC (Model-View-Controller) architectural pattern, it features secure authentication, server-side validation, cloud image storage, an interactive review system, and a real-time inquiry system β all deployed on Render with MongoDB Atlas as the cloud database.
- π Listing Management β Create, read, update, and delete rental listings with full ownership control
- π Smart Search β Search listings by title, location, or country with regex-safe filtering
- π·οΈ Category Filtering β Filter by categories: Trending, Luxury, Budget Stays, Rooms, Apartments, Family, Pet Friendly, Tourist Spots, Monthly Stays
- πΈ Image Uploads β Upload and store listing images via Multer + Cloudinary with automatic format validation
- β Review System β Star-based rating (1β5) with comment reviews, powered by Starability CSS
- π§ Inquiry System β Contact property owners directly via an integrated EmailJS-powered inquiry form
- π User Authentication β Secure signup/login via Passport.js with
passport-local-mongoose - π‘οΈ Authorization Middleware β Route-level ownership checks prevent unauthorized edits or deletes
- β Dual Validation β Joi schema validation on the server + Bootstrap client-side validation
- π Encrypted Sessions β MongoDB session store with AES crypto encryption via
connect-mongo - π HTTP Security Headers β Helmet.js integration for XSS, clickjacking, and sniffing protection
- π Dark Mode β Persistent dark/light theme toggle
- π± Responsive Design β Mobile-first layout using Bootstrap 5
- β‘ Flash Messages β Real-time success/error feedback using
connect-flash - π§ Custom Favicon β SVG compass favicon matching the brand identity
| Layer | Technology | Purpose |
|---|---|---|
| Runtime | Node.js 20.11.1 | Server-side JavaScript runtime |
| Framework | Express.js 5.x | HTTP server and routing |
| Database | MongoDB Atlas | Cloud NoSQL database |
| ODM | Mongoose 8.x | MongoDB object modeling |
| Templating | EJS + ejs-mate | Server-side HTML rendering with layouts |
| Authentication | Passport.js + passport-local-mongoose | Session-based auth with password hashing |
| Sessions | express-session + connect-mongo | Encrypted persistent session storage |
| Validation | Joi | Server-side schema validation |
| File Uploads | Multer + Cloudinary SDK | Image upload and cloud storage |
| EmailJS | Client-side email sending for inquiries | |
| Security | Helmet.js | HTTP security response headers |
| Styling | Bootstrap 5 + Custom CSS | Responsive UI framework |
| Icons | FontAwesome 6 | UI icon library |
| Deployment | Render | Cloud application hosting |
| Environment | dotenv | Environment variable management |
| Architecture | MVC Pattern | Separation of concerns |
RentyWenty/
βββ app.js # Express app entry point, middleware, session config
βββ cloudConfig.js # Cloudinary SDK configuration
βββ middleware.js # isLoggedIn, isOwner, isReviewAuthor, validateListing
βββ schema.js # Joi validation schemas for listings and reviews
βββ package.json
β
βββ controllers/
β βββ listing.js # Index (search/filter), show, create, update, delete
β βββ review.js # Create and delete reviews
β βββ user.js # Signup, login, logout
β
βββ models/
β βββ listing.js # Listing schema with cascade delete post hook
β βββ review.js # Review schema with author ref
β βββ user.js # User schema with passport-local-mongoose plugin
β
βββ routes/
β βββ listing.js # /listings CRUD routes
β βββ review.js # /listings/:id/reviews routes
β βββ user.js # /signup, /login, /logout routes
β
βββ views/
β βββ layouts/
β β βββ boilerplate.ejs # Base HTML layout with head, navbar, flash
β βββ listings/
β β βββ index.ejs # All listings with search and category filter
β β βββ show.ejs # Single listing detail + reviews + inquiry
β β βββ new.ejs # Create listing form
β β βββ edit.ejs # Edit listing form
β β βββ error.ejs # Error page
β βββ users/
β β βββ signup.ejs
β β βββ login.ejs
β βββ partials/
β β βββ inquiryForm.ejs # EmailJS inquiry form partial
β βββ includes/
β βββ navbar.ejs
β βββ legal.ejs
β
βββ public/
β βββ css/ # Custom stylesheets
β βββ js/ # Client-side scripts
β βββ favicon.svg # SVG brand favicon
β
βββ utils/
β βββ ExpressError.js # Custom error class with statusCode
β βββ wrapAsync.js # Async error wrapper for Express routes
β
βββ init/
βββ testData.js # Seed data for development
| Field | Type | Constraints |
|---|---|---|
title |
String | Required, max 100 chars |
description |
String | Required, max 3500 chars |
price |
Number | Required, min 0 |
location |
String | Required |
country |
String | Required |
category |
[String] | Enum of 9 categories |
image |
Object {url, filename} |
Cloudinary URL + filename |
owner |
ObjectId β User | Required ref |
reviews |
[ObjectId β Review] | Cascade deleted on listing delete |
| Field | Type | Constraints |
|---|---|---|
comment |
String | Required, max 750 chars |
rating |
Number | Required, min 1, max 5 |
author |
ObjectId β User | Required ref |
createdAt |
Date | Default: Date.now |
| Field | Type | Constraints |
|---|---|---|
username |
String | Unique (via passport-local-mongoose) |
email |
String | Required, unique, lowercase |
password |
Hashed | Managed by passport-local-mongoose |
Create a .env file in the project root:
# Database
ATLAS_DB_URL=mongodb+srv://<username>:<password>@cluster.mongodb.net/rentywenty
# Session
SECRET=<minimum_32_character_random_string>
# Cloudinary
CLOUD_NAME=your_cloudinary_cloud_name
CLOUD_API_KEY=your_cloudinary_api_key
CLOUD_API_SECRET=your_cloudinary_api_secret
# EmailJS
EMAILJS_PUBLIC_KEY=your_emailjs_public_key
EMAILJS_SERVICE_ID=your_emailjs_service_id
EMAILJS_TEMPLATE_ID=your_emailjs_template_id
β οΈ Never commit your.envfile. Make sure.envis listed in.gitignore.
Generate a secure session secret:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"# 1. Clone the repository
git clone https://github.com/AyanJaved/RentyWenty.git
cd RentyWenty
# 2. Install dependencies
npm install
# 3. Create and configure your .env file
cp .env.example .env # then fill in your values
# 4. Start the development server
npm start
# 5. Open in browser
# http://localhost:8080This project is deployed on Render with the following configuration:
| Setting | Value |
|---|---|
| Build Command | npm install |
| Start Command | npm start |
| Node Version | 20.11.1 |
| Environment | Set all .env variables in Render dashboard |
| Database | MongoDB Atlas (shared cluster) |
| Storage | Cloudinary (image CDN) |
Auto-deploys on every push to the main branch.
- Passwords are never stored in plaintext β hashed via
pbkdf2by passport-local-mongoose - Sessions stored in MongoDB with AES encryption (
connect-mongocrypto option) - All mutation routes protected by
isLoggedIn,isOwner, andisReviewAuthormiddleware - Server-side Joi validation on all create/update routes
- Regex-safe search β user input is escaped before being used in MongoDB queries
httpOnlyandsecurecookie flags set for productiontrust proxyenabled for correct HTTPS detection behind Render's proxy- Helmet.js sets security HTTP response headers
Contributions are welcome! To contribute:
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m 'Add your feature' - Push to the branch:
git push origin feature/your-feature - Open a Pull Request
This project is open source and available under the MIT License.