How To Build a Self-Updating Twitter Banner With Dynamic Content

Display your latest blog articles or your most recent followers without paying a dime

Tobias Schmidt
Better Programming

--

Drink and smartphone
Photo by Nathan Dumlao on Unsplash

The first impression by somebody clicking on your Twitter profile will be your header image. Why not display some dynamic content? There’s no rocket science involved to achieve this, and the possibilities are limitless.

In this article, I want to show you how to easily build this with a simple Node.js script, the Twitter and Medium APIs, and AWS Lambda.

An overview:

  • getting credentials so we can use the Twitter API.
  • creating a Node.js script for retrieving details of our latest followers.
  • retrieving our latest blog article via Medium’s RSS feed.
  • updating a static header image with the images of our followers and our blog article title.
  • putting everything into a Lambda function on AWS which will be executed every 60 seconds.

💡 Even though we’ll be creating infrastructure at AWS, this solution won’t result in any costs due to AWS’ free tier for Lambda.

Disclaimer and Credits: I’ve seen this first at Tibo’s timeline, so I’m definitely not the first one for providing a solution on this and you can also find a lot of other tutorials which helped me a lot when I was stuck at some point taking this journey myself.

Getting started

Let’s set up a new project either via npm or yarn and add the dependencies we need:

  • axios — a simple but powerful HTTP client
  • jimp — image manipulation
  • sharp — converting response buffers into images
  • twitter-api-client — communicating with the Twitter API
  • rss-to-json — for translating XML (Medium Feeds) to JSON
  • serverless — provisioning our AWS infrastructure via Serverless Framework. Install this globally!

We’ll only create a single scripting file at src/handler.js containing all of our needed operations.

Accessing the Twitter API

The next thing we need is access to the Twitter API. So we need to create a new client application at Twitter’s developer portal.

After creating your app, make sure to copy the API key and the API Secret Key. After getting back to the overview screen, select your new app and click on edit on the top right. Make sure to set full permissions (Read and Write and Direct Messages) so we can later on access all of our needed information and update our banner.

The last step is to create our Access Token and Secret. You can do this by selecting your app and switching to the tab Keys and token right beneath the headline.

Most likely, Twitter will also display your API Key and API Secret Key again together with your new Access Token and Access Token Secret. Note down everything. You can’t display those details again!

Initializing our Twitter client

Now that we’ve got our credentials, we can set up our client so we can communicate with Twitter’s API. At first, let’s put all of our keys and secrets and our Twitter & Medium handle into creds.json on the root level.

{
"TWITTER_API_KEY": "5Hn9Z28...BW4lEzD",
"TWITTER_API_SECRET_KEY": "yndh2s5sXLuh...33sbWsbbREZYp4",
"TWITTER_API_ACCESS_TOKEN": "42399689...jQIBa3Ew4RDi5ed",
"TWITTER_API_ACCESS_SECRET": "QgYTQoIueX5S...JHk44vVuty9ewwo",
"TWITTER_HANDLE": "tpschmidt_",
"MEDIUM_HANDLE": "tpschmidt"
}

Now we can create the client with the following code:

For local testing, we’ll directly fall back to our creds.json file and when deploying to AWS, we’ll use our environment variables which we’ll set up later on.

Retrieving Our Latest Followers

Let’s use the Twitter API client to get our latest followers. The response consists of a list of users that each contain profile_image_url_https.

We can download the avatars of the users and then resize the image via sharp and save it to a temporary file.

Working With Medium’s Personal RSS Feeds

Next, we want to get the latest blog article title from our own Medium feed. If you’re running a blog on Medium, all of your timelines metadata is available at https://medium.com/feed/@username.

As we’re working with JavaScript, we want to covert the XML response into JSON with rss-to-json. Afterward, we can easily extract our title. Adding a little bit of padding left and right depending on the size of the title assures us that our title is always aligned centrally for a specific point on our header.

Surely, you’re not limited to Medium. You can fetch anything at this point, even a plain HTML page, and extract the things you want to show.

Updating Our Banner Image

