Build a Car Rental System Using Next.js
Last Updated :
23 Jul, 2025
We will build a car rental system using Next.js, a popular React framework that provides server-side rendering and static site generation. This platform will allow users to browse and book vehicles for short-term usage.
Output Preview: Let us have a look at how the final output will look like.
Build a Car Rental System Using Next.jsPrerequisites
Approach to Build a Car Rental System Using Next.js
- Start by creating a new Next.js application.
- Design a navigation bar that provides links to different parts of the application, such as the car listing, booking, and user profile pages.
- Develop a CarListing component to display a grid of car cards. Each card should show basic information like the car model, price, and an image.
- Create a CarDetail component to display detailed information about a selected car, including features, availability, and contact details.
- Create managcars page to edit or delete the car details.
- Create addcar page which will have form to add new car details.
Steps to Build a Car Rental System Using Next.js
Step 1: Initialized the Nextjs app.
npx create-next-app@latest car-rental-system
Step 2: It will ask you some questions, so choose as the following
SetupStep 3: Install the necessary package for your project using the following command.
npm install bootstrap
npm install @fortawesome/react-fontawesome @fortawesome/free-solid-svg-icons
Project Structure
Folder StructureDependencies
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"bootstrap": "^5.3.3",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18"
}
Example: Create the required files and write the following code.
JavaScript
// page.js
import React from "react";
import CarListing from "./components/CarListing";
const page = () => {
return (
<div>
<CarListing />
</div>
);
};
export default page;
JavaScript
// Navbar.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Link from 'next/link';
function Navbar() {
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark shadow">
<div className="container">
<Link className="navbar-brand text-light" href="/">Car Rental</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false"
aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className="nav-item">
<Link className="nav-link text-light" href="/">Home</Link>
</li>
<li className="nav-item">
<Link className="nav-link text-light" href="/addcar">Add New Car
</Link>
</li>
<li className="nav-item">
<Link className="nav-link text-light" href="/managecars">
Manage Cars</Link>
</li>
</ul>
</div>
</div>
</nav>
);
}
export default Navbar;
JavaScript
// CarListing.js
"use client";
import React, { useState, useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Link from "next/link";
import Navbar from "./Navbar";
const CarListing = () => {
const [cars, setCars] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
useEffect(() => {
if (typeof window !== "undefined") {
const storedCars = localStorage.getItem("cars");
const allCars = storedCars ? JSON.parse(storedCars) : [];
setCars(allCars);
}
}, []);
const handleSearchChange = (e) => {
const search = e.target.value;
setSearchTerm(search);
const filteredCars = cars.filter((car) =>
car.model.toLowerCase().includes(search.toLowerCase())
);
setCars(filteredCars);
};
return (
<>
<Navbar />
<div className="container mt-5">
<div className="row mb-3">
<div className="col-md-6 offset-md-3">
<input
type="text"
className="form-control"
placeholder="Search for cars..."
value={searchTerm}
onChange={handleSearchChange}
/>
</div>
</div>
<div className="row">
{cars.map((car) => (
<div key={car.id} className="col-lg-4 col-md-6 mb-4">
<Link href={`/car/${car.id}`} passHref>
<div className="card h-100" style={{ cursor: "pointer" }}>
<img
src={car.imageUrl}
className="card-img-top"
alt={car.model}
style={{ height: "200px", objectFit: "cover" }}
/>
<div className="card-body">
<h5 className="card-title">{car.model}</h5>
<p className="card-text">
<strong>Price per Day:</strong> ₹{car.pricePerDay}
</p>
<Link href={`/car/${car.id}`} passHref>
<span className="btn btn-primary w-100
text-decoration-none">
View Details
</span>
</Link>
</div>
</div>
</Link>
</div>
))}
</div>
</div>
<style jsx>{`
.card:hover {
border-radius: 8px;
transition: box-shadow 0.3s;
width: 101%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
`}</style>
</>
);
};
export default CarListing;
JavaScript
// pages/car/CarDetail.js
"use client";
import React, { useState, useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "@/app/components/Navbar";
import { useRouter } from "next/router";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faSnowflake,
faCarBattery,
faSun,
faCar,
faTag,
faUser,
faPhoneAlt,
faCalendarAlt,
} from "@fortawesome/free-solid-svg-icons";
const CarDetail = () => {
const [car, setCar] = useState(null);
const router = useRouter();
const { id } = router.query;
useEffect(() => {
if (typeof window !== "undefined" && id) {
const storedCars = localStorage.getItem("cars");
const allCars = storedCars ? JSON.parse(storedCars) : [];
const selectedCar = allCars.find((car) => car.id === parseInt(id));
setCar(selectedCar);
}
}, [id]);
if (!car) {
return <div>Loading...</div>;
}
return (
<>
<Navbar />
<div className="container mt-5">
<div className="row">
<div className="col-md-6 mb-4">
<img
src={car.imageUrl}
alt={car.model}
className="img-fluid rounded shadow-sm"
/>
</div>
<div className="col-md-6">
<h2 className="mb-4">{car.model}</h2>
<div className="mb-3">
<p>
<FontAwesomeIcon icon={faTag}
className="me-2 text-primary" />{" "}
<strong>Price per Day:</strong> ₹{car.pricePerDay}
</p>
<p>
<FontAwesomeIcon icon={faUser}
\className="me-2 text-primary" />{" "}
<strong>Owner:</strong> {car.ownerName}
</p>
<p>
<FontAwesomeIcon
icon={faPhoneAlt}
className="me-2 text-primary"
/>{" "}
<strong>Contact:</strong> {car.ownerContact}
</p>
<p>
<FontAwesomeIcon
icon={faCalendarAlt}
className="me-2 text-primary"
/>{" "}
<strong>Available:</strong> {car.isAvailable ? "Yes" : "No"}
</p>
</div>
<div className="mb-3">
<p>
<strong>Features:</strong>
</p>
<div className="row g-2">
{car.features.ac && (
<div className="col-3">
<div className="d-flex align-items-center
justify-content-center
p-2 bg-success text-white rounded">
<FontAwesomeIcon icon={faSnowflake}
className="me-2" />
<span>AC</span>
</div>
</div>
)}
{car.features.cng && (
<div className="col-3">
<div className="d-flex align-items-center
justify-content-center
p-2 bg-success text-white rounded">
<FontAwesomeIcon icon={faCarBattery}
className="me-2" />
<span>CNG</span>
</div>
</div>
)}
{car.features.sunroof && (
<div className="col-3">
<div className="d-flex align-items-center
justify-content-center
p-2 bg-success text-white rounded">
<FontAwesomeIcon icon={faSun} className="me-2" />
<span>Sunroof</span>
</div>
</div>
)}
{car.features.automatic && (
<div className="col-3">
<div className="d-flex align-items-center
justify-content-center
p-2 bg-success text-white rounded">
<FontAwesomeIcon icon={faCar} className="me-2" />
<span>Automatic</span>
</div>
</div>
)}
</div>
</div>
<button className="btn btn-primary">Book Now</button>
</div>
</div>
</div>
</>
);
};
export default CarDetail;
JavaScript
// addcar.js
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "@/app/components/Navbar";
const AddCar = () => {
const [model, setModel] = useState("");
const [description, setDescription] = useState("");
const [pricePerDay, setPricePerDay] = useState("");
const [availability, setAvailability] = useState(true);
const [ownerName, setOwnerName] = useState("");
const [ownerContact, setOwnerContact] = useState("");
const [imageUrl, setImageUrl] = useState("");
// State for car features
const [features, setFeatures] = useState({
ac: false,
cng: false,
sunroof: false,
automatic: false,
});
const handleSubmit = (e) => {
e.preventDefault();
const id = Date.now(); // Generate a unique ID using the current timestamp
console.log({
id,
model,
description,
pricePerDay,
availability,
ownerName,
ownerContact,
imageUrl,
features,
});
// Save the form data to local storage
const carData = {
id,
model,
description,
pricePerDay,
availability,
ownerName,
ownerContact,
imageUrl,
features,
};
const cars = JSON.parse(localStorage.getItem("cars")) || [];
cars.push(carData);
localStorage.setItem("cars", JSON.stringify(cars));
// Reset form fields after submission
setModel("");
setDescription("");
setPricePerDay("");
setAvailability(true);
setOwnerName("");
setOwnerContact("");
setImageUrl("");
setFeatures({
ac: false,
cng: false,
sunroof: false,
automatic: false,
});
};
// Handle feature checkbox changes
const handleFeatureChange = (e) => {
const { name, checked } = e.target;
setFeatures((prevFeatures) => ({
...prevFeatures,
[name]: checked,
}));
};
return (
<>
<Navbar />
<div className="container" style={{ width: "70%" }}>
<h2 className="mt-3 mb-4">Add New Car for Rent</h2>
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label htmlFor="model" className="form-label">
Car Model
</label>
<input
type="text"
className="form-control"
id="model"
value={model}
onChange={(e) => setModel(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="description" className="form-label">
Description
</label>
<textarea
className="form-control"
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
></textarea>
</div>
<div className="mb-3">
<label htmlFor="pricePerDay" className="form-label">
Price Per Day
</label>
<input
type="text"
className="form-control"
id="pricePerDay"
value={pricePerDay}
onChange={(e) => setPricePerDay(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="availability" className="form-label">
Availability
</label>
<select
className="form-control"
id="availability"
value={availability}
onChange={(e) => setAvailability(e.target.value === "true")}
required
>
<option value="true">Available</option>
<option value="false">Not Available</option>
</select>
</div>
<div className="mb-3">
<label htmlFor="ownerName" className="form-label">
Owner Name
</label>
<input
type="text"
className="form-control"
id="ownerName"
value={ownerName}
onChange={(e) => setOwnerName(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="ownerContact" className="form-label">
Owner Contact
</label>
<input
type="text"
className="form-control"
id="ownerContact"
value={ownerContact}
onChange={(e) => setOwnerContact(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="imageUrl" className="form-label">
Image URL
</label>
<input
type="text"
className="form-control"
id="imageUrl"
value={imageUrl}
onChange={(e) => setImageUrl(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label className="form-label">Features</label>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id="ac"
name="ac"
checked={features.ac}
onChange={handleFeatureChange}
/>
<label className="form-check-label" htmlFor="ac">
AC
</label>
</div>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id="cng"
name="cng"
checked={features.cng}
onChange={handleFeatureChange}
/>
<label className="form-check-label" htmlFor="cng">
CNG
</label>
</div>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id="sunroof"
name="sunroof"
checked={features.sunroof}
onChange={handleFeatureChange}
/>
<label className="form-check-label" htmlFor="sunroof">
Sunroof
</label>
</div>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id="automatic"
name="automatic"
checked={features.automatic}
onChange={handleFeatureChange}
/>
<label className="form-check-label" htmlFor="automatic">
Automatic Transmission
</label>
</div>
</div>
<button type="submit" className="btn btn-primary">
Add Car
</button>
</form>
</div>
</>
);
};
export default AddCar;
JavaScript
// managecars.js
import React, { useState, useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "@/app/components/Navbar";
const ManageCars = () => {
const [cars, setCars] = useState([]);
const [editingCar, setEditingCar] = useState(null);
const [model, setModel] = useState("");
const [description, setDescription] = useState("");
const [pricePerDay, setPricePerDay] = useState("");
const [ownerName, setOwnerName] = useState("");
const [ownerContact, setOwnerContact] = useState("");
const [imageUrl, setImageUrl] = useState("");
const [features, setFeatures] = useState({
ac: false,
cng: false,
sunroof: false,
automatic: false,
});
useEffect(() => {
const storedCars = localStorage.getItem("cars");
if (storedCars) {
setCars(JSON.parse(storedCars));
}
}, []);
const handleEdit = (car) => {
setEditingCar(car);
setModel(car.model);
setDescription(car.description);
setPricePerDay(car.pricePerDay);
setOwnerName(car.ownerName);
setOwnerContact(car.ownerContact);
setImageUrl(car.imageUrl);
setFeatures(car.features);
};
const handleUpdate = (e) => {
e.preventDefault();
const updatedCars = cars.map((car) =>
car.id === editingCar.id
? {
...car,
model,
description,
pricePerDay,
ownerName,
ownerContact,
imageUrl,
features,
}
: car
);
setCars(updatedCars);
localStorage.setItem("cars", JSON.stringify(updatedCars));
resetForm();
};
const handleDelete = (carId) => {
const updatedCars = cars.filter((car) => car.id !== carId);
setCars(updatedCars);
localStorage.setItem("cars", JSON.stringify(updatedCars));
};
const resetForm = () => {
setEditingCar(null);
setModel("");
setDescription("");
setPricePerDay("");
setOwnerName("");
setOwnerContact("");
setImageUrl("");
setFeatures({
ac: false,
cng: false,
sunroof: false,
automatic: false,
});
};
const handleFeatureChange = (e) => {
const { name, checked } = e.target;
setFeatures({ ...features, [name]: checked });
};
return (
<>
<Navbar />
<div className="container mt-5">
<h2 className="mb-4">Manage Cars</h2>
{editingCar ? (
<form onSubmit={handleUpdate}>
<div className="mb-3">
<label htmlFor="model" className="form-label">
Model
</label>
<input
type="text"
className="form-control"
id="model"
value={model}
onChange={(e) => setModel(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="description" className="form-label">
Description
</label>
<textarea
className="form-control"
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
></textarea>
</div>
<div className="mb-3">
<label htmlFor="pricePerDay" className="form-label">
Price per Day
</label>
<input
type="text"
className="form-control"
id="pricePerDay"
value={pricePerDay}
onChange={(e) => setPricePerDay(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="ownerName" className="form-label">
Owner Name
</label>
<input
type="text"
className="form-control"
id="ownerName"
value={ownerName}
onChange={(e) => setOwnerName(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="ownerContact" className="form-label">
Owner Contact
</label>
<input
type="text"
className="form-control"
id="ownerContact"
value={ownerContact}
onChange={(e) => setOwnerContact(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="imageUrl" className="form-label">
Image URL
</label>
<input
type="text"
className="form-control"
id="imageUrl"
value={imageUrl}
onChange={(e) => setImageUrl(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label className="form-label">Features</label>
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
id="ac"
name="ac"
checked={features.ac}
onChange={handleFeatureChange}
/>
<label htmlFor="ac" className="form-check-label">
AC
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
id="cng"
name="cng"
checked={features.cng}
onChange={handleFeatureChange}
/>
<label htmlFor="cng" className="form-check-label">
CNG
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
id="sunroof"
name="sunroof"
checked={features.sunroof}
onChange={handleFeatureChange}
/>
<label htmlFor="sunroof" className="form-check-label">
Sunroof
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
id="automatic"
name="automatic"
checked={features.automatic}
onChange={handleFeatureChange}
/>
<label htmlFor="automatic" className="form-check-label">
Automatic Transmission
</label>
</div>
</div>
<button type="submit" className="btn btn-primary">
Update Car
</button>
<button
type="button"
className="btn btn-secondary ms-2"
onClick={resetForm}
>
Cancel
</button>
</form>
) : (
<div className="row">
{cars.map((car) => (
<div key={car.id} className="col-lg-4 col-md-6 mb-4">
<div className="card">
{car.imageUrl ? (
<img
src={car.imageUrl}
className="card-img-top"
alt={car.model}
style={{ height: "200px", objectFit: "cover" }}
/>
) : (
<div
className="card-img-top"
style={{
height: "200px",
backgroundColor: "#f0f0f0",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<span>No Image</span>
</div>
)}
<div className="card-body">
<h5 className="card-title">{car.model}</h5>
<p className="card-text">₹{car.pricePerDay} per day</p>
<p className="card-text">Owner: {car.ownerName}</p>
<button
className="btn btn-primary"
onClick={() => handleEdit(car)}
>
Edit
</button>
<button
className="btn btn-danger ms-2"
onClick={() => handleDelete(car.id)}
>
Delete
</button>
</div>
</div>
</div>
))}
</div>
)}
</div>
<style jsx>{`
.card:hover {
border-radius: 8px;
transition: box-shadow 0.3s;
width: 101%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
`}</style>
</>
);
};
export default ManageCars;
Output