Call A Single MDX File Without Making It A Page In Gatsby

February - 2021

This is a way to setup so an MDX File can be called via a RegEx without making it a page.

Note that there's probably a better way to do this, but I couldn't figure out how to pass variables to graphql


src/components/title-card.js

import React from "react"
import { MDXRenderer } from 'gatsby-plugin-mdx';
import { useStaticQuery, graphql } from "gatsby"


export default function TitleCard(props) {

    const regex_pattern = new RegExp(`title-card-${props.cardId}.mdx`);

    const data = useStaticQuery(
        graphql`query {
            allMdx(filter: {fileAbsolutePath: {regex: "/title-card-.*.mdx/"}}) {
                edges {
                    node {
                        body
                        fileAbsolutePath
                        id
                        frontmatter {
                            title
                        }
                    }
                }
            }
        }`
    )

    return (
        <React.Fragment>
            {data.allMdx.edges.map(({ node }) => (
                <React.Fragment>
                    {regex_pattern.exec(node.fileAbsolutePath) && 
                        <div key="{node.id}">
                            <h3>
                                {node.frontmatter.title}
                            </h3>
                            <MDXRenderer>{node.body}</MDXRenderer>
                        </div>
                    }
                </React.Fragment>
            ))}
        </React.Fragment>
    )
}

src/mds-pages/title-cards/title-card-1.mdx

---
title: TITLE CARD 1
---

Here's the body of the first title card.

And then make more changing the number


src/pages/index.js

import React from "react"
import TitleCard from "../components/title-card.js"


export default function Home() {
    return (
        <main>
            <TitleCard cardId="2"></TitleCard>
        </main>
    )
}

gatsby-config.js

module.exports = {
    plugins: [

        {
            resolve: `gatsby-source-filesystem`,
            options: {
                name: `mdx-pages`,
                path: `${__dirname}/src/mdx-pages`,
            },
        },

        {
            resolve: `gatsby-plugin-mdx`,
            options: {
                extensions: ['.mdx', '.md'],
                plugins: [],
                gatsbyRemarkPlugins: [],
            },
        },
    ],
}

gatsby-node.js

Note: This is all commented out since it's not required for the example. But, it's an example of using the createSchemaCustomization approach to prevent errors if you have zero files with slug frontmatter in them. That won't really be a thing with the transition, but it's nice to know about.

// exports.createSchemaCustomization = ({ actions }) => {
//   const { createTypes } = actions;
//   const typeDefs = `
//     type MdxFrontmatter implements Node @infer {
//       slug: String
//     }
//   `;
//   createTypes(typeDefs);
// };

// exports.createPages = async ({ actions, graphql, reporter }) => {
//   const { createPage } = actions
//   const blogPostV1 = require.resolve(`./src/components/blog-post-v1.js`)
//   const result = await graphql(`{
//         allMdx(filter: {frontmatter: {slug: {ne: null}}}) {
//             edges {
//                 node {
//                         frontmatter {
//                         slug
//                     }
//                 }
//             }
//         }
//     }

//   `)
//   if (result.errors) {
//     reporter.panicOnBuild(`Error while running GraphQL query.`)
//     return
//   }
    
//   result.data.allMdx.edges.forEach(({ node }) => {
//       createPage({
//           path: node.frontmatter.slug,
//           component: blogPostV1,
//           context: {
//               slug: node.frontmatter.slug,
//           },
//       })
//   })
// }