Learning Meteor.js: A Simple Chat App Tutorial

Meteor.js allows developers to share their JavaScript between the client-side and server-side in a project. Let’s see how by building a simple chat application using Meteor.js and Twilio’s IP Messaging.

Getting the Band Together

There are just two prerequisites to our application before we get started:

With that out of the way we can start hacking.

The First Star I See May Not Be A Star
We’ll start by creating a Meteor project called simplechat:

We can run our app straight out of the box by going into the directory in which it was just created and running the meteor command. Now browse to http://localhost:3000 and check it out:

Click the button and see Meteor in action. We’ve done it, we built our first Meteor application! I hope you all have enjoyed this blog post… What’s that? What about chat? Oh yeah, I guess we still need to build the chat part of our chat app. Before we do, open up simplechat.js and take a look at the default code:

Client code and server code in the same file? #MindBlown

Although having all our code in the same file is convenient the first step we’ll take in building our chat app is separating out client-side and server-side code. We’re doing this for two reasons:

  1. It makes the code a bit easier to digest
  2. We’ll be using our Twilio credentials on the server side and we want to keep them secure

Luckily, the process of separating our code isn’t too painful. Start by creating two new directories called client and server:

Now create a new file called main.js within the client folder. For the moment, we’ll just move everything within the isClient section of simplechat.js into this file:

Next create a file called app.js within the server directory. We’ll move the code from within the isServer part of simplechat.js to this file:

Clear out any remaining code in your simplechat.js. If you leave the meteor command running Meteor will automatically reload your changes as you make them. If you stopped the command before fire it up and again. You can leave this command running while you’re coding and only restart it if you’re adding a dependency to your app:

We’ll be using some very basic routing in our application to make sure the proper content loads when a user visits the homepage. Fortunately there’s a great library called Iron.Router that we can use to make this happen. We’ll start off by adding it to our project:

Are you ready to write some code? I’m hope so because the time has come. Open up client/main.js and delete all the current code. Let’s create a route for the homepage:

If you run the app you’ll see we currently have an error:

As the error message is clearly telling us, we need to define our home template. We can do that in simplechat.html which Meteor created when we ran meteor create. Let’s delete everything in that HTML file and start fresh:

By defining a <template> in our HTML, Iron.Router knows to automatically put that template into the <body> element of our page. Our home <template> just has a form that lets a user share something in the chat.

Go back to the page in your browser and you’ll see that we’re no longer getting the error about missing the home template.

It’s time to add the Twilio IP Messaging library. Typically, you’d just add the <script> in the HTML directly but because of how Meteor handles the DOM we need to get a bit more fancy to ensure the library has loaded before the template. To make that happen we’ll use an Iron.Router extension called wait-on-lb:

Replace the code in client/main.js again (last time, I promise!) and we can take advantage of waitOn to load the Twilio library and then render the template.

In order to create an authenticated IP Messaging client that can talk to Twilio, we need a token generated on the server. We can generate this token using the Twilio node module. By default we can’t use npm to add node modules to our project so we need to install the Meteor npm library:

We have to run our app once after installing this library so that Meteor will generate a packages.json. After we run the app can add the Twilio node module to our packages.json:

Within server/app.js we’re going to create a new method called getToken

You need to update this code snippet with a few different pieces of information:

  • Your Twilio Account SID: which can be found in your account dashboard
  • Twilio API Key and Secret: you can generate these here
  • Service SID for your IP Messaging app: We can generate a new service and get the SID with the API:

With our server-side code in place, we can update our client to request our token and initiate and new messagingClient  in client/main.js:

Right now the token we are generating hard-codes in our identity as ‘Alice’. Before we move into the next section, let’s update our server code in server/app.js to give each user a unique name. Typically you’d want to assign this name based on some authentication layer that already exists in your application. Since we don’t have an authentication layer we’ll just assign a name at random:

Is This Thing On?
Now that we have our foundation in place, we need to place users in a channel. We’re going to place all users in the same channel chattime. In client/main.js we’ll add code that checks if our channel exists. If it does the user will join it and if it doesn’t, the user will create it:

In this code we’re calling configureChannel. Astute readers will notice that function doesn’t exist yet. Let’s write it now at the end of our client/main.js file:

