Reputation: 1313
I have spent the better part of three days trying to get a Open Graph image generator working for my Next.js blog. After getting frustrated with hitting the 50mb function size limit I changed away from an API to a function call in the getStaticProps
method of my pages/blog/[slug].tsx
. This is working but now the issue is with the meta tags. I am dynamically setting them using the image path from the image generation function as well as information from the respective post. When I view the page source, I see all the appropriate tags and the open graph image has been generated and the path works but none of these tags are seen by crawlers. Upon checking the source file I realized that none of the head tags are pre-rendered. I am not sure if I am not understanding exactly what SSG does because I thought it would pre-render my blog pages (including the head). This seems like a common use case, and although I found some relevant questions on SO, I haven't found anyone really answering it. Is this an SSG limitation? I have seen tutorials for dynamic meta tags and they use SSR but that doesn't seem like it should be necessary.
// pages/blog/[slug].tsx
...
import Layout from '@/components/Layout';
import getOgImage from '@/utilities/ogImage';
...
export default function Post({ slug, locale, image, post, code }: Props): JSX.Element {
const metadata = {
...
};
...
return (
<Layout {...metadata}>
...
</Layout>
);
}
export const getStaticProps: GetStaticProps = async ({ params, locale }) => {
...
const ogImage = await getOgImage(slug, locale, post.data.title);
return {
props: { slug, locale, image: ogImage, post: post.data, code },
};
};
export const getStaticPaths: GetStaticPaths = async ({ locales }) => {
...
return {
paths,
fallback: false,
};
};
// Layout.tsx
...
import Meta from '@/components/Meta';
export default function Layout({ children, ...rest }: Props): JSX.Element {
return (
<>
<Meta {...rest} />
<Wrapper>
<Header />
<Content>{children}</Content>
</Wrapper>
</>
);
}
// Meta.tsx
import Head from 'next/head';
import { useRouter } from 'next/router';
...
const Meta: React.FC<Props> = ({
locale,
title,
image,
description,
author,
published,
modified,
section,
tags,
}: Props) => {
const router = useRouter();
const url = SITE_URL + router.asPath;
const ogType = router.pathname === '/' ? 'website' : 'article';
return (
<Head>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:creator" content={TWITTER_USERNAME} />
<meta property="og:url" content={url} />
<meta property="og:type" content={ogType} />
<meta property="og:site_name" content={SITE_NAME} />
<meta property="og:locale" content={locale} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} key="ogDescription" />
<meta property="og:image" content={image} key="ogImage" />
</Head>
);
};
Upvotes: 0
Views: 1599
Reputation: 1313
Thanks for anyone who looked at my issue. I figured it out! The way I implemented my dark mode used conditional rendering on the whole app to prevent any initial flash. I have changed the way I do dark mode and everything is working now!
Upvotes: 3