The Localhost

Modern web development guides hints and tips.

Open Graph Images with Gatsby and Now


I recently purged all the cover images from this site to reduce the overall size of the project, plus they don’t really add to the content.

The only real plus for having a cover image was to that I could get the sweet preview cards you get when sharing on social platforms like Twitter and LinkedIn.

I followed the awesome video content and blog post from Leigh Halliday to build my own. I now have a way to generate social sharing cards without having to add a cover image to every post I do.

Check out the interactive example to have a play with and understand how the card in generated.

This isn’t going to be a step by step guide on how to do that as Leigh has done a really good job of that with this videos.

I’ll list them out here with my own commentary on my findings.

Build and deploy

Leigh really suffered with the Now CLI and was constantly restarting it, now it is a bit more permissive so if you follow along you won’t get as many issues.

You will need to now your project before you can run now dev however. It needs to be on the platform before you can use the now dev locally.

It’s not essential it’s on GitHub at this point as you can add in the integration later on the Vercel dashboard.

For me, to begin with, I couldn’t work out why I kept getting these error messages:

no tsc config error

The reason? I didn’t have a tscconfig.json file in the project so the Now platform had no idea what to do with the project!

Here’s Leigh getting set up:

Cool, cool, after that video I had a card rendering to HTML after running the now dev command.

Parsing params

Here is where I set up the incoming message variables that will be used to add title, author, etc to the card.

After this I can now add the variables to the HTML being generated.

I didn’t get the issues Leigh was having with the Now CLI having to restart it continually.

Temporary file

Write the HTML to a temp file, which I could create the file but couldn’t access the file locally via the browser like Leigh does. I could cat the contents however.

Taking a screenshot

In this video I set up Chromium so that the HTML that was generated in the previous video can be rendered in super secret ‘headless’ mode in Chromium.

To do this locally you will need to find the path of where Chrome is, for me, being a Linux user I did:

1whereis google-chrome-stable
2google-chrome-stable: /usr/bin/google-chrome-stable

And took /usr/bin/google-chrome-stable for the execPath to be used by Chromium.

Sing us a song while we wait for the build to finish Leigh! 😂

In my project for this I’ve kept the HTML version so I can edit the card locally, if you take a look at my project I’ve left comments in there for what to comment out.

At the end of the last video there Leigh covers how he’s implemented it in his project.

I watched these videos twice before and a third time whilst I followed along, Leigh is a great teacher but there is quite a bit to take in here (for me anyway!).

There wasn’t really any issues with me getting this project up and running, some sticking points were Chromium and not being able to access the local file in my browser.

How to even though?

In the beginning, before I started however, I wasn’t really clear on how to use it in a project.

I reached out to Leigh to clarify,

“do you build it into an existing project you want to use it in?”

Or,

“Or is it something you npm install and use like that?”

Leigh really had to spell it out for me as I was clearly struggling with the concept of how it worked!

So the function lives off on the Vercel platform and creates an image with whatever variables you pass to it.

Interactive example

Here’s an intercalative example, edit the params object here to generate an image:

Pretty neat, right? So how to get that into a project. In the case of this project I used a function to build the URL then passed that into the head of the page with React Helmet.

I jacked this example from Leigh Halliday’s page, in your component you need to build the URL you want to pass to the serverless function. I the case of this project I’m pulling the values from the MDX frontmatter for the title, the rest is either hard coded or pulled from the site metadata.

1const ogImageUrl = buildURL('https://image-og.now.sh/og.jpg', {
2 author: authorName,
3 website: 'thelocalhost.io',
4 title: title.length > 55 ? `${title.substring(0, 55)}...` : title,
5 image: 'https://scottspence.me/favicon.png',
6})

This is what buildURL looks like:

1const buildURL = (url, obj) => {
2 const query = Object.entries(obj)
3 .map(pair => pair.map(encodeURIComponent).join('='))
4 .join('&')
5
6 return `${url}?${query}`
7}

The resulting URL from ogImageUrl is used in React Helmet with the corresponding meta tags for the Open Graph images.

1<Helmet encodeSpecialCharacters={false}>
2 <meta property="og:image" content={ogImageUrl} />
3 <meta name="twitter:image:src" content={ogImageUrl} />
4</Helmet>

There were issues

There was one particular issue that did, and still does have me confused, in the previous code example with React Helmet you see the prop encodeSpecialCharacters set to false.

Well, if I built the site and inspected the source I could pick out the image URL from the page HTML, if you take a look you may be able to see the issue.

page source image url

Here’s an example URL of what is being added to the page source:

1https://image-og.now.sh/og.jpg
2 ?author=Scott%20Spence
3 &amp;website=thelocalhost.io
4 &amp;title=Serverless%20OG%20Image%20Example%20Card
5 &amp;image=https%3A%2F%2Fscottspence.me%2Ffavicon.png

Getting &amp; instead of & so if you copy paste this link into a browser you get this sort of image:

undefined og image

I still get this now if I go inspect the source of a page on the site and opening one of the URLs give the same error.

But it works if you share the link on Twitter or LinkedIn, so, like I said, I’m not entirely sure what is going on there.

Check out the videos from Leigh, the source for his project is available here, and you can see the implementation of his OG Image function in his site.

Mine are pretty much the same, except for different styling on the card, here’s source for my Generate OG Image and also how I’m implementing it into this site.


A Digital Garden...
Moving Large Markdown Assets to a CDN... →