Step-by-Step Implementation of GenZ Carousel App
Step-by-Step Implementation
In this module, we will build the complete Gen-Z styled Image Carousel App from scratch using React + Vite. We'll walk through the project setup, structure, logic, animation with Framer Motion, and final styling using Tailwind CSS. You’ll follow along and build your own version just like the live app.
Set up the Environment
1) Install Node.js
First, make sure you have Node.js and npm installed. Download it from https://nodejs.org and verify:
node -v
npm -v
2) Create a React App with Vite
Open your terminal and run the following to scaffold a new React + Vite project:
npm create vite@latest genz-carousel-app -- --template react
Then:
cd genz-carousel-app
npm install
3) Start the App
Run the development server:
npm run dev
It will open at http://localhost:5173. You’ll see the default Vite + React template.
Install and Configure Tailwind CSS
We use Tailwind CSS for styling, and also Framer Motion for animations.
1) Install Tailwind CSS and PostCSS Plugins
Run:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
2) Configure Tailwind
In tailwind.config.js, update content:
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};3) Add Tailwind to CSS
In index.css, add:@tailwind base;
@tailwind components;
@tailwind utilities;
4) Custom Font (Optional)
Add this in index.html inside <head>:<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
And in body tag:
<body class="bg-black font-[Poppins]">
Create the Project Files
Your final folder structure will look like this:
genz-carousel-app/
├── public/
│ └── carousel/
│ ├── Helloooo.jpeg
│ ├── download.jpeg
│ └── CatQuote.jpeg
├── src/
│ ├── App.jsx
│ ├── Carousel.jsx
│ ├── index.css
│ └── main.jsx
├── index.html
├── tailwind.config.js
├── package.json
Let’s now build the components one by one.
Build the Carousel in App.jsx
Create a new file called App.jsx inside src/ and paste this:
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import "./index.css";
const defaultImages = [
"/carousel/Helloooo.jpeg",
"/carousel/download.jpeg",
"/carousel/CatQuote.jpeg",
];
function App() {
const [uploadedImages, setUploadedImages] = useState([]);
const [currentIndex, setCurrentIndex] = useState(0);
const images = uploadedImages.length > 0 ? uploadedImages : defaultImages;
const nextImage = () => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length);
};
const prevImage = () => {
setCurrentIndex((prevIndex) => (prevIndex - 1 + images.length) % images.length);
};
const handleUpload = (e) => {
const files = Array.from(e.target.files).slice(0, 10);
const urls = files.map((file) => URL.createObjectURL(file));
setUploadedImages(urls);
setCurrentIndex(0);
};
return (
<div className="app-container">
<h1 className="title">📸 Your Funtastic Gallery!</h1>
<div style={{ marginBottom: "1.5rem" }}>
<input
type="file"
multiple
accept="image/*"
onChange={handleUpload}
style={{
background: "#00eaff",
border: "none",
padding: "0.6rem 1.2rem",
borderRadius: "1rem",
color: "#000",
fontWeight: "bold",
cursor: "pointer"
}}
/>
<p style={{ fontSize: "0.9rem", color: "#00eaff", marginTop: "0.5rem" }}>
Hello! Welcome to my carousel app! You can upload up to 10 images to create your own carousel and mini album!
</p>
</div>
<div className="carousel">
<button className="nav-button" onClick={prevImage}>⟵</button>
<div className="image-container">
<AnimatePresence mode="wait">
<motion.img
key={images[currentIndex]}
src={images[currentIndex]}
alt={`Slide ${currentIndex}`}
initial={{ opacity: 0, x: 100 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -100 }}
transition={{ duration: 0.6 }}
className="carousel-image"
/>
</AnimatePresence>
</div>
<button className="nav-button" onClick={nextImage}>⟶</button>
</div>
<div className="thumbnail-container">
{images.map((img, index) => (
<img
key={index}
src={img}
alt={`Thumbnail ${index}`}
onClick={() => setCurrentIndex(index)}
className={`thumbnail ${index === currentIndex ? "active" : ""}`}
/>
))}
</div>
<p className="footer">
Made by Jaishree Tomar for <a href="https://www.guvi.in/" target="_blank">GUVI</a>
</p>
</div>
);
}
export default App;Styling with index.css
In index.css, paste this styling to support all components and maintain the Gen-Z black+cyan theme:
body {
margin: 0;
font-family: "Segoe UI", sans-serif;
background-color: #000;
color: #fff;
text-align: center;
padding: 0 2rem 2rem;
}
.title {
font-size: 2.2rem;
margin: 0 0 1.5rem;
color: #00eaff;
font-weight: bold;
letter-spacing: 0.5px;
}
.app-container {
max-width: 800px;
margin: 0 auto;
}
.carousel {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.image-container {
width: 700px;
height: 450px;
border-radius: 2rem;
overflow: hidden;
border: 4px solid #00eaff;
display: flex;
align-items: center;
justify-content: center;
background-color: #111;
}
.carousel-image {
width: 100%;
height: 100%;
object-fit: contain;
}
.nav-button {
font-size: 2rem;
background: transparent;
border: none;
color: #00eaff;
cursor: pointer;
transition: transform 0.2s ease;
}
.nav-button:hover {
transform: scale(1.2);
}
.footer {
margin-top: 2rem;
font-size: 1rem;
color: #aaa;
}
.footer a {
color: #00eaff;
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
.thumbnail-container {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-top: 1.5rem;
gap: 0.7rem;
}
.thumbnail {
width: 70px;
height: 70px;
border-radius: 0.5rem;
object-fit: cover;
cursor: pointer;
opacity: 0.6;
transition: all 0.3s ease;
border: 2px solid transparent;
}
.thumbnail:hover {
opacity: 1;
transform: scale(1.05);
}
.thumbnail.active {
border: 2px solid #00eaff;
opacity: 1;
}Setup Entry Point (main.jsx)
In main.jsx inside src/, replace the default code with:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>
);Add Default HTML and Font (index.html)
Update index.html inside the public/ folder like this:
Test and Run the App
Make sure your development server is running:
npm run dev
- Visit http://localhost:5173.
- Try uploading up to 10 images.
- Navigate between slides using arrows.
- Click thumbnails to jump to any image.
If everything works, congratulations — you’ve built your own animated, uploadable, modern image carousel app.


