contentlayer-datapad

v1.0.22
Awesome Contentlayer configuration with GFM, LQIP, TOC and more.
contentlayer config datapad reading time table of contents lqip

datapad

Awesome Contentlayer configuration with GFM, LQIP, TOC and more.

It includes the following plugins:

Installation

yarn add contentlayer-datapad

Setup

import { defineDocumentType, makeSource } from 'contentlayer/source-files';
import {
  computeFields,
  remarkPlugins,
  rehypePlugins,
} from 'contentlayer-datapad';

export const Blog = defineDocumentType(() => ({
  name: 'Blog',
  filePathPattern: `blog/**/*.mdx`,
  contentType: 'mdx',
  fields: {
    title: {
      type: 'string',
      required: true,
    },
    description: {
      type: 'string',
      required: true,
    },
    date: {
      type: 'date',
      required: true,
    },
    image: {
      type: 'string',
      required: false,
    },
  },
  computedFields: computeFields<'Blog'>({}),
}));

const source = makeSource({
  contentDirPath: './content',
  documentTypes: [Blog],
  mdx: {
    remarkPlugins: remarkPlugins(),
    rehypePlugins: rehypePlugins({}),
  },
});

export default source;

Also, update your Tailwind config to include the following:

import type { Config } from 'tailwindcss';

const config: Config = {
  content: ['./node_modules/contentlayer-datapad/**/*.js'],
  // ...
};

export default config;

Configuration

computeFields

computeFields accepts a configuration object with the following properties:

Property Type Description Default
openGraphEndpoint string The endpoint of the Open Graph image generator (i.e. @vercel/og) '/api/og'
imagesFolder string The folder where your images are stored, prepended to the document image path './public'

The computed fields are:

Field Name Type Description Example Output
slug string The slug of the document, used in the URL '/blog/my-post'
slugAsParams string The slug as a path segment 'my-post'
readingTime string The estimated time to read the document, in minutes '5 min read'
toc json The table of contents of the document [{ value: 'Heading 1', depth: 1, url: '#heading-1' }]
imageBlur string The LQIP image data of the document 'UklGRkgAAABXRUJQVlA4IDwAAADQAQCdASoQAAkABUB8JYwC7ADbW2wxAAD+5fWSusCgEGgrbEnESec12AakPGs5RtCwUs8GJTOZH7EgIAA='

remarkPlugins

remarkPlugins does not accept any configuration.

rehypePlugins

rehypePlugins accepts a configuration object with the following properties:

Property Type Description Default
shikiTheme Theme The theme to use for syntax highlighting 'one-dark-pro'

Usage

Here's how to use the custom fields in your Next.js app:

import { allBlogs } from 'contentlayer/generated';
import Image from 'next/image';
import type { Toc } from 'contentlayer-datapad';

return allBlogs.sort(sortBlogPostByDate).map((post) => (
  <div key={post.name}>
    <Image
      src={src}
      width={1920}
      height={1080}
      alt=""
      blurDataURL={`data:image/jpg;base64,${post.imageBlur}`}
      placeholder="blur"
    />

    <p>{post.readingTime}</p>

    <ul>
      {(post.toc as Toc).map((item) => (
        <li
          key={item.url}
          style={{
            paddingLeft: `${item.depth - 2}rem`,
          }}
        >
          <a href={item.url}>{item.value}</a>
        </li>
      ))}
    </ul>
  </div>
));
npm i contentlayer-datapad

Metadata

  • ISC
  • Whatever
  • Hayden Bleasel
  • released 1/19/2024

Downloads

Maintainers