π Table of Contents
- π€ Introduction
- βοΈ Tech Stack
- π Features
- π€Έ Quick Start
- πΈοΈ Snippets (Code to Copy)
- π Assets
- π More
MovieFlix is a dynamic movie browsing application built with Next.js, leveraging Redux Toolkit for state management and Firebase for data storage. The app features infinite scrolling to enhance user experience, allowing seamless browsing of movies without interruptions
If you're getting started and need assistance or face any bugs, join our active Discord community with over 34k+ members. It's a place where people help each other out.
- Next.js
- Firebase
- JavaScript
- TailwindCSS
- ShadCN
π Movie Listings: Display a list of movies with details like title, poster, release year, rating, and genre.
π Trailer Display: When a user clicks on a movie, a modal or separate section should show the movie trailer.
π Skeleton Loading: Implement skeleton loading screens (placeholders) while the movie data is being fetched.
π Complete Responsiveness: The application works seamlessly on all device types and screen sizes.
π File Upload Using Firebase Storage: Users can upload and store files securely within the app using firebase storage services.
and many more, including code architecture and reusability
Follow these steps to set up the project locally on your machine.
Prerequisites
Make sure you have the following installed on your machine:
Cloning the Repository
git clone https://github.com/Hi-Dear-486/Movie-flix-App.git
cd Movie-flix-App
Installation
Install the project dependencies using npm:
npm install
Set Up Environment Variables
Create a new file named .env.local
in the root of your project and add the following content:
#Firebase
NEXT_PUBLIC_FIREBASE_API_KEY
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
NEXT_PUBLIC_FIREBASE_PROJECT_ID
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
NEXT_PUBLIC_FIREBASE_APP_ID
Replace the placeholder values with your actual Firebase credentials. You can obtain these credentials by signing up on the [Firebase website (https://firebase.google.com/).
Running the Project
npm run dev
Open http://localhost:3000 in your browser to view the project.
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
},
},
plugins: [],
};
src/app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
/* ========================================== TAILWIND STYLES */
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1;
font-weight: 500;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
--black: #04152d;
--black2: #041226;
--black3: #020c1b;
--black-lighter: #1c4b91;
--black-light: #173d77;
--pink: #da2f68;
--orange: #f89e00;
--gradient: linear-gradient(98.37deg, #f89e00 0.99%, #da2f68 100%);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: var(--black);
}
::-webkit-scrollbar {
display: none;
}
.skeleton {
position: relative;
overflow: hidden;
background-color: #0a2955;
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(#193763, 0) 0,
rgba(#193763, 0.2) 20%,
rgba(#193763, 0.5) 60%,
rgba(#193763, 0)
);
animation: shimmer 2s infinite;
content: "";
}
@keyframes shimmer {
100% {
transform: translateX(100%);
}
}
}```
</details>
<details>
<summary><code>src/utils/page.js</code></summary>
```javascript
"use client ";
import axios from "axios";
// this url base key when we will search then it will be provide BASE_URL
// search example api request
const BASE_URL = "https://api.themoviedb.org/3";
const TMDB_TOKEN =
"eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJmNzI0MzkxZGQ2ZjEzMjIxZDZhMzZkYmQwOGUwYTk5ZCIsInN1YiI6IjY1ZTc0Mjk1NTY4NDYzMDE4NmE4ZmYyNyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.jIEuSlvLAODr3bGtkU-vWyvuOPQFqwv3g4fgCA4h6pc";
const headers = {
// dont forget space in 'bearer '
Authorization: "bearer " + TMDB_TOKEN,
};
// fetch data from api
export const fetchDatafromApi = async (url, params) => {
try {
const { data } = await axios.get(BASE_URL + url, {
headers,
params,
});
return data;
} catch (error) {
return error;
}
};
src/store/Homeslice.js
"use client";
import { createSlice } from "@reduxjs/toolkit";
const Homeslice = createSlice({
name: "counter",
initialState: {
url: {},
genres: {},
},
reducers: {
getApiConfiguration: (state, action) => {
state.url = action.payload;
},
getGenres: (state, action) => {
state.genres = action.payload;
},
},
});
export const { getApiConfiguration, getGenres } = Homeslice.actions;
export default Homeslice.reducer;
src/hooks/page.js
import { useEffect, useState } from "react";
import { fetchDatafromApi } from "@/utils/page";
const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading("loading...");
setData(null);
setError(null);
fetchDatafromApi(url)
.then((res) => {
setLoading(false);
setData(res);
})
.catch((err) => {
setLoading(false);
setError("Something went wrong!");
});
}, [url]);
return { data, loading, error };
};
export default useFetch;
Public assets used in the project can be found here
Advance your skills with Next.js
Enjoyed creating this project? Dive deeper for a richer learning adventure. They're packed with detailed explanations, cool features, and exercises to boost your skills. Give it a go!