HomeBlogBuild A Blog Using Contentlayer And Mdx

Build a blog using Contentlayer

4min
0 views

Contentlayer is a library that allows you to build a static website using data sources such as Markdown, MDX, JSON, YAML, or any custom format. It transforms your data into a content layer, which is a collection of typed data objects that you can query and render in your React components. On the other hand, MDX is a superset of Markdown that enables you to use JSX syntax and import React components directly into your Markdown files.

In this blog post, we'll explore how to build a blog using ContenlLayer and MDX, combining the benefits of both technologies to create a seamless content creation and rendering experience.

Install and configure Contentlayer

Instal Dependencies

Install the ContentLayer packages inside your Next.js project by running the following command in your terminal:

bash
pnpm add contentlayer next-contentlayer
bash
pnpm add contentlayer next-contentlayer

Configure next.config.js

Update the next.config.js file at your project's root to configure it to use ContentLayer:

next.config.js
import { createContentlayerPlugin } from "next-contentlayer";
 
/** @type {import('next').NextConfig} */
const nextConfig = {};
 
const withContentlayer = createContentlayerPlugin({
  // Additional Contentlayer config options
});
 
export default withContentlayer(nextConfig);
next.config.js
import { createContentlayerPlugin } from "next-contentlayer";
 
/** @type {import('next').NextConfig} */
const nextConfig = {};
 
const withContentlayer = createContentlayerPlugin({
  // Additional Contentlayer config options
});
 
export default withContentlayer(nextConfig);

Define Document Type

Next, define a document type for your MDX content. This will specify the name, content type, file path pattern, and fields of your MDX files. Create a contentlayer.config.js file and add the following code:

contentlayer.config.js
import { defineDocumentType, makeSource } from "contentlayer/source-files";
 
export const Post = defineDocumentType(() => ({
  name: "Post",
  filePathPattern: `blog/**/*.mdx`,
  contentType: "mdx",
  fields: {
    title: {
      type: "string",
      description: "The title of the post",
      required: true,
    },
    description: {
      type: "string",
      description: "The description of the post",
      required: false,
    },
    date: {
      type: "date",
      description: "The publishing date of the post",
      required: true,
    },
    image: {
      type: "string",
    },
  },
  computedFields,
}));
 
export default makeSource({
  contentDirPath: "./content",
  documentTypes: [Post],
});
contentlayer.config.js
import { defineDocumentType, makeSource } from "contentlayer/source-files";
 
export const Post = defineDocumentType(() => ({
  name: "Post",
  filePathPattern: `blog/**/*.mdx`,
  contentType: "mdx",
  fields: {
    title: {
      type: "string",
      description: "The title of the post",
      required: true,
    },
    description: {
      type: "string",
      description: "The description of the post",
      required: false,
    },
    date: {
      type: "date",
      description: "The publishing date of the post",
      required: true,
    },
    image: {
      type: "string",
    },
  },
  computedFields,
}));
 
export default makeSource({
  contentDirPath: "./content",
  documentTypes: [Post],
});

Write your content

Create your MDX files in the content/blog folder, following the schema you defined in the previous step. For example, create a file named hello-world.mdx with the following content:

hello-world.mdx
---
title: Hello World
description: Learn how to use ContentLayer to build a blog
image: /blog/blog-post-4.jpg
date: 2022-11-18
---
 
# Hello World
 
This is my first post using ContentLayer and MDX.
 
I can write Markdown and JSX in the same file.
 
<SomeComponent />
hello-world.mdx
---
title: Hello World
description: Learn how to use ContentLayer to build a blog
image: /blog/blog-post-4.jpg
date: 2022-11-18
---
 
# Hello World
 
This is my first post using ContentLayer and MDX.
 
I can write Markdown and JSX in the same file.
 
<SomeComponent />

Create slug

To render a single post, create a file named app/blog/[...slug].ts with the following code:

app/blog/[...slug].ts
import { allPosts } from "contentlayer/generated";
 
export const generateStaticParams = async () =>
  allPosts.map((post) => ({ slug: post.url }));
 
export default function Post({ params }: { params: { slug: string } }) {
  const post = allPosts.find((post) => post.url === params.slug);
  if (!post) throw new Error(`Post not found for slug: ${params.slug}`);
 
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.date}</p>
      <div dangerouslySetInnerHTML={{ __html: post.body.html }} />
    </div>
  );
}
app/blog/[...slug].ts
import { allPosts } from "contentlayer/generated";
 
export const generateStaticParams = async () =>
  allPosts.map((post) => ({ slug: post.url }));
 
export default function Post({ params }: { params: { slug: string } }) {
  const post = allPosts.find((post) => post.url === params.slug);
  if (!post) throw new Error(`Post not found for slug: ${params.slug}`);
 
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.date}</p>
      <div dangerouslySetInnerHTML={{ __html: post.body.html }} />
    </div>
  );
}

That's it! This blog post has provided you with an overview of how to build a blog using Contentlayer and written in MDX, leveraging their features to create a seamless content creation and rendering experience.

For more advanced topics, such as syntax highlighting and theming, you can refer to next blog build time syntax highlighting - Delba.

Thank you for reading!