DEV Community

Cover image for Next.js: How to Create Open Graph Social Media Cards
Dave Gray
Dave Gray

Posted on • Originally published at davegray.codes on

Next.js: How to Create Open Graph Social Media Cards

When you or your subscribers share your blog posts on social media, you can make them stand out with Open Graph Social Media Cards. In this article, I'll discuss what Open Graph is, why you should have it in your page metadata, and a few different ways to add Social Media Cards to your Next.js blog.

What is Open Graph?

Open Graph protocol was created by Facebook as a standardized way
to provide metadata for a webpage. Colby Fayock provided a nice explainer article called "What is Open Graph and how can I use it for my website? " that was published by freeCodeCamp. I highly recommend it.

Why Should I Put Open Graph in My Blog Metadata?

Simply put, you want your blog posts to stand out when they are shared on social media.

If you don't provide Open Graph metadata in your blog, a post might look like this when you share it:

Tweet without Open Graph metadata

But if you do provide Open Graph metadata, a shared post might look like this instead:

Tweet with Open Graph metadata

How to Add Open Graph Social Media Cards to Your Blog

There are several ways to add the Open Graph metadata to your pages in Next.js. By adding the Open Graph metadata, your pages will provide social media cards when they are shared.

1. Static Data

You can always provide the openGraph object with the rest of your metadata by simply typing it all out by hand for each page.

This is what I did for my homepage in the root layout.tsx file:

openGraph: {
    title: "Dave Gray",
    description: "Hello, I'm Dave. 👋 I teach coding and web development skills.",
    url: 'https://www.davegray.codes/',
    siteName: "Dave Gray's Blog",
    type: 'website',
    images: [
      {
        url: 'https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png',
        secureUrl: 'https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png',
        width: 1200,
        height: 630,
        alt: 'Preview image for Dave Gray',
      }
    ]
  },
Enter fullscreen mode Exit fullscreen mode

I should share a few things about the above code with you:

  • It is only the openGraph part of my larger metadata object.
  • I'm hosting the image for my homepage in my GitHub repository with my MDX files, but you could host yours anywhere you want.
  • The typical image size for Open Graph images is 1200x630, but you can look at the specific image sizes for several platforms. I've tried out 1200x630 on Twitter, Facebook, and LinkedIn with success.
  • You can read the Open Graph specifications for valid type values.

And the output metadata inside the <head> of my homepage for the openGraph object looks like this:

<meta property="og:title" content="Dave Gray">
<meta property="og:description" content="Hello, I'm Dave. 👋 I teach coding and web development skills.">
<meta property="og:url" content="https://www.davegray.codes/">
<meta property="og:site_name" content="Dave Gray's Blog">
<meta property="og:image" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png">
<meta property="og:image:secure_url" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Preview image for Dave Gray">
<meta property="og:type" content="website">
Enter fullscreen mode Exit fullscreen mode

The only required properties above are og:title, og:url, og:image, and og:type. Reference the Open Graph specification to decide what other properties you want to include.

Twitter / X Metadata

In addition to the openGraph object detailed above, Twitter (now called X) has its own specification and Next.js twitter metadata object. As of this writing (November, 2023), the Twitter Developer docs are not completely up-to-date and their Twitter Card validator tool does not work. That said, I don't think they have changed much of anything about their Twitter Cards. You can read an Overview of Twitter Cards and still gain useful knowledge.

Below is the twitter metadata object I created in my root layout.tsx file:

twitter: {
    card: 'summary_large_image',
    site: '@yesdavidgray',
    title: "Dave Gray",
    description: "Hello, I'm Dave. 👋 I teach coding and web development skills.",
    creator: '@yesdavidgray',
    images: {
      url: 'https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png',
      alt: 'Preview image for Dave Gray',
    }
  },
Enter fullscreen mode Exit fullscreen mode

A few notes about the above code:

  • It is only the twitter part of my larger metadata object.
  • The title and description properties are identical to the openGraph properties.
  • The images object does not support width and height.
  • I chose to use the summary_large_image Twitter Card.
  • The Next.js example currently (November, 2023) shows siteId and creatorId properties. They are not required or provided in the Twitter Card examples.
  • Both the site and creator properties should have your Twitter handle as the value.
  • Max characters: title: 70, description: 200, images.alt: 420.
  • Images must be less than 5mb in size.
  • Noteworthy: Daily.dev uses the creator property to give you credit for your article if it is featured on their site.

And the output metadata inside the <head> of my homepage for the twitter object looks like this:

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@yesdavidgray">
<meta name="twitter:creator" content="@yesdavidgray">
<meta name="twitter:title" content="Dave Gray">
<meta name="twitter:description" content="Hello, I'm Dave. 👋 I teach coding and web development skills.">
<meta name="twitter:image" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/og-card.png">
<meta name="twitter:image:alt" content="Preview image for Dave Gray">
Enter fullscreen mode Exit fullscreen mode

To examine how Twitter, LinkedIn, and Facebook use the metadata above, you can share my homepage and see the social media cards those platforms create when you post my webpage link.

2. Dynamic Data

The static approach isn't too efficient for blog article pages. They should provide page specific data, and just like your dynamically generated Next.js blog pages, you can create this metadata dynamically.

