Build an Interactive Messaging App with Stream, MML, Node and React
Tags: chat, messaging, node, react
Published: 2021-01-08 20:20:27

---
title: Build an Interactive Messaging App with Stream, MML, Node and React
published: true
description: Tutorial on Stream's new Message Markeup Language (MML) written in Node and React
tags: chat, messaging, node, react
canonical_url: https://getstream.io/blog/build-an-interactive-messaging-app-with-stream-mml-node-and-react/
cover_image: https://stream-blog-v2.imgix.net/blog/wp-content/uploads/132e0400f5152cd409759df97fec13d6/NrZR7Rm.png
---

Message Markup Language (MML) enables you to build an interactive messaging experience. MML supports embedding elements as simple as a button to your message or as complex as date pickers and custom forms within your chat experience. MML also supports images, icons, and tables out of the box.

The goal for MML is to provide a standardized way to handle the most common use cases for message interactivity. MML can be extended into custom components using the [MML React library](https://getstream.github.io/mml-react/mml).

## MML for React

The first Stream SDK to support MML is the [Stream Chat React SDK](https://getstream.io/chat/react-chat/tutorial/ "Stream Chat React SDK"). This feature accepts an MML string and renders it as React components. To see specific examples of use cases for MML on React, read our docs for [MML-React](https://getstream.github.io/mml-react/mml "MML-React"). Read more about MML in our [chat docs](https://getstream.io/chat/docs/mml_overview/ "chat docs").

## Prerequisites

Basic knowledge of Node.js (Javascript) and React is required to follow this tutorial. This code is supposed to run locally on your machine. Make sure you have installed [Node.js](https://nodejs.org/en/download/ "Node.js") and [Yarn](https://yarnpkg.com/getting-started/install "Yarn"). You also need to install [create-react-app](https://github.com/facebook/create-react-app "create-react-app"), which helps us kick off our React app.

{% gist https://gist.github.com/nparsons08/d0bb702b4a38dac9f447588798ed1766 %}

You need to create an account for [Stream](http://getstream.io/ "Stream") and start your chat trial. Once you made your account, proceed to the dashboard and grab your app key and secret, we'll need them later.

![Stream Dashboard API Key and Secret](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/32ba4fdd34b006848d3ce540608b5063/dashboard.png)

## Building the App

Our projects consist of a simple backend app written in Node.js, [Express.js](https://expressjs.com/), and [localtunnel](https://www.npmjs.com/package/localtunnel) to expose our localhost to the internet. The frontend app is a simple [create-react-app](https://github.com/facebook/create-react-app "create-react-app") project which uses [Stream-Chat-React](https://github.com/GetStream/stream-chat-react) components that support [MML](https://github.com/GetStream/mml-react) out of the box. Let's start with our Frontend app.

## Frontend

First, we need to create a new React application, install some dependencies, and then open the editor's frontend folder.

{% gist https://gist.github.com/nparsons08/1abc59fc65345274a2acfb6c295a05e5 %}

Open the src/App.css and replace its content with this:

{% gist https://gist.github.com/mahboubii/1d8df70aa3c2233e979de459eacbc1f0 %}

Next, we need to choose a user id and generate a token for this user. Let's call our user "jim", grab your app secret from [Stream Dashboard](https://getstream.io/dashboard/) and head over to this the [user token generator](https://getstream.io/chat/docs/token_generator/). In the user id field, enter `jim` and paste your app secret from the dashboard in the secret field. You now have a user token signed for this user. (Note that in production, you need to generate user token in your backend) Now we need to update our src/App.js file with this and put our API KEY from [Stream Dashboard](https://getstream.io/dashboard/) in line 8 and our generate user token in line 11:

{% gist https://gist.github.com/mahboubii/80bc7acb38a46b8e1175f82e2c7213df %}

Awesome! Our fully functioning chat application is ready! We can now see our app by running `yarn start` or `npm start` from the terminal. Open http://localhost:3000 in your browser and click on the "Create a New Channel" button to create the first channel for Jim.

![Frontend app powered by Stream Chat React components](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/969534619f27be34ad647ad716712aa3/mml-1.png)

## Backend

Here things get interesting. We will create an API that accepts POST requests from the [Stream Webhook](https://getstream.io/chat/docs/webhooks_overview/) system. Using webhooks allows you to integrate your server application with Stream Chat tightly. Our app will use the custom command webhook feature, and this will enable us to create interactive messages similar to how `/giphy funk` command works in Slack.

For our example app, we introduce a new command to our chat application that allows our users to create an appointment. When a user writes a message with `/appointment [title]`, we will show a custom message to the user and follow a few steps to create an appointment in our server application. If you want to know more about how custom commands work best, see the [Stream official documentation](https://getstream.io/chat/docs/custom_commands_webhook/).

Let's create a new folder and start implementing our backend app:

{% gist https://gist.github.com/nparsons08/289d4b7bbe1ea1f847aec207445bda20 %}

We are going to create a basic Express app in the `index.js` file. We are using the `localtunnel` library, which allows us to tunnel our localhost API and expose it on the internet with a random public URL.

{% gist https://gist.github.com/mahboubii/aaa9a4293f5a804f6de1be7c1317cab3 %}

Now you can run your API by running `node index.js` in your terminal, and it should show you an output similar to this:

{% gist https://gist.github.com/nparsons08/b58e69750597ce6fa682dd5d8f673862 %}

Note that the second URL is randomly generated every time you run your API. If you open it, you should see a JSON response like this `{"message": "API is live!"}` in your browser.

To integrate Stream with our backend, we need to get our API Key and Secret from Stream Dashboard similar to our frontend app. Once you got it, update your `index.js` file with the following code. We initialized our `chatClient` using our keys and created an express middleware to verify the request's integrity. That is a crucial step since our API is publicly accessible to everyone; we have to make sure the requests are coming from Stream. You can read more about this [here](https://getstream.io/chat/docs/webhooks_overview/#security-and-performance).

{% gist https://gist.github.com/mahboubii/d34b8d247a2c6e80085d5f7b47ee5c5d %}

In the next step, we will update the `setupTunnelAndWebhook` function to set up our webhook configuration and update our app's settings in Stream. First, we create our `appointment` command and update our Channel type with it. Next, we update the app configuration to forward commands to our server application.

> Note: this step needs to be done only once for a production app. We are running this step every time we run the app as our public URL changes with each run for this tutorial.

{% gist https://gist.github.com/mahboubii/b81a6b3b6ee8d77a8e980a3cad5532e1 %}

So far, great! Finally, we can add the controller to handle the appointment command and respond to the user with our MML string. That is a rather complicated use case consisting of several steps to show the MML and Stream Webhooks' power.

{% gist https://gist.github.com/mahboubii/e94023869f95d491ecd56d1cc78f1aff %}

You can see the full backend code [here](https://github.com/mahboubii/mml-test-app/blob/master/backend/index.js). Let's run our backend app by running `node index.js` and our frontend app by running `yarn start` and see how our app works:

1. User writes a message with appointment command like `/appointment Doctor`

![User starts the flow by running our custom command](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/373b605b7cb4cc74b9f7b8483b3a477b/mml-2.png)

2. Stream webhook calls our server application, we update the message with an [MML Input](https://getstream.github.io/mml-react/components/input#basic-usage) component and ask for user phone number

![User enters phone number](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/99aef87afa19340461abfd88b1aca8ab/mml-3.png)

3. User enters the phone number and click on the submit button

4. Our server application now receives another webhook call, which has a `form_date` object that includes the user's phone number. It stores the number and updates the message to show an [MML Scheduler](https://getstream.github.io/mml-react/components/scheduler#basic-usage) component

![User selects a time slot](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/306dfa9e97a23b944945c3e6539e8f20/mml-4.png)

5. User now selects a time slot and click on the submit button

6. Another webhook call is received by our server application with the selected time slot. Now we make the message persistent, store the appointment in our database and update the message to show an [MML AddToCalendar](https://getstream.github.io/mml-react/components/add-to-calendar#basic) component that allows the user to add the appointment to their calendar of choice.

![User can add the appointment to their calendar](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/4873bf2f73cbaf04dd770b36362d679d/mml-5.png)

![Appointment received on our backend app](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/b5c751475cb95af411df852fecef5ef8/mml-6.png)

## Final Thoughts

We successfully created a sample Chat application powered by [Stream](https://getstream.io/chat/) with custom commands, and MML React components.

MML is a powerful and flexible feature that allows us to support a wide range of use cases in our applications. Stream supports different types of webhooks.

For example, you can create a bot user in channels to respond with custom MML strings whenever a specific event happens or a new message is posted to a channel.

The full source code for this tutorial can be found in [GitHub](https://github.com/mahboubii/mml-test-app).

{% github mahboubii/mml-test-app %}