Creating a Twitter module for your Nuxt app
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
1. Setup
The modules we’ll be using are:
- twitter - Which will make connecting to the Twitter API painless.
- 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 - 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:
yarn add --dev twitter fs-extra dotenv
Or if you’re using npm
, run:
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 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
:
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:
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:
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:
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:
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:
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:
<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.
First of all, create a Netlify account if you don’t have one already. After this, choose New site from Git
on Netlify App. 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.
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:
Now create an account on IFTTT. Once done, create a new applet by visiting 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. 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.