Realtime tweets visualizer with Pusher and Zappier

Eugene Musebe

Introduction

In this Mediajam, I'll be taking you through the process of building a real-time tweets visualizer using

Nuxt.js as the web development framework. We will be using

  • Cloudinary to store a tweet image template and perform transformations on it.

  • Pusher to receive real-time tweet events.

  • Zappier to easily automate the collection of tweets from Twitter and send them to Pusher.

The article assumes that you are familiar with Javascript and Nuxt.js.

Visit the codesandbox below to test the final product:

Projects Final Folder structure

📦realtime-tweet-visualizer-nuxt

┣ 📦components

┣ ┣ 📜Hero.vue

┣ ┣ 📜NuxtLogo.vue

┣ ┣ 📜Tutorial.vue

┣ ┣ 📜Tweet.vue

┣ ┣ 📜TweetImage.vue

┣ ┗ 📜Wall.vue

┣ ┣ 📦pages

┣ ┗ 📜index.vue

┣ 📦plugins

┣ ┗ 📜vue-final-modal.js

┣ 📦static

┣ ┗ 📜favicon.ico

┣ 📦store

┣ ┗ 📜README.md

┣ ┣ 📜.editorconfig

┣ 📜.env.example

┣ 📜.gitignore

┣ 📜README.md

┣ 📜nuxt.config.js

┣ 📜package.json

┗ 📜yarn.lock

Getting Started

This tutorial assumes you're already familiar with Vue and Javascript. Node.js and Nuxt.js will also be utilized (some knowledge of the two is expected but not mandatory).

Prerequisites

Installing Node.js and NPM

