Build a Personal Site with ContentLayer and ChakraUI#

  • Contentlayer converts mdx, md into json and react components
  • Contentlayer does routing - nextjs prerender
  • Contentlayer appiles styles to generated components
  • Provide styles via ChakaraUI and useMDXComponent hook
  • GitHub
Build a Personal Site with Contentlayer, NextJs and Amplify

Create NextJS App#

npx create-next-app@latest my-site --typescript

add content layer

npm install contentlayer next-contentlayer

add chakraui

npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

configure tsconfig with paths

"compilerOptions": {
"incremental": true,
"baseUrl": "."
"paths": {
"contentlayer/generated": ["./.contentlayer/generated"],
"styles/*": ["styles/*"]
"include": [
"exclude": ["node_modules"]

configure next.config.js

const { withContentlayer } = require('next-contentlayer')
module.exports = withContentlayer({})

Configure Schema#

This is the content of contentlayer.config.js and it specifies the schema of Post. Given the schema, contentlayer can convert md, mdx content into react components.

import { defineDocumentType, makeSource } from 'contentlayer/source-files'
export const Post = defineDocumentType(() => ({
name: 'Post',
filePathPattern: `**/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
description: 'The title of the post',
required: true
description: {
type: 'string'
date: {
type: 'date',
description: 'The date of the post',
required: true
computedFields: {
url: {
type: 'string',
resolve: post => `/posts/${post._raw.flattenedPath}`
export default makeSource({
contentDirPath: 'posts',
documentTypes: [Post]

Configure Routes#

import { allPosts } from './../../.contentlayer/generated'
export async function getStaticPaths() {
const paths = => post.url)
return {
fallback: false

match the request url (from user) with the nextjs url using slug.

export async function getStaticProps({ params }) {
const post = allPosts.find(post => post._raw.flattenedPath === params.slug)
return {
props: {

Apply Styles#

Provide styles for generated components via MDXComponents. For example

const mdxComponents = {
h1: props => <chakra.h1 fontSize={'5xl'} apply="mdx.h1" {...props} />,
h2: props => <chakra.h2 fontSize={'3xl'} apply="mdx.h2" {...props} />

Then apply the styles into generated components

import React from 'react'
import { allPosts } from '.contentlayer/generated'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { Box, chakra } from '@chakra-ui/react'
import styles from 'styles/Home.module.css'
const PostLayout = ({ post }) => {
const MDXContent = useMDXComponent(post.body.code)
return (
<Box bg={'gray.100'} maxW="1000px" margin={'auto'} padding="20px">
<h1 className={styles.title}>{post.title}</h1>
<MDXContent components={mdxComponents}></MDXContent>
export default PostLayout

Amplify Hosting#

amplify init

then add hosting

amplify add hosting

select manual then publish (this work for static website). For hybrid, need to choose CI/CD pipeline with GitHub source or using vercel hosting.

amplify publish