How to automate twitter card images for your blog

You work hard to create quality content. And you would like that content to stand out as it deserves. One thing that can help you with this is to create nice images that go with your content. Everytime your content is shared on Twitter, the image is there, like the cherry on the cake.

A Twitter card image example

You do this by setting a couple of meta tags on the page:

<meta name="og:image" content="path-to-my-image" />
<meta name="twitter:card" content="summary_large_image" />

But nobody likes to create those images manually. We’re just to busy or we simply forget out them. The good news is there are ways to automate the image creation process. You’ll never have to manually make them again.

How to do it

One popular way to generate them is by using an online service like Cloudinary. For an in-depth example take a look at Jason Lengstorf.

My problem with this approach is that the images are generated on the fly everytime they are requested. Yes, they are not stored somewhere, they are generated on the fly. This is a waste if you ask me. Cloudinary(and others) has a free plan that might be enough for you or not. I’m not sure what happens if you reach the limit.

How to do it with Gatsby

Another solution, a better one in my opinion, would be to generate the images only once, on build. Then host these generated images in the same way as the rest are.

Since I’m using Gatsby the obvious solution for me was to use a plugin that does this. I coundn’t find one so I decided to create one myself, gastby-plugin-twitter-card!

Let me show you how I integrated it:

Install the plugin

npm i gatsby-plugin-twitter-card

Put the plugin in gatsby-config.js

I use a template image (twitter-card-template.jpg) and on it draw two texts: the article title and the site name using ‘IBM Plex Sans’ font(so it matches the website font)

Finally, I also draw a small top border.

module.exports = {
  plugins: [
    ...{
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          ...{
            resolve: `gatsby-plugin-twitter-card`,
            options: {
              tinypngApiKey: process.env.TINY,
              width: 1280,
              height: 669,
              templateImage: "content/assets/twitter-card-template.jpg",
              backgroundColor: "#fff",
              fonts: [
                {
                  file: "content/fonts/IBMPlexSans-SemiBold.ttf",
                  family: "IBM Plex Sans",
                },
              ],
              texts: [
                {
                  text: "$title",
                  color: "#222",
                  font: '48pt "IBM Plex Sans"',
                  x: 450,
                  y: 669 / 2,
                  maxWidth: 700,
                  lineHeight: 60,
                },
                {
                  text: "raresportan.com",
                  font: '26pt "IBM Plex Sans"',
                  x: "center",
                  y: 669 - 36,
                  color: "#444",
                },
              ],
              borderTop: {
                width: 30,
                color: "#fce000",
              },
            },
          },
        ],
      },
    },
  ],
};

Add the image in the page meta

First, in the blog post template (renders all posts), you need to get the twitterCardImage field:

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      excerpt(pruneLength: 160)
      html
      frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
        description
      }
      fields {
        twitterCardImage
        readingTime {
          text
        }
      }
    }
  }
`;

Send the twitter card image to the SEO component or whatever component renders the meta tags:

<SEO
  title={post.frontmatter.title}
  description={post.frontmatter.description}
  twitterImage={post.fields.twitterCardImage}
/>

Finally render the meta tags, in the SEO component:

const SEO = ({ description, lang, meta, title, twitterImage }) => {
  // other stuff here
  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={`%s | ${site.siteMetadata.title}`}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          property: `og:image`,
          content: twitterImage,
        },
        {
          name: `twitter:card`,
          content: `summary_large_image`,
        },
        {
          name: `twitter:creator`,
          content: site.siteMetadata.social.twitter,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
        {
          name: `google-site-verification`,
          content: `xDnpQH7jmHWkQ6saBRffZ-vUNSuucsqYyhdSd0PikSw`,
        },
      ].concat(meta)}
    />
  );
};

Generate the images and test them

Run gatsby develop and you should see images generated in static/twitter-cards/ folder. Publish the changes and made them live.

To make sure everything is working correctly, use the Twitter card validation.

Tweet an article

Now you can share one of yours articles on Twitter. Look at how beautiful they are 😃!

Want to learn more?