This function is a little beefy, let’s walk through it:

  1. We’re storing our channel in a global variable called currentChannel.
  2. We’re joining the channel.
  3. We’re setting a messages array in the user’s session. This will allow Meteor to automatically update the UI when that session data changes for a user.
  4. We’re adding a listener to detect when new messages are added to the channel and updating our session to contain the new message.

We have the code in place to update things when a message is added, but we need to allow a user to actually add a message in the UI. Meteor makes this really easy. We’ll create a new event on our template at the bottom of our client/main.jsfile that takes care of this for us:

With template events we pass a CSS selector to identify the element we want to detect events on. In this case we’re detecting when our .new-message form has been submitted. Within our event we can pull the text from our input and send it to our channel.

Start up your application and give it a try.

You probably realize what’s missing. We need to display our messages in the UI.

Create a new helper on our Template at the bottom of client/main.js to return all the current messages:

All we have to do now is update our HTML to display those messages. Meteor takes care of updating this element whenever a new message is added to our session:

Fire up the app, open another browser window and see your first chat application in action!

You probably don’t want to chat with yourself. Let’s get this app deployed:

Welp, that was easy. Once the deployment is done you can share that URL with your friends and start chatting.

What Will You Build Next?
Meteor is super rad and makes building an application like this really easy. Looking for some improvements you could make? Here are a few ideas:

  • Use Iron.Router to have multiple rooms based on different URLs that users can enter
  • Add a buddy list to show who else is currently in the chat room
  • Give users the ability to invite each other to rooms

Have questions about this hack or want to share what you’ve been building with Meteor? Hit me up on twitter (@rickyrobinett) or drop a message in the comments below.

  • Vandna

    Meteor.js is a good app to chat. THANKS FOR a Simple Chat App Tutorial.

    http://www.kalailm.com/istikhara-for-getting-marriage-method-in-urdu/

  • priya gupta

    Meteor.js is an open-source platform built on Node and MongoDB. It’s not just a framework, it’s more than that.

    http://www.discoveryofjolly.com/chinnamasta-mantra-helps-to-remove-obstacles/

  • Brandon S. Brandon

    Do you have a github for this tutorial? I’m having a problem with my main.js file and I would like to see your completed file. For more information on my error:

    Error Message:

    client/main.js:1:18: client/main.js: Unexpected token (1:18)

    I have sent you an email to your Twilio email account with information on how to check out the contents of my “main.js” file if you would like to take a look. Thank you for your help.

    Best,
    Brandon

    • Siddharth

      Did you get a solution to the problem? Please share it.
      Thanks,
      Siddharth

    • Siddharth

      hey you might have deleted the code

      Router.route(‘/’, {

      waitOn: function () {

      return IRLibLoader.load(‘//media.twiliocdn.com/sdk/rtc/js/ip-messaging/v0.8/twilio-ip-messaging.min.js’);

      },
      So the problem is coming.. same happened in my case.. anyways the error is gone but the app is still not working may be because of the serviceID that I was unable to run through the ‘curl’ command. If you get the app running then please notify and help me so that i can run the curl command and get the service sid..
      @brandonsbrandon:disqus

    • Agree that a GitHub would be nice.

  • Siddharth

    am getting an error:

    {“message”: “Missing required parameter FriendlyName in the post body”, “status”: 400}curl: (6) Could not resolve host: —data

    curl: (6) Could not resolve host: FriendlyName=simplechat

    pls help me rectify it

  • Nate

    I am having an issue running the curl command:
    Error states: {“code”: 20003, “detail”: “Your AccountSid or AuthToken was incorrect.”, “message”: “Authentication Error – {xxx} is not a valid username”, “more_info”: “https://www.twilio.com/docs/errors/20003”, “status”: 401}curl: (6) Could not resolve host: —data

    curl: (6) Could not resolve host: FriendlyName=

  • Nathan

    I solve it just by changing ‘https://webname…’ to “https://webname…”

    Notice the quote. It should be double (“) instead of single (‘).

    • Kevin Hattam

      I found -data didn’t work for me, I used -d instead

  • Kevin Hattam

    I had to do meteor add session as it’s not included by default

  • seoservice