| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||
In this post, we'll be building (and deploying) a scalable, full-stack chat application using Firebase, NextJS, and ChatEngine.io!
Here, we will connect the three to make the amazing chat app above - in about 15 minutes of work!
Taking a step back, let's make the folder we'll run this project inside:
mkdir chat-firebase-next
cd chat-firebase-next
code .To setup a firebase project, make sure you have the Firebase CLI installed and a Firebase account.
Now, open a terminal in this new folder, and start a firebase project with firebase init command. Make sure you pick the following options below:
Now, when you run a free command you should see the following:
.
├── .firebaserc
├── .gitignore
├── firebase.json
└── functions/I'll list each item below:
On that note, let's setup an Express JS server in Cloud Functions.
We'll be connect all our Users to Chat Engine so they can use Chat Engine's chat infrastructure. The Chat Engine backend will handle all our web-sockets, chat storage, and everything else.
We need to make Rest API calls to Chat Engine whenever a new user Signs Up, and delete their account whenever they leave.
To start, hop in functions to install axios and hop back out:
cd functions
npm i axios
cd ..The dependency axios will make our API calls to Chat Engine.
Open the functions/src/index.js file in your IDE and the following code:
import * as functions from "firebase-functions";
exports.createChatEngineUser = functions.auth.user().onCreate((user) => {
console.log("create", user);
});
exports.deleteChatEngineUser = functions.auth.user().onDelete((user) => {
console.log("delete", user);
});This will simple state when a user signs up or deleted their account.
To deploy this, just run firebase deploy. You will be prompted to enable Authentication and the Blaze plan if you haven't already.
I just enabled Google Authentication and followed the steps in the website.
firebase deployYour backend be good to go! And you should see the following in your functions tab online:
[TODO: image of firebase console]
Now, let's connect this backend to ChatEngine.io!
Chat Engine's APIs let us host chatrooms on their platform, and provide us tools to build pretty chat UIs. We'll be signing up our new Firebase users to Chat Engine automatically here.
Here is the documentation on Chat Engine's APIs: https://rest.chatengine.io
In particular, we'll be using their Create User API and their Delete User API.
To start, go to https://chatengine.io, create an account, and set up a new Project. The Private Key and Project ID will be needed for our API calls.
Now, let's add the code to functions/src/index.js and be sure to replace XXX and YYY with your Private Key and Project ID, respectively.
import * as functions from "firebase-functions";
const axios = require("axios");
exports.createChatEngineUser = functions.auth.user().onCreate((user) => {
axios.post(
"https://api.chatengine.io/users/",
{
username: user.email,
secret: user.uid,
email: user.email,
first_name: user.displayName,
},
{ headers: { "Private-Key": "8c63dbce-80a7-455a-890b-9368d16e1dcb" } }
);
});
exports.deleteChatEngineUser = functions.auth.user().onDelete((user) => {
axios.delete("https://api.chatengine.io/users/me/", {
headers: {
"Project-ID": "794653df-052a-4ad2-b0aa-d6c251a10aef",
"User-Name": user.email,
"User-Secret": user.uid,
},
});
});If you're using TypeScript, you may need to modify the rules in .eslintrc.js like I did below:
rules: {
// prettier-ignore
"quotes": ["error", "double"],
"import/no-unresolved": 0,
// prettier-ignore
"indent": ["off", "always"],
"object-curly-spacing": ["off", "always"],
"@typescript-eslint/no-var-requires": ["off", "always"],
}Our backend is complete! Now users have access to Chat Engine when they sign up and their account goes away is they delete their data!
Let's setup a frontend and connect it to Firebase and Chat Engine!
At the top level of our project, we'll run the command below to make a NextJS project. Be sure to select the following too:
npx create-next-app@latest --tsI highly recommend TypeScript with Chat Engine, you'll see why soon :)
Now you should have a frontend/ folder right next to functions/.
Important side note: Replace styles/gloabl.css with the following code too.
Let's CD into this folder, install dependencies, and run in dev-mode.
cd frontend
npm install
npm run devAnd now you should see a pretty website on http://localhost:3000
For the final push, let's add all the code we need to our frontend!
To start, diable StrictMode in next.config.js and re-run the server with yarn dev.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
};
module.exports = nextConfig;This allows us to connect web-sockets in a NextJS project.
Next, let's delete the following:
Next, let's create an auth page (pages/AuthPage.tsx) with the following code
export default function Page() {
return <div />;
}Next, let's create an chats page (pages/ChatsPage.tsx) with the following code
import { User } from "firebase/auth";
interface ChatProps {
user: User;
}
export default function Page(props: ChatProps) {
return <div />;
}Next, add a loading page (pages/Loading.tsx) with the following code:
export default function Loading() {
return (
<div className="page">
<div className="logo">☝️</div>
<div className="text">Loading your info...</div>
</div>
);
}Finally, modify the pages/index.tsx file to load the pages based on auth state:
import { useState } from "react";
import AuthPage from "./AuthPage";
import ChatPage from "./ChatsPage";
import Loading from "./Loading";
import { auth } from "@/firebase";
import { User } from "firebase/auth";
export default function Home() {
const [user, setUser] = useState<User | null>();
auth.onAuthStateChanged((user) => setUser(user));
if (user === undefined) {
return <Loading />;
} else if (user === null) {
return <AuthPage />;
} else {
return <ChatPage user={user} />;
}
}NEXT_PUBLIC_FIREBASE_API_KEY=AIzaSyDqXgd1AwRdqSCpdrhf_t0-rB1MuE2sd4A NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=chat-rce.firebaseapp.com NEXT_PUBLIC_FIREBASE_PROJECT_ID=chat-rce NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=chat-rce.appspot.com NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=45443650042 NEXT_PUBLIC_FIREBASE_APP_ID=1:45443650042:web:2598e30783c0e0bd545443 NEXT_PUBLIC_FUNCTIONS_URL=https://us-central1-chat-rce.cloudfunctions.net/v1 NEXT_PUBLIC_CHAT_ENGINE_PROJECT_ID=16b08e85-e4c9-4541-b30e-45e157ec3821
Make sure NEXT_PUBLIC_CHAT_ENGINE_PROJECT_ID is there with yuor project ID.
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
Now add this code to AuthPage:
import { auth } from "@/firebase";
import { signInWithRedirect, GoogleAuthProvider } from "firebase/auth";
export default function AuthPage() {
const onClick = () => {
signInWithRedirect(auth, new GoogleAuthProvider());
};
return (
<div className="page">
<div className="logo">👋 💬 🤖 </div>
<div className="text">Welcome to ChatRCE</div>
<div className="text" style={{ paddingBottom: "16px" }}>
Log in with your account to continue
</div>
<button className="button" onClick={onClick}>
Log In
</button>{" "}
<button className="button" onClick={onClick}>
Sign Up
</button>
</div>
);
}
Finally, let's connect our new user to Chat Engine using react-chat-engine-pretty!
Modify pages/ChatsPage.tsx with the following code:
import { auth } from "@/firebase";
import { signOut, User } from "firebase/auth";
import { PrettyChatWindow } from "react-chat-engine-pretty";
interface ChatProps {
user: User;
}
export default function Page(props: ChatProps) {
return (
<div style={{ height: "100vh" }}>
<button
style={{ position: "absolute", top: "0px", left: "0px" }}
onClick={() => signOut(auth)}
>
Sign Out
</button>
<PrettyChatWindow
projectId={process.env.NEXT_PUBLIC_CHAT_ENGINE_PROJECT_ID || ""}
username={props.user.email || ""}
secret={props.user.uid}
style={{ height: "100%" }}
/>
</div>
);
}And we're done!
| Back | FazBrowse Home | New Git URL |