Skip to content

AyanJaved/RentyWenty

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

36 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RentyWenty Logo

RentyWenty

A full-stack rental listing platform built with Node.js, Express, and MongoDB

Live Demo Node.js MongoDB Express License: MIT


πŸ“– Overview

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.


✨ Features

Core Functionality

  • 🏠 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

Security & Authentication

  • πŸ” 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

UX & Design

  • πŸŒ™ 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

πŸ› οΈ Tech Stack

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
Email 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

πŸ“‚ Project Structure

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

πŸ—‚οΈ Data Models

Listing

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

Review

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

User

Field Type Constraints
username String Unique (via passport-local-mongoose)
email String Required, unique, lowercase
password Hashed Managed by passport-local-mongoose

πŸ” Environment Variables

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 .env file. Make sure .env is listed in .gitignore.

Generate a secure session secret:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

πŸ“¦ Installation & Local Setup

# 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:8080

🌍 Deployment (Render)

This 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.


πŸ”’ Security Highlights

  • Passwords are never stored in plaintext β€” hashed via pbkdf2 by passport-local-mongoose
  • Sessions stored in MongoDB with AES encryption (connect-mongo crypto option)
  • All mutation routes protected by isLoggedIn, isOwner, and isReviewAuthor middleware
  • Server-side Joi validation on all create/update routes
  • Regex-safe search β€” user input is escaped before being used in MongoDB queries
  • httpOnly and secure cookie flags set for production
  • trust proxy enabled for correct HTTPS detection behind Render's proxy
  • Helmet.js sets security HTTP response headers

🀝 Contributing

Contributions are welcome! To contribute:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit your changes: git commit -m 'Add your feature'
  4. Push to the branch: git push origin feature/your-feature
  5. Open a Pull Request

πŸ“„ License

This project is open source and available under the MIT License.


Built with ❀️ by Ayan Javed Ayan Khan Alveena Fatima

About

A full-stack rental listing platform built with Node.js, Express, MongoDB Atlas, and Cloudinary. Features auth, image uploads, reviews, search, and dark mode.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors