For static site generation with Next.js
, we will build openGraph
image generator.
Building a project for automatic image generation#
First of all, let's create a project for automatic image generation.
Of course, you don't have to build new one if you have one.
I will use Next.js
here as well.
Setup#
1npx create-next-app og-image
We will use chakra-ui
for styling our project. This is a great library that will make your life easier.
See the official documentation to install chakra-ui
to your Next.js
project.
Creating a page#
1/* pages/index.js */23import { chakra, Heading, HStack } from '@chakra-ui/react';4import { useRouter } from 'next/router';5import Image from 'next/image';67export default function Home() {8 const router = useRouter()9 const searchParams = new URLSearchParams(router.asPath.split(/\?/)[1]);10 const title = searchParams.get('title');1112 return (13 <>14 <chakra.div15 position="relative"16 display="flex"17 flexDirection="column"18 width={1200}19 height={630}20 p={16}21 justifyContent="space-between"22 alignItems="center"23 borderWidth="2rem"24 borderColor="gray.600"25 >26 <div/>27 <Heading px="4rem" textAlign="center" fontSize="5rem">28 {title}29 </Heading>30 <HStack spacing="1rem">31 <chakra.div32 position="relative"33 width="8rem"34 height="8rem"35 borderRadius="50%"36 overflow="hidden"37 >38 <Image src="/profile.png" layout="fill" objectFit="contain" />39 </chakra.div>40 <Heading fontSize="2rem">so99ynoodles</Heading>41 </HStack>42 </chakra.div>43 </>44 );45}
We will create a UI by sending title
query-string to the URL, like https://example.com/?title=TITLE
.
We will set the image size as 1200 x 630
, you can adjust the value to optimize your image for your usage.
If you access to the address localhost:3000/?title=Creating openGraph images automatically for Next.js
, you can get above image.
Deploy your new project somewhere like Vercel
.
Changing fonts#
Feel free to change font-family for your design adjustment.
1/* pages/index.js */23import GoogleFonts from 'next-google-fonts';45export default function Home() {6 ...7 <GoogleFonts href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;500;700;900&display=swap" />8 ...9 <Heading fontFamily="Noto Sans" px="4rem" textAlign="center" fontSize="5rem">10 {title}11 </Heading>12 ...13}
Accessing to the project and get openGraph
image on production build#
Let's write a function to generate openGraph
image.
Writing a function#
1/* utils/openGraphImage.js */23import fs from 'fs';4import { createHash } from 'crypto';5import { chromium } from 'playwright';67export async function getOpenGraphImage(path) {89 /* We will only run this function on production build */10 if (process.env.NODE_ENV === 'development') {11 return;12 }1314 /* Change this to your project url */15 const baseUrl = 'https://example.og.com'16 const url = `${baseUrl}${path}`;17 const hash = createHash('md5').update(url).digest('hex');1819 const ogImageDir = `./public/images/og`;20 const imagePath = `${ogImageDir}/${hash}.png`;21 const publicPath = `${process.env.SITE_URL}/images/og/${hash}.png`;2223 try {24 fs.statSync(imagePath);25 return publicPath;26 } catch (e) {27 console.log(`generating og image for ${path}`);28 }2930 const browser = await chromium.launch({ headless: true });31 const page = await browser.newPage();32 await page.setViewportSize({ width: 1200, height: 630 });33 await page.goto(url, { waitUntil: 'networkidle' });34 const buffer = await page.screenshot({ type: 'png' });35 await browser.close();3637 fs.mkdirSync(ogImageDir, { recursive: true });38 fs.writeFileSync(imagePath, buffer);3940 return publicPath;41}
Here's what getOpenGraphImage
function does.
- Using
playwright
package, openChrominium
browser and access to the page - Save the screenshot of the page to
/public/images/og
folder - Return production url for the saved image
Use getStaticProps
to generate image#
Using getOpenGraphImage
at getStaticProps
will help us to generate openGraph images of the blog post automatically.
1/* pages/blog/[post].js */23export const getStaticProps = async ({ params }) => {4 const { post } = params;5 const { frontmatter, source } = await getPost(post);6 const openGraphImage = await getOpenGraphImage(`/?title=${frontmatter.title}`);7 return {8 props: {9 frontmatter,10 source,11 openGraphImage,12 }13 };14};
Adapting SEO to your static site Next.js
project#
Last but not least, we need to pass openGraph
image to the SEO.
next-seo
package will help us to do that.
Setting SEO to your project#
1npm install next-seo
1/* pages/blog/[post].js */2import Head from 'next/head';3import { NextSeo } from 'next-seo';45export default function BlogPost({ frontmatter, source, openGraphImage }) {6 const { title, description, slug } = frontmatter;7 return (8 <Layout>9 <Head>10 <NextSeo11 title={title}12 description={description}13 openGraph={{14 title,15 description,16 url: `${process.env.SITE_URL}/${slug}`,17 images: [{18 url: openGraphImage19 }]20 }}21 />22 </Head>23 {source}24 </Layout>25 )26}
Well done! Redeploy your static site and see what happens.