Search code examples
htmlreactjsgatsby

Gatsby mdx pages not rendering fully when placed in subfolder of src/pages


I have been converting a WordPress site to Gatsby, and everything works nicely with gatsby develop, however after building with gatsby build some pages seem to render with only the page body and no wrapper layout or styling. I am using markdown pages with mdx, and I have all my markdown files under subfolders of the src/pages directory, like this:

src/pages/
  --project/
    --contact.md
    --outputs.md
    --project.md
    --sources.md
  --software/
    --apps.md
    --frontend.md
    --system.md

The above structure is more for organizational reasons than anything else (there are many more mdx files in reality). It does also correspond to the overall path structure of the site, however. In my built site, when I go to http://localhost:9000/contact the page renders perfectly, but when I visit http://localhost:9000/project or any other pages relating to that folder I only see the page body (the text content), with no layout component wrapper or styling. Everything under the software folder renders fine.

Each markdown file has a slug defined in the usual way in the frontmatter. The slug defined in src/project/project.md is just '/project'. The slug for src/project/contact.md is '/project/contact'.

Clearly the presence of src/pages/project/project.md is causing problems, but I can't figure out exactly why. I tried renaming that to src/pages/project/index.md, but that did nothing. Interestingly, when I look at public/project I see an index.html at the top level, with subfolders for each subpage, each containing its index.html. For public/software there is no index.html at the top level.

My gatsby-config.js (relevant parts):

   {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`,
        path: `${__dirname}/src/pages`,
      },
    },
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        extensions: [`.md`, `.mdx`, `.markdown`],
        gatsbyRemarkPlugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 1024,
            },
          },
        ],
      },
    },

My template (under templates/page.js - I use some MUI components):

export default function SitePageTemplate({ data: { mdx } }) {

  const { frontmatter, body } = mdx;
  const { title } = frontmatter;

  return (
    <Layout>
      <Seo title={title} />
      <Container fixed>
        <Stack direction="row" justifyContent="space-between">
          <SideBar/>
          <div style={ { padding: "0 0 0 3.5%", width: "75%" } }>
            <MDXRenderer>{body}</MDXRenderer>
          </div>
        </Stack>
      </Container>
    </Layout>
  );
}

export const pageQuery = graphql`
  query ($id: String!) {
    mdx(id: { eq: $id }) {
      body
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        slug
        title
      }
    }
  }`

My gatsby-node.js:

const path = require("path");

exports.createPages = async ({ graphql, actions, reporter }) => {

  const { createPage } = actions

  createPage({
    path: "/using-dsg",
    component: require.resolve("./src/templates/using-dsg.js"),
    context: {},
    defer: true,
  })

  const result = await graphql(`
    query MARKDOWN {
      allMdx {
        edges {
          node {
            id
            frontmatter {
              date(formatString: "MMMM DD, YYYY")
              slug
              title
            }
          }
        }
      }
    }
  `);

  if (result.errors) {
    reporter.panicOnBuild("🚨  ERROR: Loading \"createPages\" query");
  }

  const md = result.data.allMdx.edges;

  md.forEach(({ node }, index) => {
    createPage({
      // This component will wrap our MDX content
      component: path.resolve("./src/templates/page.js"),
      // Pass any value you want to access inside the template. They'll be available via `props`.
      context: {
        id: node.id
      },
      // Slug defined with frontmatter in each MDX file.
      path: node.frontmatter.slug
    });
  });

}

If I place all the markdown files flat under the src/pages directory the problem goes away. But I would like to retain the above folder layout so that the markdown is organized properly. How can I do this whilst at the same time avoiding this problem?


Solution

  • OK, returning to this issue after a few months, I think I finally solved it. A warning I was also getting turned out to be the real clue - initially I had thought it unrelated to this issue. At develop and at build time I was getting a warning in the following format:

    warn Non-deterministic routing danger: Attempting to create page: "/project/contact/", but page
    "/project/contact" already exists
    

    Others have reported this warning, but none of the reasons or propsed fixes seemed to relate to my problem. Looking at my gatsby-config.js, however, I noticed that I had at some time included the gatsby-plugin-page-creator plugin. I suspected that somehow this might be generating pages in addition to the mdx plugin. And it seemed as if this was right - removing the plugin removed both the warnings about duplicate page creation and also fixed my rendering problems. Everything looks fine now, for both development and production versions of my site.

    I can't remember why I originally included this plugin - I was originally using the mdx extension for my markdown files, and I think I needed gatsby-plugin-page-creator so that files with that extension would be correctly interpreted as markdown. I now use the standard md extension, and removing gatsby-plugin-page-creator doesn't cause any problems.