1

I have recently updated Gatsby from V3 to V4(latest one) and also updated the plugins below.

"@mdx-js/mdx": "^2.1.3",
"@mdx-js/react": "^2.1.3",
"gatsby-plugin-mdx": "^4.1.0",
"gatsby": "^4.21.1",

The code in node-config.js -

{
   resolve: `gatsby-plugin-mdx`,
   options: {
     defaultLayouts: { default: require.resolve(`./src/components/layout`), },
   },
},
{
  resolve: `gatsby-source-filesystem`,
  options: {
    name: `pages`,
    path: `${__dirname}/src/pages/`,
  },
},

In /src/pages/index.mdx

---
title: Title
description: Description
class: home
imageTwitter: /twitter-home.jpg
imageOg: "/og-home.jpg"
imageAlt: Image for the Title.
---

import { StaticImage } from "gatsby-plugin-image"
import { Container, Row, Col, Card } from "react-bootstrap"
import { Link } from "gatsby"
import { navigate } from "gatsby"

<div class="w-60 text-center home-intro">
content
</div>

Latest version of gatsby-plugin-mdx doesn't have defaultLayout so when I hit http://localhost:8000/ the page loads without header and footer because the layout doesn't work.

In /src/components/layout.js

import React from "react"
import PropTypes from "prop-types"
import { StaticQuery, graphql } from "gatsby"
import { Container, Row, Col } from "react-bootstrap"
import "../styles.scss"
import Footer from "./footer"
import Menu from "./menu"
import Helmet from "react-helmet"

const Layout = ({ location, children, pageContext, ...props }) => (
  <StaticQuery
    query={graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
            siteUrl
          }
        }
        allMdx {
          edges {
            node {
              frontmatter {
                title
                description
                class
                imageOg
                imageTwitter
              }
            }
          }
        }
      }
    `}
    render={data => (
      <>
        <Helmet>
          <body className={pageContext.frontmatter.class} />
        </Helmet>
        <Container>
          <Row>
            <Col>
              <Menu />
            </Col>
          </Row>
        </Container>
        <Container className="full-width">
          <Row className="mx-0">
            <Col>
              <main>
                <article id="content">
                  {children}
                </article>
              </main>
            </Col>
          </Row>
        </Container>
        <Footer />
      </>
    )}
  />
)

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

Is there any way I can create a default template inside the page's directory and then reference each MDX file as a child? For example, if it's index page then it will select home.mdx

Any help is highly appreciated.

Prithviraj Mitra
  • 11,002
  • 13
  • 58
  • 99

1 Answers1

0

According to the migration guide, you have several options to use a common layout across dynamic page creation:

  1. Use the wrapPageElement API including its SSR counterpart.
  2. Add an export default Layout statement to your MDX file, see MDX documentation on Layout.
  3. When using the createPage action to programatically create pages, you should use the following URI pattern for your page component: your-layout-component.js?__contentFilePath=absolute-path-to-your-mdx-file.mdx. To learn more about this, head to the programmatically creating pages guide.

Given your scenario, I'd say option 2 and 3 fits better since they are easy to implement and has fewer changes to conflict to whatever you had already but. Chose wisely, whatever fits your specs (if you are or ain't using gatsby-node.js, using global wrappers as Redux, etc.).

Option 2

If you define a Layout, it will be used to wrap all content. A layout can be defined from within MDX using a default export:

export default function Layout({children}) {
  return <main>{children}</main>;
}

All the things.

Or:

export {Layout as default} from './components.js'

The layout can also be passed as components.wrapper (but a local one takes precedence).

Option 3

In your gatsby-node.js, in your page generation you need to point to the layout like:

createPage({
  path: `/some-slug/`,
  component: `layout-component.js?__contentFilePath=${absolute-path-to-your-mdx-file.mdx}`,
  context: {
    id: `123456`,
  },
})

Note: this approach may force you to tweak a little bit the GraphQL query to add the needed data to build the __contentFilePath properly.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
  • Thank you and sorry for being super late. I think I'll go with option 2. I have gone through the MDX documentation on Layout but I am not understanding it completely. Is there any other reference or example on how I can use Layout. I am searching for a basic example. – Prithviraj Mitra Sep 15 '22 at 09:12
  • https://mdxjs.com/docs/using-mdx/#layout – Ferran Buireu Sep 15 '22 at 09:49
  • 1
    I didn't make this but found this codepen useful. It minimally demonstrates option 1 and 3. https://codesandbox.io/s/github/LekoArts/mdx-v2-example – Tim MB Nov 15 '22 at 20:53