gatsby-mdx-routes
gatsby-mdx-routes is a plugin that exposes links to .mdx
files sourced from src/pages
.
This plugin aims to separate the data from the ui, which means the styling of your navigation is up to you.
👁️ Preview
🚀 Getting started
Install
npm install @pauliescanlon/gatsby-mdx-routes
Setup
To source .mdx
files from src/pages
you'll need gatsby-source-filesystem
and gatsby-plugin-mdx
installed.
Your gatsby-config
should look something like this...
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages/`,
},
},
{
resolve: `gatsby-plugin-mdx`,
options: {
defaultLayouts: {
default: `${__dirname}/src/layouts/layout.js`,
},
},
},
],
}
If that's all setup you'll now need to add @pauliescanlon/gatsby-mdx-routes
as a plugin of gatsby-plugin-mdx
module.exports = {
{
resolve: `gatsby-plugin-mdx`,
options: {
defaultLayouts: {
default: `${__dirname}/src/layouts/layout.js`,
},
plugins: [`@pauliescanlon/gatsby-mdx-routes`],
},
},
}
Using the defaultLayouts
from gatsby-plugin-mdx
allows you to create one file that will be repeated across pages.
This is where we'll add MdxRoutes
.
MdxRoutes
MdxRoutes returns two arrays, routes which is a flat array and menus which is created recursively and contains a menu
array.
You will probably use one or the other, not both.
routes
The routes
array returns two object keys, one is the actual route to the file in question (slug
), the other is the navigationLabel
from frontmatter
Key | Description |
---|---|
slug | Route to .mdx file |
navigationLabel | navigationLabel extracted from frontmatter |
src/pages/a-page.mdx
frontmatter
---
navigationLabel: Page Title
---
src/layouts/layout.js
import React, { Fragment } from "react"
import { Link } from "gatsby"
import { MdxRoutes } from "@pauliescanlon/gatsby-mdx-routes"
export default ({ children }) => (
<Fragment>
<nav>
<MdxRoutes>
{(routes, _) => (
<ul>
{routes.map((route, index) => (
<li key={index}>
<Link to={route.slug}>{route.navigationLabel}</Link>
</li>
))}
</ul>
)}
</MdxRoutes>
</nav>
<main>{children}</main>
</Fragment>
)
menus
The menus
array also returns the two object keys mentioned above, it also returns the following
Key | Description |
---|---|
slug | Route to .mdx file |
navigationLabel | navigationLabel extracted from frontmatter |
id | key to use in recursive function |
parent | string to determine parent |
menu | array of routes grouped by parent |
paths | internal array to use in recursive function |
The menus array is constructed by looking at the file paths on disk and determining what depth a file lives. This is calculated by the amount of forward slashes in the slug
To create the menus array MdxRoutes
will mirror the directory structure in your project
your project
|-- src
|-- pages
|-- other-pages
|-- some-other-page.mdx
|-- sub-pages
|-- sub-page-items
|-- sub-page-items-again
|-- sub-page-item-again-1.mdx
|-- sub-page-item-1.mdx
|-- sub-page-1.mdx
|-- about.mdx
|-- contact.mdx
|-- index.mdx
To use the menus array you'll also need a recursive Tree function to create your navigation list.
Watch out for the conditional slug
, we need this to determine if the object key is a parent or an actual route to a file.
src/layouts/layout.js
import React, { Fragment } from "react"
import { Link } from "gatsby"
import { MdxRoutes } from "@pauliescanlon/gatsby-mdx-routes"
const Tree = ({ menus }) => {
const createTree = menus => {
return (
<ul>
{menus.map(route => (
<li key={route.navigationLabel}>
{route.slug ? (
<Link to={route.slug}>
{route.navigationLabel}
{route.menu && createTree(route.menu)}
</Link>
) : (
<span>
{route.navigationLabel}
{route.menu && createTree(route.menu)}
</span>
)}
</li>
))}
</ul>
)
}
return createTree(menus, null)
}
export default ({ children }) => (
<Fragment>
<nav>
<MdxRoutes>{(_, menus) => <Tree menus={menus} />}</MdxRoutes>
</nav>
<main>{children}</main>
</Fragment>
)
props
Prop | Type | Required | Description |
---|---|---|---|
navigationOrder | Array[string] | no | A reference array to order by |
navigationOrder
By passing in an array of strings MdxRoutes
can use this to sort the returned routes or menus array, otherwise everything is just returned alphabetically in an ascending order based on the slug, with the index ("/") being first in the list.
<MdxRoutes navigationOrder={["Contact", "About", "Home", "Sub Page"]}>
{(routes, menus) => (
<ul>
{routes.map((route, index) => (
<li key={index}>
<Link to={route.slug}>{route.navigationLabel}</Link>
</li>
))}
</ul>
)}
</MdxRoutes>
If you're using gatsby-mdx-routes in your project i'd love to hear from you @pauliescanlon