🎉 New! Web Push Notifications for Chatkit. Learn more in our latest blog post.
Hide
Products
chatkit_full-logo

Extensible API for in-app chat

channels_full-logo

Build scalable realtime features

beams_full-logo

Programmatic push notifications

Developers

Docs

Read the docs to learn how to use our products

Tutorials

Explore our tutorials to build apps with Pusher products

Support

Reach out to our support team for help and advice

Sign in
Sign up

Implement rich link previews in a React chatroom

  • Ayooluwa Isaiah

April 2nd, 2019
You will need Node 8+ installed on your machine.

It is a common feature for chat applications to show a preview of web content like articles, pages, and tweets shared in the application. It’s easy to add this feature to a Chatkit powered application with only a few lines of code, as I’m about to show in this tutorial.

At the end of it all, you should have an application that looks like this:

This tutorial builds upon what was covered in the tutorial on sending direct messages with Chatkit, so you need to go over that one first before moving on to this one. You can clone this GitHub repository and follow the instructions in the README file to get set up.

Prerequisites

Prior experience with building React and Node.js applications is required to be able to follow through with this tutorial. You also need to have Node.js (version 8 ) and npm installed on your machine. You can view this page for instructions on how to install Node and npm on your machine.

Install additional dependencies

We’ll be making use of the microlink package to provide rich link previews in the application so we have to install it first. microlink also depends on the styled-components package so we’ll install that as well.

Run the command below from the client directory to install them both:

    npm install @microlink/react styled-components --save

Detect the presence of a URL in the message text

The first thing to do is detect the presence of URL in a message and display the link appropriately in the rendered message. To do this, we’ll use the power of regular expressions to parse the text and then wrap the URLs in an anchor tag.

Open up client/src/components/ChatSession.js and change it to look like this:

    // client/src/components/ChatSession.js

    import React from "react";
    import Proptypes from "prop-types";
    import { format } from "date-fns";

    const insertTextAtIndices = (text, obj) => {
      return text.replace(/./g, function(character, index) {
        return obj[index] ? obj[index] + character : character;
      });
    };

    const ChatSession = props => {
      const { messages } = props;
      return messages.map(message => {
        const time = format(new Date(`${message.updatedAt}`), "HH:mm");
        const urlMatches = message.text.match(/\b(http|https)?:\/\/\S+/gi) || [];

        let { text } = message;
        urlMatches.forEach(link => {
          const startIndex = text.indexOf(link);
          const endIndex = startIndex + link.length;
          text = insertTextAtIndices(text, {
            [startIndex]: `<a href="${link}" target="_blank" rel="noopener noreferrer" class="embedded-link">`,
            [endIndex]: "</a>"
          });
        });

        return (
          <li className="message" key={message.id}>
            <div>
              <span className="user-id">{message.senderId}</span>
              <span
                dangerouslySetInnerHTML={{
                  __html: text
                }}
              />
            </div>
            <span className="message-time">{time}</span>
          </li>
        );
      });
    };

    ChatSession.propTypes = {
      messages: Proptypes.arrayOf(Proptypes.object).isRequired
    };

    export default ChatSession;

First, we match the message text against a regular expressions and return an array of URLs found in the message text or an empty array if no links are present in the message. Next, each URL in the array is wrapped in an anchor tag with the help of the insertTextAtIndices() function.

The result is that URLs found in the message are rendered as links in the chatroom and each link opens in a new browser tab as shown below.

Using the microlink React package to render rich link previews is pretty easy. All we need to do is import the card preview package and pass the URL to render. This card visualization is shipped with a default minimal style which is easily customizable in your CSS if you wish to change the it.

Update your client/src/components/ChatSession.js as follows:

    // client/src/components/ChatSession.js

    import React from 'react';
    import Proptypes from 'prop-types';
    import { format } from 'date-fns';
    // import the package
    import MicrolinkCard from '@microlink/react';

    const insertTextAtIndices = (text, obj) => {
      return text.replace(/./g, function(character, index) {
        return obj[index] ? obj[index] + character : character;
      });
    };

    const ChatSession = props => {
      const { messages } = props;
      return messages.map(message => {
        const time = format(new Date(`${message.updatedAt}`), 'HH:mm');
        const urlMatches = message.text.match(/\b(http|https)?:\/\/\S+/gi) || [];

        let { text } = message;
        urlMatches.forEach(link => {
          const startIndex = text.indexOf(link);
          const endIndex = startIndex + link.length;
          text = insertTextAtIndices(text, {
            [startIndex]: `<a href="${link}" target="_blank" rel="noopener noreferrer" class="embedded-link">`,
            [endIndex]: '</a>',
          });
        });

       // add this line
        const LinkPreviews = urlMatches.map(link => <MicrolinkCard url={link} />);

        return (
          <li className="message" key={message.id}>
            // update the message content
            {urlMatches.length > 0 ? (
              <div>
                <span className="user-id">{message.senderId}</span>
                <span
                  dangerouslySetInnerHTML={{
                    __html: text,
                  }}
                />
                {LinkPreviews}
              </div>
            ) : (
              <div>
                <span className="user-id">{message.senderId}</span>
                <span>{message.text}</span>
              </div>
            )}
            <span className="message-time">{time}</span>
          </li>
        );
      });
    };

    ChatSession.propTypes = {
      messages: Proptypes.arrayOf(Proptypes.object).isRequired,
    };

    export default ChatSession;

At this point, you be able to view a minimal preview for each link shared in the chatroom. If you haven’t already, make sure to start the server using node server.js and the React app by running npm start from the client directory.

Wrap up

In this tutorial, you’ve learnt how easy it is to implement link previews for any URL shared in a chatroom. By doing so, you can improve the user interaction on your site, letting your users see what's behind any link.

You can checkout other things Chatkit can do by viewing its extensive documentation. Don't forget to grab the full source code used in this tutorial here.

Clone the project repository
  • Chat
  • chatroom
  • JavaScript
  • Node.js
  • React
  • Chatkit

Products

  • Channels
  • Chatkit
  • Beams

© 2019 Pusher Ltd. All rights reserved.

Pusher Limited is a company registered in England and Wales (No. 07489873) whose registered office is at 160 Old Street, London, EC1V 9BW.