An exact clone of youtube with all functionalities from View count to Subscribe to everything (Without Youtube Api) Using Firebase, FFmpeg, And React
Following are the different parts of this project in order:
I’ll update the order as we Move on :))
Again for new viewers, The Github code has been uploaded
https://github.com/harsh317/Youtube-CLone-ReactJs
So in this part First let’s add firebase to our app then we can create the firebase Context API. We’ll implement the Entire Authentication system of firebase and complete our context file. With that being said, Let’s get started !!
First, quickly go to
You should see something like this
Now let’s enable the firestore database for our app. Click on the Firestore database or directly go to this
Next on the right- side click on “Create database” → Select a starting mode for your Cloud Firestore Security Rules (I will click Test mode for now) → Select a
*Good for getting started with the mobile and web client libraries, but allows anyone to read and overwrite your data. After testing, **make sure to review the
Secure your data *section. https://firebase.google.com/
**
With that our firebase should look like this with default Test rules which we will change later:
Now, similarly, click on the Authentication tab in the sidebar or directly go to this
Click on “Get Started” and you will be presented with the “Get started with Firebase Auth by adding your first sign-in method” Screen. Let’s Add the Providers we need
Just click on the Email/Password Provider And further, click on the Email/Password check box and click on the Save button
Then just add a new provider and in the Additional providers, column click on “Google” provider. And further, click on the Google check box and change the following settings. Finally, click on the “Save” button
When you got the following 2 statuses enabled, we are ready to go!
And with that ig we are finished setting up Firebase. Now, let’s makeUp the Context API. :)
If you don’t know about context API, I recommend checking about them more. Here is more basic meaning from the
Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language
So, let’s move ahead further without wasting any more time. In the Src folder, create a “Context” folder and create the context file with maybe a better file name unlike me ; — ;
import React, { useContext, useState, useEffect } from "react";
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
onAuthStateChanged,
signOut,
GoogleAuthProvider,
signInWithPopup,
} from "firebase/auth";
import { doc, setDoc } from "firebase/firestore";
import { db, auth } from "../Config/FirebaseConfig";
const AuthContext = React.createContext();
export const useAuth = () => {
const auth = useContext(AuthContext);
return { ...auth, isAuthenticated: auth.CurrentUser != null };
};
export function AuthProvider({ children }) {
const [CurrentUser, setCurrentUser] = useState();
const [loading, setloading] = useState(true);
useEffect(() => {
const unsuscribe = onAuthStateChanged(auth, (user) => {
console.log(user);
setCurrentUser(user);
setloading(false);
});
return unsuscribe;
}, []);
const SignupUser = (email, password, name) => {
return createUserWithEmailAndPassword(auth, email, password).then(
(resp) => {
if (resp.user) {
CreateFireStoreUser(
resp.user,
name,
"https://cdn-icons-png.flaticon.com/512/149/149071.png"
);
}
}
);
};
const CreateFireStoreUser = (user, name, profileImage) => {
const UsersRef = doc(db, "Users", user.uid);
setDoc(UsersRef, {
name: name,
profileImage: profileImage,
initials: name[0] + name[name.length - 1],
Suscribers: [],
}).then(() => {
console.log("added User");
});
};
const LogInUser = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
};
const SignInWithGoogle = () => {
const provider = new GoogleAuthProvider();
return signInWithPopup(auth, provider);
};
const logout = () => {
return signOut(auth);
};
const value = {
CurrentUser,
SignupUser,
LogInUser,
logout,
ResetPassword,
CreateFireStoreUser,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
Yup, we have Our Basic Context File ready for simple and basic functions like Signup/login(With Email Password), creating a Firestore user when the user is signing up, etc. The above code is quite self-explanatory ig
So let’s move on my adding functions like Email verification, password reset, etc. For that, In the Authentication section, click on the templates tab Or directly go to this
Now, let’s work on all the 3 things on the sidebar. First, we have the Email address verification thing. Like below ⬇️⬇️⬇️
Now, Click on the edit button in and change the things you want. Like ‘sender name’ and ‘from’ settings. In the message section, you see this weird line right?
http://localhost:3000/UserActions?mode=action&oobCode=code
For all the user management actions such as updating a user’s email address and resetting a user’s password, we send an email to the user’s email duh. So, By default, user management emails link to the default action handler, which is a web page hosted at a URL in your project’s Firebase Hosting domain. Firebase adds several query parameters to your action handler URL when it generates user management emails. For example:
https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr
For more info, you can read about it
https://firebase.google.com/docs/auth/custom-email-handler
So, let’s change the default action handler. It’s not that difficult ;). In the bottom section, you would be able to see a text with “Customize action URL” and there put the following value.
http://localhost:3000/UserActions
Don’t worry if you are confused right now, when we will start implementing these features, you will get more clear ;))
There is nothing more to do in these settings. Just change the text you want etc but idk we have nothing more left to do here.
OOF OOF, that whole section was a mouthful, It might look boring a bit but nvm we are finished and now we can close this site ❤️❤️😳
Now let’s complete our UserAuthContext file. This will be the complete file. It’s not that complicated ig, Just 1–2 lines of code with some settings to pass and we have the functionality running
import React, { useContext, useState, useEffect } from "react";
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
onAuthStateChanged,
signOut,
GoogleAuthProvider,
signInWithPopup,
sendPasswordResetEmail,
confirmPasswordReset,
sendSignInLinkToEmail,
isSignInWithEmailLink,
signInWithEmailLink,
} from "firebase/auth";
import { doc, setDoc } from "firebase/firestore";
import { db, auth } from "../Config/FirebaseConfig";
const AuthContext = React.createContext();
export const useAuth = () => {
const auth = useContext(AuthContext);
return { ...auth, isAuthenticated: auth.CurrentUser != null };
};
export function AuthProvider({ children }) {
const [CurrentUser, setCurrentUser] = useState();
const [loading, setloading] = useState(true);
useEffect(() => {
const unsuscribe = onAuthStateChanged(auth, (user) => {
console.log(user);
setCurrentUser(user);
setloading(false);
});
return unsuscribe;
}, []);
const SignupUser = (email, password, name) => {
return createUserWithEmailAndPassword(auth, email, password).then(
(resp) => {
if (resp.user) {
CreateFireStoreUser(
resp.user,
name,
"https://cdn-icons-png.flaticon.com/512/149/149071.png"
);
}
}
);
};
const CreateFireStoreUser = (user, name, profileImage) => {
const UsersRef = doc(db, "Users", user.uid);
setDoc(UsersRef, {
name: name,
profileImage: profileImage,
initials: name[0] + name[name.length - 1],
Suscribers: [],
}).then(() => {
console.log("added User");
});
};
const LogInUser = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
};
const SendEmailVerification = () => {
const actionCodeSettings = {
url: "http://localhost:3000", // Redirect to this url when we are succesfull
handleCodeInApp: true,
};
return sendSignInLinkToEmail(auth, CurrentUser.email, actionCodeSettings);
};
const VerifyEmailLink = () => {
if (isSignInWithEmailLink(auth, window.location.href)) {
return signInWithEmailLink(auth, CurrentUser.email);
}
};
const SignInWithGoogle = () => {
const provider = new GoogleAuthProvider();
return signInWithPopup(auth, provider);
};
const forgotPassword = (email) => {
return sendPasswordResetEmail(auth, email, {
url: "http://localhost:3000/login",
});
};
const ResetPassword = (oobcode, newPasword) => {
return confirmPasswordReset(auth, oobcode, newPasword);
};
const logout = () => {
return signOut(auth);
};
const value = {
CurrentUser,
SignupUser,
LogInUser,
logout,
SignInWithGoogle,
forgotPassword,
ResetPassword,
CreateFireStoreUser,
SendEmailVerification,
VerifyEmailLink,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
Annd with that, we have completed our Context API file too! Nice :000000. Well, the article went a bit long today but don’t worry we have some output :))
Now in the next part, we will complete the Authentication system with all the screens. We are moving slowly but we will soon be able to see some results. I bet.
I hope you like this part and I will be back with another part soon! Till then
Till then stay safe, stay healthy
Thank you
Also Published Here