Chat Msg App with Auth & SMS -JS Mastery


Uncategorized

Updated Aug 30th, 2021

Build and Deploy a Full Stack Realtime Chat Messaging App with Authentication & SMS Notifications

Published Aug 30, 2021 – 3.5 hrs

Link to video here.

Medical Pager

Works with Stream. GetStream.io is the number one Chat Messaging platform that allows you to build scalable and custom chat applications using their APIs.

Time Stamps

00:00:00 Intro
00:05:40 Setup
00:11:21 Initial Structure
00:50:07 Client-Side Auth
01:08:57 Server-Side Auth
01:29:32 Client-Server Communication
01:45:15 Channel Container
02:01:57 Create Channel and Sidebar
02:58:22 Edit Channel
03:06:47 Search
03:17:43 Twilio SMS Notifications
03:28:38 Deployment

Chapter Details

Intro

Wow.

Node, React, React Context API, Stream.io, Twilio. General Page. Deploy.

Medical Pager.

Login and registration form. Added to Database. Emoji Reactions, Threads for replies, Gifs, Search, Mobile-responsive.


Setup

Empty folder on desktop then open in VS Code

two directories, client and server

in the client folder

install create-react-app

delete src contents and add App.js file and index.js file that connects to index.html

Build out App.js file

install dependencies

npm install stream-chat, stream-chat-react, univeral-cookie

entire code on github


Initial Structure

import everything

Get API KEY from stream website and store in constant variable

Create instance of stream chat

Specify client and theme

Add component folder and build out components ChannelCOntainer.jsx and ChannelListsContainer

Add a new index.js file to hold all of your components so we can just import that file into App.js instead of crowding App.js with lots of import lines.

Uses BEM methodology.

Copy and paste all styles into App.css file from the GitHub gist link, (1800 lines of code).

Note: I know CSS isn’t the purpose of this video but skipping 1800 lines of CSS code in a 3.5 hour video gives you some idea of how long it would take to build this from scratch. Knowing how to build out the CSS is very important.

import the “App.css” file into the “App.jsx” file.

import things into ChannelListContainer.jsx component

Create assets folder to source built-in icons. These are SVGs stored in components and “.png” files and a “.jpg.”

Left Sidebar

Add Functional Comp named Company Header

With Stream you build out the JSX.

Implement a Channel Search

Bring in UseState amd UseEffcte

useChat Content from “stream chat react”

Add input with value and onChange

query, setQuery to useSate with emoty string

prevent default on an onSearch fcuntion

create a loading setLoading state

setQuery(event.target.value)

getChanne;ls

Const getChannels – async ()text -> {}

try catch

better comments VSCode extendion

Add Channel List into Channel List Container

filters pops

chammel Remder Foleten F

List props

if error return type — “team ? (…)

if (loading) return same div

render ()

Create TeamChannelPrview

Will receive a lot of porps. Add a a Preview rht

import Avatar and useChatContext from “stream0chat-react”

simple p tag and “# {channel?.data?.name || channel?.data?.id}

const driect Prview

We do not get back an array

We need to turn the object into a array using object.value().fitler(membrr => {})

Return block of JSX with Avatar component passing it props of image and name and size.

below the avatar add the members name

in the main return block have a dynamic classname


Client-Side Auth

import auth

will get AUTH token if logged in so based on that show or hide he form

hide everything o not logged in.

inside of the Auiht.jsx comp we need useTstate and cookies from “universla colkied” and need to install and import axios.

create layout for auth

dive with auth__form-container and inside form

create a variable isSignup and setIsSignipe with false das default

Nice blue screnn to sign in

out browser side by side with editor

Add a form with onSubmit propeot

isSignup && (..)

this is an alternagiv to the ternary opeator.

add a label with htmlFor properot

Add na inupt with name and type and placeholder and onCHange propoety to add function called handleChage and make this reauire. Cannot have emoty onf subnut

Need to create handleCHange

To see for now change useState for teuw.

username is not oin the block

Add another input for username byt duplicating

Add another inputphonenNUmber

add another input avatar URL

Add input for Passowrd

One more field by repeating password and use isSignuo block

name need to be correct because this is how we are managing data

Add a aith_form-conteinat_field-account

if is Signup ? Already have an account : Don’t have an account

Have a span with an on Click pointing to switch mode and define this up top and setIsSiunup to not previous is signup (state depending in previous state)

diplay an image next to iur form

add a classname to a div and inside add an img with src

Looks great on fullscreen.

Handle the data from all of the inputs with a new state field called form

initial state shuld be am object with fullname, userna,epaddowrd, confiormPassword,

Add onHandleCHange that receives event and setForm and spread input in the field using e.target.name

Keeps track of every single keystroke (need a throttle function)

Forgot to add a fields-content_button tot he form and then conditionally render sign up or sign-in

Add a handle Submit union for that that accept event and prevent the default.

We see the data object in the console. Thisis wjat we want to send to the erver


Server-Side Auth

CD inot the server directory and create new index.jsx file. In the terminal and run npm init-y and now we need to install all the dependencies

keep to terminals open

tweak some scripts in the package.json file

Add basic express server.

