Creating a Twitter module for your Nuxt app
Tags: nuxt, vue, javascript, node
Published: 2019-11-01 21:28:57

This tutorial covers how to integrate a Twitter feed into a statically generated Nuxt site. We’ll be using Node to pull tweets from Twitter, and IFTTT to rebuild our statically generated site on Netlify every time we tweet.

A demo repo can be found here in case you have any issues following the tutorial: [https://github.com/davidwarrington/nuxt-tweet](https://github.com/davidwarrington/nuxt-tweet)

## 1. Setup
The modules we’ll be using are: 
* [twitter](https://www.npmjs.com/package/twitter) - Which will make connecting to the Twitter API painless.
* [fs-extra ](https://www.npmjs.com/package/fs-extra) - This is optional. You can use the built-in `fs` Node module, but fs-extra makes things a little easier, by removing the need to manually check for pre-existing files and other boring tasks. For this reason we’ll use it in this tutorial.
* [dotenv](https://www.npmjs.com/package/dotenv) - This is used to inject API keys that we don’t want to expose publicly for use during the build process. If you’re already using the `@nuxt/dotenv` module, you can skip installing this.

If you’re using `yarn`, run:
```bash
yarn add --dev twitter fs-extra dotenv
```
Or if you’re using `npm`, run:
```bash
npm install --save-dev twitter fs-extra dotenv
```

Finally, this step is optional, but if you don’t want to fill you commit history with JSON files containing tweets, add `tweets/` to your `.gitignore`. 

## 2. Creating the Twitter Client
To begin with, we need to make sure that we can connect to Twitter. Sign in to [developer.twitter.com](https://developer.twitter.com/) and create an app. This will allow us to generate API keys, in turn allowing us to pull information from Twitter. Once you’ve created the app, open it and visit the `Keys and Tokens` tab. You will need both Consumer API keys and Access Tokens. So you will have to make sure both are generated.

Now onto the code: create a `modules` folder and a `twitter.js` file inside. This module is going to run every time we run either the `generate` or `dev` scripts. This means that when we’re developing locally, Nuxt will pull the latest tweets from our feed and they will be deployed to the live site each time it is rebuilt.

Before we make the Nuxt module itself, let’s build the Twitter client to ensure that we can pull the info from Twitter. 

To begin with add the following lines of code to your `modules/twitter.js`:

```js
const Twitter = require('twitter')
const fs = require('fs-extra')

const client = new Twitter({
  consumer_key: '[CONSUMER KEY]',
  consumer_secret: '[CONSUMER SECRET]',
  access_token_key: '[ACCESS TOKEN]',
  access_token_secret: '[ACCESS TOKEN SECRET]'
})
```

We’ve just imported the `Twitter` module, which will allow us to easily configure Node to connect to the Twitter API. We’ll use the `fs-extra` module, which we’ve named `fs` , to save the data we pull from Twitter in a JSON file.

Replace the string values in `client` with your API keys and the `Twitter` module will be able to connect to the API.

From here add the following code:
```js
const endpoint = 'statuses/user_timeline'
const params = {
  screen_name: '[YOUR USERNAME]',
  include_rts: false
}
const callback = (error, tweets, response) => {
  if (!error) fs.outputJSON('./tweets.json', tweets.slice(0, 5), { spaces: 4 })
}

client.get(endpoint, params, callback)
```

The endpoint is the part of the API we want to connect to. Since in this tutorial we’re getting tweets from our own timeline, the endpoint we’re using is `statuses/user_timeline`.

The params are options we’re sending to configure the endpoint. Since we want our own tweets, the `screen_name` property is our own twitter handle (excluding the @) and `include_rts` just prevents it from including retweets.

The callback tells the client what to do with the tweets it pulls from the API. We only need to use the first two arguments in our module, however I like to include all that are available in case I want to change it later on. In the function we’re simply saying “if the API doesn’t respond with an error, write the tweets to `./tweets.json`, using 4 spaces for indentation to make it nice and readable”. I’m slicing the response to only include the latest 5 tweets. If you want to show more, or even all of the tweets it returns, feel free to replace `tweets.slice(0, 5)` with whatever you need.

Now to test our API connection. In your terminal, navigate to your modules directory and run `node twitter`. This should run the script we’ve just created. If all has gone well, once the script finishes, you should have a `tweets.json` file which contains an array of your tweets, which you should delete to prevent committing them unnecessarily. If not, go back through the previous steps to make sure you’ve not missed anything.

## 3. Building the Nuxt module
From here, converting our Twitter script into a Nuxt module is relatively simple.  At the end of your `twitter.js` module, write the following:
```js
export default function NuxtTwitter(config) {
	this.nuxt.hook('build:before', generator => {
		client.get(endpoint, params, callback)
	})
}
```

Delete the `client.get(endpoint, params, callback)` line we’d previously added in the JS file, as we now only need it inside the module we’re exporting.

Similarly to before, we’re not making use of either the `config` or the `generator` arguments that are passed to the module, but they’ve been included anyway, in case we want to expand the module later.

In case you’re interested, `config`, in this example, is passed in via the `modules` array in your `nuxt.config.js`. When declaring which modules are to be used by Nuxt, the modules array can either accept strings, which are just the module names, or it can accept arrays. The first value in these arrays is the location of the module and the second value in these arrays is the data passed as our `config` argument.

The `generator` argument passed to our callback in the `nuxt.hook` contains a lot of information about the whole process. By accessing `generator.options` you can access your `nuxt.config.js`. It’s worth running the module and either logging `generator` to your console or printing it to a JSON file for a closer inspection. `generator.options` is the method used by a lot of modules to pass module options from within `nuxt.config.js`, but outside of the `modules` array.

By using `this.nuxt.hook` we are able to tell Nuxt to run a function when it hits a certain “hook”, which refers to a stage in its process. The first parameter: `build:before`, represents the stage at which to run the function. The `build` stage is used by both `generate` and `dev` command processes, so it covers both bases. We need to run this before we build the site, because we need to be able to import the JSON data in order to use it within our site.

Also change the first argument in your `fs.outputJSON()` method call from `./tweets.json` to `./tweets/tweets.json`.

## 4. Setting up Nuxt modules
Our `nuxt.config.js` should be exporting a config object. Find the `modules` property in this object. If you don’t have one, create it. The modules property is an array that tells Nuxt which modules to load when it runs. Add the file path and name to help Nuxt find your module. You can omit the `.js` extension in your module name. It should look like this:
```js
module.exports = {
	// other config properties

	modules: [
		'modules/twitter'
		// any other modules used in your build
	]
}
```

So now, if we run `yarn dev`, `yarn generate`, `npm run dev` or `npm run generate`, depending on which package manager takes your fancy, we should find that Nuxt creates the JSON file for us. This allows us to import the data from this file into any pages/components we need.

## 5. Securing our API keys
Before we go pushing any of our code to public repos, let’s hide the API keys so that nobody else has access to them. If you’ve not already installed `dotenv`, do so now. In the root of our project, create a file called `.env`. By default, `dotenv` will take keys from this file and add them to Node’s `process.env`, which is part of any running Node process.

Your `.env` file should look something like this:
```
CONSUMER_KEY=
CONSUMER_SECRET=
ACCESS_TOKEN_KEY=
ACCESS_TOKEN_SECRET=
```

Now move the keys we added to our `twitter.js` `client` to this file, assigning them to the relevant variable. Once this is done, we’ll replace the `client` declaration in our `twitter.js` module with the following:
```js
const client = new Twitter({
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  access_token_key: process.env.ACCESS_TOKEN_KEY,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET
})
```

We’ll also add the following beneath our `Twitter` and `fs` requires at the top of our module file: 
```js
const dotenv = require(‘dotenv’)
dotenv.config()
```

By importing `dotenv` and calling it’s `config()` method, we’re adding the contents of `.env` into `process.env`, which can be accessed by Node.

Also, add `.env` to your `.gitignore` if it’s not already included. This will stop you committing the file to your repo.

## 6. Importing Tweets into Nuxt
With our API keys hidden away and our tweets being written to a JSON file correctly, we can now use them in our build. Just to demonstrate this, we’ll create a list of tweets on our index page. Open `pages/index.vue` and replace all code in the file with:

```vue
<template>
  <ul>
    <li
      v-for="tweet in tweets"
      :key="tweet.id"
    >
      {{ tweet.text }}
    </li>
  </ul>
</template>

<script>
import tweets from '@/tweets/tweets'

export default {
  data() {
    return {
      tweets
    }
  }
}
</script>
```

If you run `yarn dev` or `npm run dev`, you should find that the index page just lists your 5 latest tweets. Our template is importing them via the `import tweets from @/tweets/tweets` line in `index.vue`.

## 7. Deploying our site
In order to get our site live we need to use a deployment tool that can be triggered via webhooks and supports adding environment variables. For the purposes of this tutorial we’re going to use [Netlify](https://www.netlify.com/).

First of all, create a Netlify account if you don’t have one already. After this, choose `New site from Git` on [Netlify App](https://app.netlify.com/). From here we need to connect Netlify to our repository. Choose the Git provider and follow the set up process to launch your site. Netlify will deploy our site by pulling the git repository and serving our chosen folder.

In the build settings, set the build command to `yarn generate` and set the publish directory to `dist`.

Deploying from our site won’t work immediately because we need to add the API keys we hid with `dotenv`. In the site settings find `Environment variables` and add the same variables you have in your `.env` file. 

![Netlify Environment Variables](//images.ctfassets.net/z95r3xeuw1k1/1VEqjsiEDtpysIr5hJnLU7/fa4e21b82a82e491c5a75c823a5cb55c/Netlify_Environment_Variables.png)

## 8. Setting up deployment webhooks with IFTTT
What’s the use in having a Twitter feed on our site if it doesn’t update when we tweet? We’re going to use IFTTT to solve this problem. For anyone who doesn’t know, IFTTT is a service that allows us to automate tasks with “recipes”. We’re going to have a recipe that says “When I tweet, send a request to a predetermined URL”. When Netlify receives this request, it will build the site again, causing our Nuxt module to update the list of tweets.

First of all add a `build hook` in the `Continuous Deployment` section of your Netlify site build settings, like so:

![Netlify Build Hook](//images.ctfassets.net/z95r3xeuw1k1/7krjmYEnXzTDNHa4LcQLRZ/431a9304283f5b7cd5a2c4c0686a51c1/Netlify_Build_Hook.png)

Now create an account on [IFTTT](https://ifttt.com). Once done, create a new applet by visiting [IFTTT.com/create](https://ifttt.com/create). We’ll use Twitter as our “this” trigger. Follow the process on IFTTT to connect it to our account and choose the “New Tweet by you” trigger. The “that” action should then be the webhooks service. Use the service to “make a web request”. Copy the URL for your Netlify build process, change the method to POST and then finish creating the applet.

Now, post a tweet to test that everything has worked. If it has, you should see a new deployment on the `deploys` page of your Netlify site.

Congratulations! You’ve now integrated a twitter feed into your statically generated Nuxt site and learned how to create your own Nuxt module.

You can see the result of this tutorial in the twitter feed at the bottom of each page of [my site](https://ellodave.dev). I've sliced the tweets array to only show the 3 latest tweets though.

If you had any issues following this tutorial, please take a look at this demo Git repo. The commit history for which shows all of the steps taken in this tutorial.

[Repo](https://github.com/davidwarrington/nuxt-tweet)