We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
in this article, I will show you how to generate a table of contents in Next.js with contentplayer.
contentplayer is a static site generator for Next.js. It is a great tool to build a blog or documentation site. It is easy to use and has a lot of features.
when using contentplayer, we must create a contentlayer.config.ts
file in the root directory. In this file, we can define the content type and the fields of the content type. For example, we can define a Post
content type with the following code:
const Post = defineDocumentType(() => ({
name: "Post",
filePathPattern: `**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
description: "The title of the post",
required: true
},
date: {
type: "date",
description: "The date of the post",
required: true
}
},
computedFields: {
url: {
type: "string",
resolve: (doc) => `/posts/${doc._raw.flattenedPath}`
}
}
}));
In the above code, we define a Post
content type with two fields: title
and date
. We also define a computed field url
to generate the url of the post. for Toc, we can define a computed field toc
to extract the toc from the markdown file.
const Post = defineDocumentType(() => ({
... other fields
computedFields: {
url: {
type: "string",
resolve: (doc) => `/posts/${doc._raw.flattenedPath}`
},
toc: {
type: "list",
resolve: (doc) => {
return doc.body.raw.match(/\n## .*\n\n/g)?.map((heading) => {
const title = heading.replace("## ", "").replace(/\n+/, "");
const id = title.toLowerCase().replace(/ +|\./g, "-");
return { title, id };
});
}
}
}
}));
In the above code, we define a computed field toc
to extract the toc from the markdown file. We use the match
method to extract the headings from the markdown file(contents like ## h2 heading
). Then we use the map
method to convert the headings to an array of objects with title
and id
properties.
in the post page, we can use the toc
field to render the toc. For example, we can use the toc
field to render the toc in the post page.
<ul className="my-4 flex flex-col text-primary">
{post.toc &&
post.toc.map(({ title, id }: { title: string; id: string }) => (
<li key={id}>
<Link href={`#${id}`}>#{title}</Link>
</li>
))}
</ul>
in order to make the toc work, we need to add an anchor to each heading. to achieve this, we need modify mdx-component.tsx
file.
const h2 = ({ children }: any): ReactElement => {
const idText = children.replace(/\s+|\./g, "-").toLowerCase();
return <h2 id={idText}>{children}</h2>;
};
const components = {
h2,
Image
};
export function Mdx({ code }: MdxProps) {
const Component = useMDXComponent(code);
return <Component components={components} />;
}
In the above code, we define a h2
component to add an anchor to each heading. We use the replace
method to replace the spaces and dots with -
. Then we use the toLowerCase
method to convert the heading to lowercase. Finally, we use the id
attribute to add an anchor to the heading.
in this article, I show you how to generate a table of contents in Next.js with contentplayer. I hope this article is helpful to you.