/uses Contribution

Way back in January, Wes Bos released his /uses website. It's a little site that compiles lists of the various things web developers say that they use on their web dev portfolios. It was built on Gatsby and Wes said that pull requests were welcome.

I scrolled through the open issues in GitHub and found one that seemed doable: #274 - Add Twitter card + other meta. I had just recently added social media cards to the Austin PBS site, so I figured it wouldn't be a huge lift.

Social media cards are little cards that preview the content of a website when that website's URL gets posted by a user onto social media. The content of that card, which typically includes the website and/or page title, a website description, and a preview image, is generated by <meta> tags with the <head> of the HTML document.

The meta tags that Twitter needs specifically on the /uses site are:

<meta name="description" content="A list of /uses pages detailing developer setups.">
<link rel="canonical" href="https://uses.tech">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:creator" content="@wesbos">
<meta name="twitter:title" content="/uses">
<meta name="twitter:description" content="A list of /uses pages detailing developer setups.">
<meta name="twitter:image" content="https://uses.tech/twitter-card.png">

Much of this information was readily available within gatsby-config.js, so things like the website title or creator were already present in the GraphQL data layer of the site. The site URL wasn't available yet, so I went ahead and added it to gatsby-config.js:

siteMetadata: {
  title: `/uses`,
  description: `A list of /uses pages detailing developer setups.`,
  author: `@wesbos`,
  siteUrl: "https://uses.tech",
},

With the metadata available in GraphQL, it was just a matter of plugging that data into the <head> of the document. The tool for doing that is React Helmet. In short, React Helmet allows you to use a <Helmet> component within JSX, and it will place children of that <Helmet> component within the <head> of the document. I added this to header.js:

<Helmet>
  <html lang="en" amp />
  <title>{siteTitle}</title>
  <meta name="description" content={siteDescription} />
  <link rel="canonical" href={siteUrl} />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:creator" content="@wesbos" />
  <meta name="twitter:title" content={siteTitle} />
  <meta name="twitter:description" content={siteDescription} />
  <meta name="twitter:image" content={`${siteUrl}/twitter-card.png`} />
</Helmet>

The last thing that was needed was the twitter-card.png image file that would get used for the site preview when embedded. This threw me for a bit of a loop. Images can be pretty complicated when it comes to Gatsby. The gatsby-image plugin ecosystem is awesome, but not always straightforward. Essentially you tell this plugin what images you want to use on your site, and it will generate optimized versions of those images that you can drop onto yourself again using GraphQL. It's a lot of steps.

However, that wasn't what I needed. This wasn't going to be an image that would be embedded within the HTML of the site, so it didn't need all of the fancy gatsby-image processing work done to it. Instead it just needed to be in a place where Twitter could find it. Again, this isn't something that's super straightforward in Gatsby world.

The solution is to place it within a static folder that lives in the root of the project directory. This is a folder where you put any files that need to be served statically from the site -- any simple front end JavaScript or image files that otherwise don't need the server to process or run them.

So with all of that done, I submitted the PR and Wes approved it. Cheers to my very first open source project pull request getting merged! It was definitely cool seeing the social media previews showing up as other devs added to the site and then shared their work on Twitter.

You can check out the pull request here.