There are numerous tutorials available on how to accomplish this. On installation and adding the path to your environment variables, you can consult the official Node.js website. You could also look into [NVM], a node version manager (https://github.com/nvm-sh/nvm). I would recommend the latter if you are a power user who will be switching between node versions frequently.

Pusher setup

Pusher is a platform that provides APIs to developers so they can build collaboration and communication features into their web and mobile applications. You should create a Pusher account if you don't already have one. Both the Channels and Beams Sandbox plans are completely free and will work nicely with this example project. To start using pusher in the application do the following :

  1. Create a Channels app by clicking Get Started

  2. Follow the steps in the dialog box to name your app with the name of your preference and also choose a preferred cluster location from the list.

  3. Note the app id, key, secret, and cluster from the App Keys page because you'll need them to connect to your Channels app.

Zapier setup

[Zappier] is a tool that lets you automate tasks and create workflows by integrating various applications such as Twitter. We shall leverage it in the application to track tweets based on the different hash-tags we shall declare.

To get started on using the platform, create or sign in to a Zapier account and perform the following actions :

Apps created in Zapier are known as Zaps

Step 1: Twitter search mention
  • Every Zap requires a trigger. A trigger is basically an event that will run the Zap. Since we want specific hashtags, we will select the search mentions trigger on Twitter.

  • Authenticate Zapier into your Twitter Account

  • Enter the search terms you want to monitor. You may use query operators E.g. #javascript OR #js OR #python OR #java OR #php OR #rubyonrails OR #typescript OR #dart OR #flutter OR #cloudinary

  • Confirm this step works with a test by clicking on the ‘Test and Review’ button which will run the code.

Step 2: Publish event in Pusher

Once an event (hash-tag) has been triggered on zappier, we will need to publish it in Pusher so that we can view it in real-time on the application. To achieve this :

  1. Create a new step by choosing the app Pusher.
  2. You will be requested to input the pusher app keys.
  3. Select the publish pusher event action event.
  4. Set up the action by providing the following information:
  • Channels: tweets
  • Event name: new-tweet
  • Event data:
  • username: Twitter username
  • text: Twitter text
  • full_name: Twitter full name
  • tweet_url: Twitter url
  • user_profile_image: Twitter user profile image
  • created_at: Twitter created at
  • lang: Twitter lang
  1. To ensure everything works well, Test and Trigger an event on Zappier then visit the Pusher debug console in the pusher dashboard to view all the triggered events in real-time.

  2. To be able to get the latest Tweets with hashtags in real-time, click the Activate Zap button which will turn it on.

Project setup

To get started, make sure npx is installed on your system. This can be achieved through:

1yarn global add npx
2
3# OR
4
5npm install -g npx

Then open up your terminal/command line and navigate to your desired Project folder. Run the following command to create your project.

1yarn create-nuxt-app realtime-tweet-visualizer

This command above will ask you a series of questions. We recommend using the following defaults for this project:

  • Programming Language -> JavaScript
  • Package manager -> Yarn
  • UI Framework -> TailwindCSS
  • Nuxt.Js modules -> None
  • Rendering mode: Universal (SSR/SSG)
  • Deployment target: Client-side (SPA hosting)

After installation, navigate to the project folder and launch it with the following command :

1yarn dev

At the root of your project, create a new file and name it .env.local. Inside the file, paste the following data

1NUXT_ENV_CLOUDINARY_CLOUD_NAME=YOUR_CLOUD_NAME
2NUXT_ENV_PUSHER_APP_KEY =YOUR_PUSHER_APP_KEY
3NUXT_ENV_PUSHER_CLUSTER=YOUR_PUSHER_CLUSTER

Replace YOUR_CLOUD_NAME YOUR_PUSHER_APP_KEY and YOUR_PUSHER_CLUSTER with the appropriate values from pusher and cloudinary

Packages Setup

Nuxt Cloudinary

The background card for all the tweets shall be served from Cloudinary. To install cloudinary into the project using npm or yarn run the following command :

1npm install @nuxtjs/cloudinary
2# OR
3yarn add @nuxtjs/cloudinary

Then add @nuxtjs/cloudinary as a module in your nuxt.config.js file.

1export default {
2modules: [
3'@nuxtjs/cloudinary'
4]
5 }

In your nuxt.config.js, create a cloudinary section for your cloudinary configurations.

1cloudinary: {
2
3cloudName: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,
4
5useComponent: true
6
7}

As the background card for our tweets, we shall use this image template. Feel free to grab it and add it to your cloudinary media library. For the purpose of this tutorial, this file is saved using this public id: realtime-tweet-visualizer/tweet_card_template_vazitc

Pusher Js

To install pusher into the application using yarn or npm run the following command :

1npm install pusher-js
2
3# OR
4
5yarn add pusher-js

Trim Character

To trim the text of the tweets to a certain number of characters we shall leverage this package. To install it run the following command :

1npm install trim-characters
2
3# OR
4
5yarn add trim-characters

Vue Final Modal

To render and style the application's components we shall use this lightweight templating package that supports Tailwind CSS out of the box. Run the following to install it into the application :

1npm install vue-final-modal@latest
2# OR
3yarn add vue-final-modal@latest

Then create a main.js plugin file to configure the package in the plugins directory:

1import VueFinalModal from 'vue-final-modal/lib'
2Vue.use(VueFinalModal())

Add the plugin to our nuxt.config.js file.

1export default {
2plugins: ['~plugins/vue-final-modal.js'],
3build: {
4transpile: ['vue-final-modal']
5}
6 }

Receiving tweets from Pusher

We are going to connect our Nuxt.Js application to our pusher app. First, we are going to set the required environment variables. You can obtain these keys by opening your app on Pusher and checking the App Keys tab.

1NUXT_ENV_PUSHER_APP_KEY=
2NUXT_ENV_PUSHER_CLUSTER=

To Display all the triggered tweets from Pusher inside the components directory, create a Wall.vue file which will be used to display all the tweets with declared hashtags in real-time.

In the file, import and create a pusher instance using the above credentials. We shall do this in the same file in order to listen to incoming events.

1import Pusher from "pusher-js";
2const PUSHER = new Pusher(process.env.NUXT_ENV_PUSHER_APP_KEY, {
3cluster: process.env.NUXT_ENV_PUSHER_CLUSTER,
4});

As we shall be listening to only one channel and event, let's set them as constants.

1const CHANNEL = "tweets";
2const EVENT = "new-tweet";

The next step is to subscribe to our channel and bind to the new-tweet event.

1mounted() {
2
3const channel = PUSHER.subscribe(CHANNEL);
4
5channel.bind(EVENT, (data) => {
6
7this.tweets.push(data);
8
9});
10
11},

To notify Pusher that we are no longer listening for events, we shall unsubscribe in the beforeDestroy event lifecycle hook. This hook is called before we destroy the component.

1beforeDestroy() {
2
3PUSHER.unsubscribe(CHANNEL);
4
5},

Rendering tweets

In order to start the rendering of tweets, in the components folder create a TweetImage.vue file. This component shall be used to render the tweets, we shall be using a series of transformations. Let's break them down first before reviewing the full result.

Display the tweet template image

The below code will just display the plain tweet template image. The options specified are:

  • publicId: The public id of the image in Cloudinary

  • secure: Instructs the Cloudinary SDK that we want a secure https resource.

  • width: Specifies the width of the image

  • alt: Alternative text for the image.

1<cld-image
2
3publicId="realtime-tweet-visualizer/tweet_card_template_vazitc"
4
5secure="true"
6
7width="500"
8
9:alt="`${tweet.username}'s tweet`"
10
11>
12
13</cld-image>

Displaying the user's profile photo

We shall now use the fetch transformation to display the user's profile image. To position it correctly, we'll specify the x and y coordinates. We shall then specify maximum border-radius (r="max") to ensure our image is rounded.

1<cld-transformation
2
3:overlay="`fetch:${tweet.user_profile_image}`"
4
5y="-70"
6
7x="-265"
8
9r="max"
10
11/>

Displaying other textual data

To display the user's full name, username, text and created_at, we shall use text overlays.

The challenge is that some characters aren't compatible with the transformation, thus we created the following method to clean the text. We shall first remove all URLs. We shall then remove all characters not included in this regex group: [A-Za-z0-9_@.#&+-].

To wrap the text in the template, we shall add a newline after every 70th character.

1safeText(str) {
2
3return new String(str)
4
5.replace(/(?:https?|ftp):\/\/[\n\S]+/g, "URL")
6
7.replace(/[^ A-Za-z0-9_@.#&+-]/gi, "")
8
9.replace(/.{70}/g, "$&\n");
10
11},

To ensure our texts are safe for usage in URLs, we shall the encodeURIComponent. We shall also specify the x, y coordinates for placing the text. Here is a sample of the code used to transform text onto the template.

1<cld-transformation
2
3:overlay="`text:arial_16_bold:${encodeURIComponent(safeText(tweet.full_name))},co_rgb:34383d`"
4
5y="-85"
6
7x="-176"
8
9/>

Here is the code of home the transformations all come together.

1<cld-image
2
3publicId="realtime-tweet-visualizer/tweet_card_template_vazitc"
4
5secure="true"
6
7width="500"
8
9:alt="`${tweet.username}'s tweet`"
10
11>
12
13<cld-transformation
14
15:overlay="`fetch:${tweet.user_profile_image}`"
16
17y="-70"
18
19x="-265"
20
21r="max"
22
23/>
24
25<cld-transformation
26:overlay="`text:arial_16_bold:${encodeURIComponent(safeText(tweet.full_name))},co_rgb:34383d`"
27
28y="-85"
29
30x="-176"
31
32/>
33<cld-transformation
34:overlay="`text:arial_16_thin:@${encodeURIComponent(safeText(tweet.username))},co_rgb:536471`"
35y="-60"
36x="-176"
37/>
38
39<cld-transformation
40:overlay="`text:arial_16_thin:@${encodeURIComponent(safeText(tweet.text.substring(0, 300)))},co_rgb:0f1419`"
41crop="fit"
42y="10"
43/>
44
45<cld-transformation
46
47:overlay="`text:arial_16_thin:${tweet.created_at},co_rgb:536471`"
48y="95"
49x="-170"
50/>
51</cld-image>

Conclusion

After you've completed all of the above, you should be able to see real-time tweets on the homepage of your app, demonstrating the power of each individual tool used in the application.

The Final code repository can be found HERE

Resources

You may find these resources useful.

Eugene Musebe

Software Developer

I’m a full-stack software developer, content creator, and tech community builder based in Nairobi, Kenya. I am addicted to learning new technologies and loves working with like-minded people.