I previously discussed generating metadata for dynamic pages in a blog post about ordering and merging metadata in Next.js. The examples I show you below will be part of a larger metadata object that is returned by the generateMetadata function.

Since we have now discussed both the openGraph and twitter metadata objects that Next.js uses, I'm going to provide you with one larger example that includes both:

openGraph: {
    title: meta.title,
    description: meta.description,
    url: `/posts/${meta.id}`,
    type: 'article',
    siteName: "Dave Gray's Blog",
    publishedTime: new Date(meta.date).toISOString(),
    modifiedTime: new Date(meta.modified).toISOString(),
    authors: ['Dave Gray'],
    images: [
        {
            url: `https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/${meta.id}.png`,
            secureUrl: `https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/${meta.id}.png`,
            width: 1200,
            height: 630,
            alt: `Preview image for ${meta.title}`,
        }
    ],
},
twitter: {
    card: 'summary_large_image',
    site: '@yesdavidgray',
    title: meta.title, 
    description: meta.description, 
    creator: '@yesdavidgray',
    images: { 
        url: `https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/${meta.id}.png`,
        alt: `Preview image for ${meta.title}`, 
    },
},
Enter fullscreen mode Exit fullscreen mode

Here's a few notes about the above code:

  • meta is the object I have dynamically requested that contains front matter about my specific blog post.
  • The Open Graph type value article has the associated fields publishedTime, modifiedTime, and authors. Research the Open Graph type values.
  • I am hosting my blog post images in the same GitHub repository as my MDX blog post files. I give each image the same filename (except the file extension) as the blog post MDX file. This becomes the meta.id as I fetch blog data. Some call this the slug.
  • If you don't want to provide a different image for each blog post, you don't have to. Flavio has a very successful blog, and he uses the same image as his homepage in the Open Graph and Twitter metadata for every article he posts.

Here's the output metadata inside the <head> of one of my blog posts from both objects above:

<meta property="og:title" content="Next.js: Ordering and Merging Metadata">
<meta property="og:description" content="Discovering how much Next.js Metadata I need to provide for individual pages of my blog.">
<meta property="og:url" content="https://www.davegray.codes/posts/nextjs-ordering-merging-metadata">
<meta property="og:site_name" content="Dave Gray's Blog">
<meta property="og:image" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/nextjs-ordering-merging-metadata.png">
<meta property="og:image:secure_url" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/nextjs-ordering-merging-metadata.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Preview image for Next.js: Ordering and Merging Metadata">
<meta content="article" property="og:type">
<meta content="2023-11-12T00:00:00.000Z" property="article:published_time">
<meta content="2023-11-12T00:00:00.000Z" property="article:modified_time">
<meta content="Dave Gray" property="article:author">

<!-- Begin Twitter Metadata -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@yesdavidgray">
<meta name="twitter:creator" content="@yesdavidgray">
<meta name="twitter:title" content="Next.js: Ordering and Merging Metadata">
<meta name="twitter:description" content="Discovering how much Next.js Metadata I need to provide for individual pages of my blog.">
<meta name="twitter:image" content="https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/nextjs-ordering-merging-metadata.png">
<meta name="twitter:image:alt" content="Preview image for Next.js: Ordering and Merging Metadata">
Enter fullscreen mode Exit fullscreen mode

Note that none of the meta tags above are guaranteed to be next to each other inside the <head> element, but they are in there.

opengraph-image & twitter-image

Much like a favicon, Next.js gives you the option of simply providing some specifically named files - opengraph-image and twitter-image with supported image file extensions. I did not do this because I wanted different images for each blog post. This approach lets you assign one opengraph-image and one twitter-image file to any route segment. You can read more about using image files.

If you do choose this approach, be sure to create the necessary opengraph-image.alt.txt and twitter-image.alt.txt files.

Dynamically Generate Images

An interesting feature of Next.js is the ability to generate dynamic Open Graph and Twitter images.

You can style the created images with CSS just like you would the rest of your app. This approach uses the edge runtime to speed things up, too.

Why didn't I choose to use this feature?

In the end, it seems like a quick way to generate generic images with a color background and text overlay. You could spend more time with it to pull in unique cover images, too, but I already easily pull in images from my GitHub repo. Most social media sites will already pull in your article title text from your Open Graph metadata and compile a card with it and your Open Graph image.

I may spend some more time with Next.js image generation in the future. The ImageResponse API looks fun, and I think I could use it to generate a dynamic social card for my homepage.

If the image generation approach has peaked your curiosity, don't wait for me - go for it!

In the meantime, you can share any of my blog posts to see how the different social media platforms create social media cards from my Open Graph and Twitter metadata.


Let's Connect!

Hi, I'm Dave. I work as a full-time developer, instructor and creator.

If you enjoyed this article, you might enjoy my other content, too.

My Stuff: Courses, Cheat Sheets, Roadmaps

My Blog: davegray.codes

YouTube: @davegrayteachescode

X: @yesdavidgray

GitHub: gitdagray

LinkedIn: /in/davidagray

Buy Me A Coffee: You will have my sincere gratitude

Thank you for joining me on this journey.

Dave

Top comments (0)