2023-08-01: This is no longer the preferred way as Nextjs has implemented a full metadata solution.
Use this wrapper Container component in the HOC
(javascript)
import Head from 'next/head'
import { useRouter } from 'next/router'
import Footer from '@/components/Footer'
import Navbar from '@/components/Navbar'
function Container(props) {
const { children, ...customMeta } = props
const router = useRouter()
const meta = {
title: 'Title ...',
description: 'Summary ...',
image: 'Page image ...',
type: 'website',
...customMeta,
}
return (
<>
<Head>
<title>{meta.title}</title>
<meta name="robots" content="follow, index" />
<meta content={meta.description} name="description" />
<meta property="og:url" content={`Base url ... ${router.asPath}`} />
<link rel="canonical" href={`Base url ... ${router.asPath}`} />
<meta property="og:type" content={meta.type} />
<meta property="og:site_name" content="Learn NextJS" />
<meta property="og:description" content={meta.description} />
<meta property="og:title" content={meta.title} />
<meta property="og:image" content={meta.image} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@learnnextjs" />
<meta name="twitter:title" content={meta.title} />
<meta name="twitter.description" content={meta.description} />
<meta name="twitter:image" content={meta.image} />
{meta.data && (
<meta property="article:published_time" content={meta.date} />
)}
</Head>
<Navbar />
<main>{children}</main>
<Footer />
</>
)
}
export default Container
Usage in a Dynamic route
(javascript)
import { useMemo } from 'react'
import BlogLayout from '@/layouts/Blog'
import { getMDXComponent } from 'mdx-bundler/client'
import { getFileBySlug, getFiles } from '@/lib/mdx'
import MDXComponent from '@/components/MDXComponents'
export default function BlogSlug({ code, frontMatter }) {
const Component = useMemo(() => getMDXComponent(code), [code])
return (
<BlogLayout matter={frontMatter}>
<Component components={{ ...MDXComponent }} />
</BlogLayout>
)
}
export async function getStaticPaths() {
const posts = await getFiles('posts')
return {
paths: posts.map((p) => ({
params: { slug: p.replace(/\.mdx/, '') },
})),
fallback: false,
}
}
export async function getStaticProps({ params }) {
const post = await getFileBySlug(params.slug, 'posts')
return { props: { ...post } }
}