specific port or 5000

require dotvevn.confiog so we can use env variable

app.us cors, express.jsons, urlencoded

app.get for the first route using res.send

app.listen(port => {…})

Minimum instance of express application

Add route by requiring routes file at the top and then create a route folder and an auth.js file

require in express and the router

add a router.post() to “signup” and another for “/login”

Create controller folder and “auth.js” file

create login and “isSignup” functions

with module.exports o {signup, oign}

import these functions into the “route/auth.js” file

export router

build out signup function with try catch blocks. inside the catch block throw and error if there’s a problem UI the try block destructure from req.body

import crypto and all other packages

implemt user id with random crypto stream.

Connect form getStream but need to pass some things. But these need to be protect so we will use env variables.

We find these value from the stream dashboard.

Add a .env file in your application

Paste in values formthe stream dashbaord.

const hashedPassword set equal to await bcrypt.hash(passpowrd, 10)

remember 10 is the salet.

const token

res.status(200).json

Creta login function as asuyn function and destrcuture form req.bodya nd connect the client and new instance of StreamChat.getInstance with (api_key and Api_secret)

const {users} = await client.queryUsers()

if no users res.status.400.json()

const suvccess = await bcrypt.compare (password, users)

create new use token const token – serverCLient.createuserToken(I)

if success then send data back res.status(200).json(pass data back here0

else res.statuis(500).json ()incorrect


Client-Server Communication

get data out of it const {} -= form

cont URL – http://local:5000/auth

now make an axio scall sont data = await axios.post()

We have a dynamic url iside of our string

destrcuture token, useriD, hashedpasssord,

crate instance of cookies

then cookies.set(token, tokemn)

repeat three times for username na dfullanem adn iserId

if isSignup set phone number and avatar and hashed password.

Storing eveyrhtingin cookies right

reload browser with window.location.reload.

cookies.get()

if authtoken then client.connectUsr({})

cookies.get()

We are in an object so we need a key

shortcut magoc to format data

need userid to be id and

connect usr accept second parameter

user will be connected and get his messages

Test by create user and logging in as that user

get error and cannot connect

require .env config

click signup

we are logged in in stream dashbaord see if the user has been created.

how do we actually logout

go to client/source.ChannelListCOntainer and juyst below crate a new fucntion and clear the cookies and reload the window.

switch cookies.get from cookies.remove and call window.location.reload

pass logout as a prop

Now wehn we log out we go back ot he sign in


Channel Container

Create right part where messages, inputs for messages, gifs, etc.

In channelContainer ad from stream-chat-react., channel and useChatContext

also import channel inner, createchannel, edit channle

Create Channel component

paste in fro channel inner

Add imports for tall of these componentn in the inex.js file

in channel container destrcutu channel from

Decaltre state field right inside of the App.js fiule

ChannelList container gets a buch of props

Channel Container gets a lot of props as well

Accepting all of these props inside of the ChannelContainer

if isCreating return ()

is isEditing retun ()

const EmptyState function Thsi si the beginning of your chat histoyr.

main return()

Channel and props of empty state indicator, message prop that gets function

ChannelInner component

Add one more import to grab their CSS for better looking components

ChannelContainer

Paste in code for Channel Inner Component created out of the box with stream chat.

We shoud now see some good stuff

Test sending a message

Bring in Message Teme comp (deprecated) but stil used

Add emojis, deelte, edit, by built0in stream channel components


Create Channel and Sidebar

Add a button to add a new channel in TeamChanelList

of type == theme and if type !== theme

import an icon from AddChannel component

Add AddChannel to TeamChannelList but we don’t’ have access tot he props we need to pass it. So we need to send from App.js file to ChannelListCOntainer and Destrcutute props

Setiscreating, SrtCreateType, setIsEditing and type

Now we need to acess from Team ChannelLsisrt to access to the same props from,

We will Switch from this prop drilling to React’s context API with time

Now we can pass the necessary props to the AddChannel component

move into the createChannel Component and import useChatContext from “stream-chat-react”

also import userList from “./”

also import closeCreateChannel from “../assets”

return a div with paragraph input and a second p tag

Add handleChage function hooked tot he input

setChannelName

in CreateChannel add some JSX with some condtiinla

closCreateChannle

Add another logicla bloxk to render ChanneInputname

We don’t have access tot he variable

add useState and set to empty string. import from top

UserList component doesnt exist yet, so lets create it right now

import useEffect and useState. Also bring in avatar and useChat Channel from stream chat react

import invite Icon from assets

return som JSx

import into index.jsx

bring browse to the right and ide ot hr ledt

List Conatiner

UserList

seond helper function componentn const UserItem = function

get users by stting state and leveraging useEffct hook with fulters as dependnecy array

if loading, which need to be ste up as a state filed.

try and catch block to query users from cleitn which we destrcuture from useChatContext

const response – await client.queryUsers()

We haven’t declared filters yet, we don’t need now so hold off.

if reponseusers.lentgh then set users to repoosne.user esle setListMpety to tru and in the catch consol.e erro and afte that then setIsLaoding to false

ListCOntainer

users.map() to redner UserIrem compen and pas some thing sot it, index, key,

in UserIte rddner the Avatar iwht he image name and size props

Add icons to see if we are following or not

Able to toggle between them using new useState field set to false ad conditional logic aysing

add onClick to iv and handleSleetec Function that simple sets selected tp prev sletion and notpreviuos seleftd

Click tot toogel users on and off. But we need to keep track of which cine is toggled.

client.userid || empty steing

We need to pas setSlecteUsees to list

if user was seldted callback with prevuser to prevuser.fgilter(prevusers !== user,id)

removce selected user

else setSlectedUsers (prevuser) [..pevuser, user.id]

if error don’t render list container

needs to be inside of list container

Copy if statement and change if error to if list is empty

Now the userList comp is completed. Long component.

Add a button to create channel hooked up to a createChanel function that is an asyn function that gets the vent and ha a try catch block an prevents default and in the try block new chaheln eauls await client.chahnel() and then await newChahenl.watch

also have cleanup setChannelName, setIsCreatign, setSledcteusers, SetActiveChannel

test adding a new channel and we are in

channel doesn’t aear onthe left isde?

lets fix by going to channel list container and we left filters ot be emoty

cerate filters by gettign a list of all the channels and filter out === team and antoher that finds ===messaing

renaming channelListContainer

setCreateYype, setisCreating, setIsEditing, one more state value

Be able to toggle container baed on the wisth of the field

improt useState ad set togleCONtsiner, setToofel COtainer state thatis initiia;;ly set to false

waht JSx we retunr a fragemtnt hat get a div with channel-list__cointainer ad inside we render ChannelListCOntent and pass als the props

We dont have to pass iseEditing propert

Under that we have a sif channel-list_container-reonseive. witha style that has left proprty set contiionally 0% or -89% to pull from left side.

also a “channel-list__container-toggle” div with clasName and onclick that has setTofflContainer

Also ChannelLostContent and add prop of setTofleCOntainer

SO we have two version, one for response and one for non-responsive

const filters = {}

Finish left side for the

Pass in a few more places

Pass setToffleCOntainer

Need to implemt clicking on a channel

TeamChannelPreview componeent

setAcive Channel and pas in chnnel variable

Checkout Diretcpreview fucntion in “UserList” file

Creating another doctor account and then go to the dashboard and you will see a list of users.

There is an error in logic that gets fixed.

Test gain and now we see name and not id


Edit Channel

In the EditChannel component, import React and useState

build out JSX that includes a closeCreateChannel with seIsEditing prop

Also has a ChannelNameInput and we need to get these value and store in state

Also render out the user List as self closing component and setSeleteced user so we need to get them and store in state.

Add onclick that points to upodateChannel function that is an asyn function and received event ad


Search

ChannelSearch.jsx component and so set const {} from useChat contex

need a few useTsta efor teamCHannels and directChanlles

now inside of the try blocj setchannlerepsons eto client.queryCHannels and pass some data

also query the users with const useRespoinse = client.queryUsers({}) and pass data into the object

put these into a promise.all const channels, users – await Promise.all([channelResponse, userRespsonee])

if channles.lenght setTeamChannels(channels)

if users.lenght setDirectChannelss(users)

if query exist render s a component called ResultsDropdown and we will need to pass a lot fonf info into this component.

teamchannel, directcahhe, loading, stChannel, srtQuer, etc.

const SetChannel to be

ChannelSearhc is currently not passing any data so we need to fix that

Add useEffct to this fuel and add “query” as a dependency array

ode out results deopdown component and import into the index.js file

Paste in the coed since there is not a lot to leanr form here?

in ChannelSearch we import and add

We are now done with the application


Twilio SMS Notifications

Connectso if a user is not online they wil get a text mesage

create a Twilio account

veryfy email

verify phone

No we are hosting our own code. Testing Get a Twilio trial phone number.

in the server.iundex.js const accountSID = process.ene.twilio_account)sid and const authToken -[ procees..enc.Twilio_auth_token

cot twilioClient = require(twilio)

copuy valuesfrom the web insot your .env file

set up one fmore route that will trigger a specif route

app.post(“./)

const {message, user: sender, type, e,ebrs} = req.bidy

cannot be tested in develpment mode.

if type ==== messaeg.ew ebers.forEavh memmber frun t if usr!onlie twilil.clitne.meddage.create({boyd: “”, messageServcieSID: messageServeiID, to })

const messaging servivceSID – process.ebe_twilio and paste this inot the ,env file

We don’t want to send a message to ourselves so we use a filter function to filter out ourselves

res.status.0.send

return res,sattsus(200) not a new message

this is all the twilio code. they make it ery easy.

emojis work, thresds, wrok , we are finally ready tldepluye


Deployment

deploy backend to heroku

downloads and install heroku cli

run heroku login after stopping both servers. cd into the correct directory.

rungit init in the server idfectory

se tht git remote git add, commit, git push heroku master

application is now live. grab the backend URL and go to iur stream and endter inot the dahsboard webhookrul field in stea,.io

ikn the code updateth hsot url

Deploy he front end to netlify and in cd in the font end code to

now are website is live!

group chat with friends