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
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:
- The folder where the mdx is stored
- 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
* }
*/