I followed some article to setup generating pages for MDX content. That tutorial used the path
value defined in frontmatter to build the page. Which is bothersome because now i gotta specify a path
in frontmatter every time. Otherwsie the build will fail. I’m coming from Jekyll and Hugo, and the path was always optional.
I’d much rather it take the filename as the basis for the URL, which i have now managed to do, by following yet another article.
Here’s the code for both.
The first one is generating pages based on the path
value and then i’m using this on the index pages and applying a filter to get posts from different folders
1const path = require('path')
2
3exports.createPages = async ({ graphql, actions, reporter }) => {
4 const { createPage } = actions
5 const result = await graphql(`
6 query {
7 allMdx {
8 edges {
9 node {
10 id
11 frontmatter {
12 path
13 }
14 }
15 }
16 }
17 }
18 `)
19
20 if (result.errors) {
21 reporter.panicOnBuild('🚨 ERROR: Loading "createPages" query', result.errors)
22 }
23 // Create blog post pages.
24 const posts = result.data.allMdx.edges
25 // you'll call `createPage` for each result
26 posts.forEach(({ page }, index) => {
27 createPage({
28 path: page.frontmatter.path,
29 component: path.resolve(`./src/components/Layout/Post.jsx`),
30 context: {
31 id: page.id,
32 },
33 })
34 })
35}
And this one is generating pages based on filename and taking them from the notes
directory. I don’t have to add any path
values to the frontmatter
1const { createFilePath } = require('gatsby-source-filesystem')
2const path = require('path')
3
4// Add a field called 'slug', which is basically filename + directory
5exports.onCreateNode = ({ node, getNode, actions }) => {
6 const { createNodeField } = actions
7
8 if (node.internal.type === 'Mdx') {
9 const slug = createFilePath({
10 node,
11 getNode,
12 basePath: `notes`,
13 trailingSlash: false,
14 })
15
16 createNodeField({
17 name: 'slug',
18 node,
19 value: `${slug}`,
20 })
21 }
22}
23
24// Use that slug field to create pages
25exports.createPages = async ({ graphql, actions, reporter }) => {
26 const { createPage } = actions
27
28 const result = await graphql(`
29 query {
30 allMdx {
31 edges {
32 node {
33 id
34 fields {
35 slug
36 }
37 }
38 }
39 }
40 }
41 `)
42 if (result.errors) {
43 reporter.panicOnBuild('🚨 ERROR: Loading "createPages" query', result.errors)
44 }
45
46 const posts = result.data.allMdx.edges
47 posts.forEach(({ node }, index) => {
48 createPage({
49 path: node.fields.slug,
50 component: path.resolve(`./src/components/Layout/Post.jsx`),
51 context: { id: node.id },
52 })
53 })
54}
Now i want it to use path
(if defined) for custom URL slug and use filename as a default fallback. But that bit i’ll get to at some other time..