Skip to content
Advertisement

Read the values from `frontmatter` from `.mdx` files using a `.js` file

I want to use https://github.com/iamvishnusankar/next-sitemap to generate Sitemap.

However, when I use it normally like:

next-sitemap.js

module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
}

It generates sitemap for all my posts.

Although, in my .mdx files, I have a published key to know whether the post is a draft or it is ready to be published like:

export const meta = {
    title: 'Hello World',
    date: '2020-09-11T14:54:37.229Z',
    tags: ['hello', 'world'],
    author: 'Akshay Kadam',
    published: false,
}

# Hello World

This is my first blog post, not yet ready to be published

How do I read the published key from .mdx file so I can generate sitemap of only published: true posts?

Note: I can’t use https://www.npmjs.com/package/gray-matter because my .mdx files have an exported object as metadata.

Advertisement

Answer

I used a custom sitemap generator like:

scripts/build-sitemap.js

const fs = require('fs')
const glob = require('fast-glob')
const prettier = require('prettier')
const { getAllPublishedEssays } = require('@/utils/essay/getAllEssayPreviews')
const { getAllPublishedTutorials } = require('@/utils/tutorial/getAllTutorialPreviews')

const posts = [...getAllPublishedEssays(), ...getAllPublishedTutorials()]

const config = {
    siteUrl: 'https://akshaykadam.com',
    changefreq: 'daily',
    priority: '0.7',
    lastmod: new Date().toISOString(),
}

const robotsTxt = `
User-agent: *
Allow: /
Host: ${config.siteUrl}
Sitemap: ${config.siteUrl}/sitemap.xml
`.trim()

const main = async () => {
    const prettierConfig = await prettier.resolveConfig('./prettier.config.js')

    const sitemap = `
        <?xml version="1.0" encoding="UTF-8"?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
            ${posts
                            .map((post) => {
                                return `
                        <url>
                                                        <loc>${`${config.siteUrl}/${post.slug}`}</loc>
                                                        <changefreq>${`${config.changefreq}`}</changefreq>
                                                        <priority>${`${config.priority}`}</priority>
                                                        <lastmod>${`${config.lastmod}`}</lastmod>
                        </url>
                    `
                            })
                            .join('')}
        </urlset>
    `

    const formatted = prettier.format(sitemap, {
        ...prettierConfig,
        parser: 'html',
    })

    fs.writeFileSync('public/sitemap.xml', formatted)
    fs.writeFileSync('public/robots.txt', robotsTxt)
}

main()

getAllEssayPreviews.ts

export const getAllPublishedEssays = (): Array<{
    slug: string
    module: any
}> =>
    importAll(require.context('../../pages/essay/?rss', true, /.mdx$/))
        .filter((p: Post) => p.module.meta.published)
        .sort((a: Post, b: Post) => dateSortDesc(a.module.meta.date, b.module.meta.date))

next.config.js

const withBundleAnalyzer = require('@next/bundle-analyzer')({
    enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer({
    .
    .
    .
    webpack: (config, options) => {
        .
        .
        .
        if (!options.dev && options.isServer) {
            const originalEntry = config.entry

            config.entry = async () => {
                const entries = { ...(await originalEntry()) }
                entries['./scripts/build-rss'] = './scripts/build-rss.js'
                entries['./scripts/build-sitemap'] = './scripts/build-sitemap.js'
                return entries
            }
        }

        return config
    },
})
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement