Skip to content

Read Your Mdx Files

Most dev use MDX as their storage to store content such as blog, well this site use mdx too, this snippet useful to read mdx files

Rizki Maulana Citra

Created by / Rizki Maulana Citra

Read Mdx File

To read Mdx file, first locate where the mdx files are stored by targeting its folder

JS
// in my case: src/data/blog
import * as fs from 'fs/promises'
import matter from 'gray-matter'
import * as path from 'path'

// notice I only target it's parent folder (data) in case there is another
// mdx content that I want to store aside from blog post
const folder = path.join(process.cwd(), 'src/data')

export const getContentBySlug = async (path, slug) => {
  // read path to file src/data/{path}/[{slug}].mdx
  const dir = join(`${folder}/${path}`, `${slug}.mdx`)
  // read file with promise based
  const file = await readFile(dir, 'utf8')

  // parse file content with gray matter, extract it's header and content
  const { content, data } = matter(file)

  return {
    // in case we need the file name as slug, example usage is for the url page
    header: { ...data, slug },
    content
  }
}

TypeScript Implementation

TS
type Content<T> = {
  header: T & { slug: string }
  content: string
}

export const getContentBySlug = async <T>(path: string, slug: string): Promise<Content<T>> => {
  const dir = join(`${folder}/${path}`, `${slug}.mdx`)

  const file = await readFile(dir, 'utf8')
  const { content, data } = matter(file)

  return {
    header: { ...(data as T), slug },
    content
  }
}

Usage

To read your mdx file, simply call it with giving it two argument:

  1. The folder where the mdx is stored
  2. the file name itself
JS
// notice I don't need to prefix the first parameter to be `/blog`
// or the second paramter to be `my-first-post.mdx`
const post = await getContentBySlug('blog', 'my-first-post')

Usage in TypeScript

Previously the function require one generic type, so the usage will be like so

TS
type Post = {
    title: string
    published_at: string
    author: string
}

const post = await getContentBySlug<Post>('blog', 'my-first-post')

/**
 * post will be:
 * const post = { 
 *  header: { title: string; published_at: string; author: string; slug: string }
 *  content: string
 * }
 */