Published in


Nextjs + Markdown + Content layer

How to install Contentlayer in nextjs?

Build an entire static blog with markdown and contentlayer — full support of Home, tag, search, SEO, sitemap and pagination. #series 1

The content layer is a new javascript content management library. The content layer help organise your markdown file.

Benefits of the content layer

  1. Automatic type definition
  2. Built-in validations
  3. Caching and incremental regeneration
  4. Live reloading
  5. Clean code and better readability

Read more about contentlayer

All the codes are available on GitHub Repo. You can also check the final website demo with vercel.


  1. Project Setup
  2. Project Structure
  3. Posts And Images Dummy data
  4. Pages
  5. Layout
  6. Home Page
  7. Reading Page
  8. Category Page
  9. Tag Page
  10. Search Page and Functionality
  11. SEO
  12. Sitemap
  13. pagination


My project builds with javascript, and I’m not using typescript in my contentlayer.

In this article, we discuss only project setup and in the next articles we discussed one to ten step.

Project Setup

  1. Install-package
  2. Config contentlayer in nextjs
  3. Create a contentlayer.config.js file


The happiest news with the contentlayer npm package. With contentlayer, you do not need gray-matter and markednpm package. The contentlayer itself handles all markdown functionality.

npm install -D contentlayer next-contentlayer

Config contentlayer in nextjs

Edit Configuration of contentlayer inside nextjs. You change the code into two files.

  1. next.config.js or next.config.mjs
  2. tsconfig.json or jsconfig.json

next.config.js or next.config.mjs

If you use javascript in nextjs, you copy and paste the following code into your next.config.js file.

const { withContentlayer} = require('next-contentlayer')
const nextconfig = {reactStrictMode: true,disableImportAliasWarning: true,... rest configation}module.exports = withContentlayer(nextconfig)

If you use typescript in your nextjs project. then you copy and paste the following code into your next.config.mjs file.

// next.config.mjs

import { withContentlayer } from 'next-contentlayer'

export default withContentlayer(
... if your have any config write here


The code is the same for both next.config.js and next.config.mjs file.

tsconfig.json or jsconfig.json

The tsconfig.json file use for typescript and jsconfig.json file use for javascript.

If you use javascript. the paste the following code into jsconfig.json

{"compilerOptions": {"baseUrl": ".","paths": {        "contentlayer/generated": ["./.contentlayer/generated"]     } },"include": [".contentlayer/generated"]}

If you are using javascript. the paste the following code into tsconfig.json .

{"compilerOptions": {"baseUrl": ".","paths": {"contentlayer/generated": ["./.contentlayer/generated"]}},"include": [".contentlayer/generated"]}

After code, add your tsconfig.json file looks like.

{"compilerOptions": {"target": "es5","lib": ["dom", "dom.iterable", "esnext"],"allowJs": true,"skipLibCheck": true,"strict": false,"forceConsistentCasingInFileNames": true,"noEmit": true,"incremental": true,"esModuleInterop": true,"module": "esnext","moduleResolution": "node","resolveJsonModule": true,"isolatedModules": true,"jsx": "preserve","baseUrl": ".","paths": {"contentlayer/generated": ["./.contentlayer/generated"]}},"include": ["next-env.d.ts","**/*.ts","**/*.tsx",".contentlayer/generated"],"exclude": ["node_modules"]}

Create a contentlayer.config.js file

At the root level, you create contentlayer.config.js file in your project and add your markdown schema and source for your markdown posts in the project.

Configuration for markdown (Default)

filePathPattern: `**/*.md`,contentType: 'markdown',

Configuration for MDX

filePathPattern: `**/*.mdx`,contentType: 'mdx',

For this project, I’m using markdown for our blog and my contentlayer.config.js file look.

import { defineDocumentType, makeSource, defineNestedType} from "contentlayer/source-files";const Tag = defineNestedType(() => ({  name: 'Tag',  fields: {      title: { type: 'string'},   },}))const Images = defineNestedType(() => ({  name: 'Images',  fields: {     title: { type: 'string', required: true },  },}))const Categories = defineNestedType(() => ({   name: 'Categories',   fields: {      title: { type: 'string' },   },}))const Post = defineDocumentType(() => ({  name: 'Post',  filePathPattern: `**/*.md`,  contentType: 'markdown',fields: {   title: {     type: 'string',required: true,},date: {   type: 'date',   required: true,},author:{   type: 'string',   required: true,},description:{   type: 'string',   required: true,},image:{   type: 'string',   required: true,},draft:{   type: 'string',   required: true,},summary:{   type: 'string',   required: true,},tags: {   type: 'list',of: Tag,},images: {   type: 'list',of: Images,},categories:{   type: 'list',of: Categories,}},computedFields: {  slug: {    type: "string",    resolve: (doc) => doc._raw.sourceFileName.replace(/\.md/, ""),  },}}))export default makeSource({   contentDirPath: 'posts',   documentTypes: [Post],})
  1. In the contentDirPath, pass your posts directory path. In my case, all markdown posts are inside the posts folder.
  2. In the documentTypes pass your defineDocumentType configuration.


I like the contentlayer for not does have an Automatic type definition, Built-in validations and Live reloading. But I’m using the contentlayer for Clean code, better readability and understandability. with contentlayer; you achieve a blog functionality with few lines of code.

Suppose you read my previous series on markdown. You know I write code is a little bit messy. On the other hand, the contentlayer provides clean code syntax, and you can easily add other functionality to the blog.


I start the entire series on the contentlayer with markdown in nextjs. In series, we create a full-function blog with static generation.

You can follow and read more articles on and tag them on Twitter.

Read More content on the Nextjs. Sign up for a free newsletter and join the frontend web community on medium



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rajdeep singh

Rajdeep singh


JavaScript || Reactjs || Nextjs || Python || Rust || Biotechnology || Bioinformatic || Front-end Developer || Writer ||