The tricky part is already done now. We’ve retrieved our dynamic content! Now we only need to add a base image for our header into our project into a new assets folder. Here’s an example of mine:

As you see, I’ve left out space where I want to fill in the blog title as well as the pictures of the latest followers. Depending on your image, you have to later adjust the coordinates where we add the overlays for our dynamic content.

Additionally, I’m using another image to mask our follower’s images to have rounded borders. It’s just a white-filled circle with a black background. Make sure to also have it in the same size as our follower’s images (in the example we’re using 90x90 pixels). If you’re preferring squares, just remove the mask calls.

There’s not a lot of magic involved:

  • we’re loading our assets and our pre-saved follower’s images
  • we’re setting font, color, and size for our text
  • we add our images and our headline to the banner

The result is a new file at 1500x500_final.png file at /tmp.

Finally, we just need to update our new header on Twitter!

Automating Everything With Lambda and Eventbridge Rules

Now we’ve got some local script to update our banner. But we want to run this continuously and automatically as often as the Twitter API allows it.

We can easily do this by leveraging AWS Lambda. If you haven’t started with AWS yet, just register yourself (it’s free and you’ll start with additional free limits in the first year, even though there’s a lot of free base contingent for several services like Lambda already).

Afterward, there are just a few things you need to do beforehand:

  • visit your Security Credentials to generate a new key and corresponding secret.
  • install the AWS CLI (e.g., via homebrew).
  • run aws configure to set your credentials from the first steps.

That’s it! You’re good to go.

We already installed Serverless Framework globally so we can initialize a new template file by running sls or serverless. We’ll end up with a new serverless.yml template file that defines all of our infrastructures.

What we want to have at the end:

  • a Lambda function that runs our script.
  • a Lambda Layer that contains our dependencies.
  • an EventBridge rule that triggers our function every 60 seconds.

With Serverless Framework, that’s super simple to build and only a few lines of code.

Let’s have a look at the three major parts:

  • provider — defines that we want to use AWS and sets a few basics like that we want our logs to expire after seven days so we don’t introduce any costs in the future.
  • layers — defines our layer that contains all of our node_modules dependencies.
  • functions — that's where we create our Lambda function.

With the events field, we define that EventBridge will invoke our function regularly.

Before we get to the packaging of our files, we need to add a proxy function to our script which will be later invoked by Lambda.

If you have a second look, you’ll see that we referenced src/handler.handler in the serverless.yml. In our case, the source can be found at src/handler.js. This tells Lambda where to start the execution of our node script.

Final part: packaging our function and our layer.

That’s it! We can now just deploy our whole stack via sls deploy and we’re good to go. If somethings not working out, have a look at the corresponding CloudWatch log streams to find the underlying issue. If everything runs smooth, you’ll see our debug logs:

INFO   Retrieving followers...
INFO Retrieving avatar...
INFO Retrieving avatar...
INFO Retrieving avatar...
INFO Retrieving headline...
INFO Retrieved headline: Distributed Tracing Matters
INFO Adding followers...
INFO Appending image 0 with x=600
INFO Appending image 1 with x=700
INFO Appending image 2 with x=800
INFO Adding headline...
INFO Uploading to twitter...

If you made it until here and everything worked out: nice work! 🎉

💡 Don’t be scared that your code will be invoked every 60 seconds because as mentioned before, there’s a free tier for Lambda on AWS which includes 1m executions and computation seconds per month. As our function only takes a few seconds to finish, we’ll never exceed this in any way.

You can find all of the code at GitHub. If there are any issues or you’re stuck with the descriptions, don’t hesitate on messaging me on a contact channel of your choice.

Wrap up

Even though it’s not a unique thing anymore, having some fun with dynamic content on your Twitter timeline can have benefits in building your audience. Also, you maybe learned something new and enjoyed the process of building this.

Besides that, there are basically no limits on what you can do and add. You can also automate updates to your bio or your avatar.

Be creative, and show it to the world.

--

--

Software Engineer & Serverless Enthusiast, focusing on AWS & Azure as well as Kotlin & Node.js. Always learning & looking to meet people on the same journey!