A real-time chat frontend with plain JavaScript and Feathers
The Feathers documentation has a guide for creating a chat API including a simple frontend. But how do you integrate it with other frameworks? This post is part of an ongoing series for integrating different frontend frameworks with the latest release of Feathers (currently Auk).
You don’t always need a framework though. This time we will dive into creating a real-time chat frontend with signup and login using plain old JavaScript with ES6 which is supported by most modern browsers. This will also help to show what Feathers is about without the distractions that the structure of a framework might bring. You can find the code of the final version here.
Setting up the index page
If you went through the chat guide there will already be a file in public/index.html
of your project. We will now use it to implement the JavaScript chat by updating it to the following:
This will load our chat CSS style, add a container div #app
and import several libraries:
- MomentJS to format our dates
- The browser version of Feathers (since we are not using a module loader like Webpack or Browserify)
- Socket.io provided by the chat API
- An
app.js
for our code to live in
Let’s create public/app.js
where all the following code will live (with each code sample added to the end of that file).
Connecting to the Feathers API
We’ll start with the most important thing first, the connection to our Feathers API. You already saw how Feathers can be used on the client in the building a frontend chapter of the chat guide. Here, we do pretty much the same thing: Establish a Socket connection and initialize a new Feathers application but we also set up the authentication client which we will use later:
This allows us to talk to the chat API through websockets (meaning we also get real-time events when a new message is created instead of having to poll the server for updates).
Static HTML and user/message items
Next, we have to define some static and dynamic HTML that we can insert into the page when we want to show the login page (which also doubles as the signup page) and the actual chat interface:
This will add the following variables and functions:
loginHTML
contains some static HTML for the login/signup pagechatHTML
contains the main chat page content (once a user is logged in)addUser(user)
is a function to add a new user to the user list on the leftaddMessage(message)
is a function to add a new message to the list. It will also make sure that we always scroll to the bottom of the message list as messages get added
Displaying the login/signup or chat page
Next we will add two functions that show the login and chat page where we will also add a list of the 25 newest chat messages and the registered users.
showLogin(error)
will either show the content ofloginHTML
or, if the login page is already showing, add an error message. This will happen when you try to log in with invalid credentialsshowChat()
is a little more interesting. First, we add the staticchatHTML
to the page. Then we get the latest 25 messages from themessages
Feathers service (this is the same as the/messages
endpoint of our chat API) using the Feathers query syntax. Since the list will come back with the newest message first we need to reverse the data and then add each message by calling our addMessage function so that it looks like a chat app should — with messages getting older as you scroll up. Then we get a list of all registered users to show them in the sidebar by callingaddUser
.
Login and signup
Alright. Now we can show the login page (including an error message when something goes wrong) and if we are logged in display a list of the most recent messages and all users. We’ve built out the UI, now we have to add the functionality to actually allow people to sign up, log in and also log out.
getCredentials()
gets us the values of the username (email) and password fields from the login/signup page to be used directly with Feathers authentication.login(credentials)
will either authenticate the credentials returned bygetCredentials
against our Feathers API using thelocal
authentication strategy (e.g. username and password) or, if no credentials are given, use the standard JWT token authentication. This will try and get the JWT from localStorage first where it is put automatically once you log in successfully so that we don’t have to log in every time we visit the chat. Only if that doesn’t work it will show the login page. For more information, see the Adding authentication chapter in the chat guide or our authentication guides. Finally, if the login was successful it will show the chat page.- We also added click event listeners for three buttons. Clicking
#signup
will signup and log in at the same time. It will first create a new user on our API and then log in with that same user information.#login
will get the credentials and just log in with those. Finally,#logout
will forget the JWT and then show the login page again.
Real-time and sending messages
In the last step we will add functionality to send new message and make the user and message list update in real-time.
- The
#submit
button event listener gets the message text from the input field, creates a new message on the messages service and then clears out the field. - Next, we added two
created
event listeners. One for messages which just callsaddMessage
to add the new message to the list and one for users which adds the user to the list viaaddUser
. This is how Feathers does real-time and everything we need to do in order to get everything to update automatically. - To kick our application off, we call
login()
which as mentioned above will either show the chat application right away (if we signed in before and the token isn’t expired) or the login page.
That’s it. We now have a plain JavaScript real-time chat frontend with login and signup. This example demonstrates many of the core principles of how you interact with a Feathers API. I hope you can see just how powerful it is and how Feathers can be used with or without a framework.
If you haven’t tried FeathersJS yet, take it for a spin and let us know what you think in Slack or on Twitter.