SEO Images with Unsplash

I added an SEO component to my blog recently and on top of that I decided to set up infrastructure to pull in images for Twitter, etc. The SEO component already handled titles and descriptions for cards on Twitter, but I wanted something a bit more... interesting. I like large images and I eventually want to start drawing images for my blog posts. So I dove into gatsby-transformer-sharp.

The sharp transformer makes it absolutely trivial to handle an image described in frontmatter and post it as a Twitter meta card.

First I jacked the SEO component from the Gatsby starters. Then I added a couple key components. Notably twitter:image and the switch that enabled the summary_large_image card type.

import React from "react";
import PropTypes from "prop-types";
import Helmet from "react-helmet";
import { StaticQuery, graphql } from "gatsby";
function SEO({
description,
lang = "en",
meta = [],
keywords = [],
title,
image
}) {
return (
<StaticQuery
query={detailsQuery}
render={data => {
const metaDescription =
description || data.site.siteMetadata.description;
return (
<Helmet
htmlAttributes={{
lang
}}
title={title}
titleTemplate={`%s | ${data.site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription
},
{
property: `og:title`,
content: title
},
{
property: `og:description`,
content: metaDescription
},
{
property: `og:type`,
content: `website`
},
{
property: `twitter:site`,
content: "@chrisbiscardi"
},
{
name: `twitter:card`,
content: !!image ? `summary_large_image` : `summary`
},
{
name: `twitter:creator`,
content: data.site.siteMetadata.author
},
{
name: `twitter:title`,
content: title
},
{
name: `twitter:description`,
content: metaDescription
}
]
.concat(
keywords.length > 0
? {
name: `keywords`,
content: keywords.join(`, `)
}
: []
)
.concat(
image
? {
name: `twitter:image`,
content: `https://www.christopherbiscardi.com${image}`
}
: []
)
.concat(meta)}
/>
);
}}
/>
);
}
SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.array,
keywords: PropTypes.arrayOf(PropTypes.string),
title: PropTypes.string.isRequired
};
export default SEO;
const detailsQuery = graphql`
query DefaultSEOQuery {
site {
siteMetadata {
title
description
author
}
}
}
`;

Then I stuck an image in my frontmatter for a blog post. The addition of gatsby-transformer-sharp enabled the following query to get the processed image.

export const pageQuery = graphql`
query($id: String!) {
mdx(id: { eq: $id }) {
id
code {
body
}
excerpt
frontmatter {
title
featuredImage {
childImageSharp {
fixed {
src
}
}
}
}
}
}
`;

Then it's a matter of using that query and passing it into the SEO component.

const imageRoot = data.mdx.frontmatter.featuredImage;
let src = undefined;
if (imageRoot) {
src = imageRoot.childImageSharp.fixed.src;
}
return (
<SiteLayout
sidebar={<aside css={{ minWidth: "200px" }}>some stuff</aside>}
>
<SEO
description={data.mdx.excerpt}
title={data.mdx.frontmatter.title}
image={src}
/>

Now to add a new "featured image" that shows up on Twitter, we only need to add a pointer to the image in our frontmatter.

Downsides

I currently use Netlify CMS to edit my blog posts and I'm starting to feel the need for something a bit more custom. Currently, Netlify CMS will blow away the featuredImage key on updates, erasing the Twitter opengraph image from being presented.

Join the Newsletter

My newsletter is where you'll find exclusive content from me. I write about technology, startups, and why you shouldn't call yourself a junior engineer

Web Mentions

Author

Adam Rackis

How though? The image prop is never passed to the SEO component. Is there some Gatsby magic happening there?

github.com/gaearon/overre…
Author

Levi ᕙ(⇀‸↼‶)ᕗ

For tomorrow levi
Author

Adam Rackis

I assume you meant “adding an image” but thank you.

Holy shit I’ve been on this platform for how many years and I didn’t know that 😐😑
Author

Kyle Mathews

No just when he creates the tweet he's adding a screenshot

Author

Kyle Mathews

No image ^^^

Author

Adam Rackis

Hmm - the card never showed up for me when I composed my tweet...

Will take a fresh look tomorrow. Thanks a ton for the info!
Author

Adam Rackis

🤦‍♂️🤦‍♂️🤦‍♂️

LOL. I need to go to bed. So it seems he’s just terminating the default Twitter card altogether and adding his own screen shot. What’s the secret sauce for killing the card?
Author

Kyle Mathews

Dan's just adding a screenshot though it seems

Author

:party-corgi:

I mean, the tweet from Dan is just a pasted screenshot into the tweet.

Author

Kyle Mathews

I think you can just delete it when creating the tweet :-)