module.exports = {
siteMetadata: {
title: 'Josh W Comeau',
description:
'Friendly tutorials for developers. Focus on React, Gatsby, CSS, and animation.',
author: '@joshwcomeau',
siteUrl: 'https://www.joshwcomeau.com',
},
plugins: [
{
resolve: `gatsby-plugin-sitemap`,
options: {
exclude: ['*/admin/*', '*/confirmed'],
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage {
edges {
node {
path
context {
isCanonical
isPublished
}
}
}
}
}
`,
serialize: ({ site, allSitePage, ...delegated }) => {
return allSitePage.edges
.map(edge => {
if (edge.node.context.isCanonical === false) {
return null;
}
return {
url: site.siteMetadata.siteUrl + edge.node.path,
changefreq: `daily`,
priority: 0.7,
};
})
.filter(edge => edge);
},
},
},
],
};
exports.createPages = async function({ actions, graphql }) {
const { createPage } = actions;
const { data } = await graphql(`
query {
allMdx(
sort: { fields: [frontmatter___publishedOn], order: DESC }
limit: 1000
) {
edges {
node {
id
fields {
slug
}
frontmatter {
title
isPublished
publishedOn
type
abstract
level
categories
interactive
alwaysShowDate
}
}
}
}
}
`);
const content = data.allMdx.edges.map(edge => edge.node);
content.forEach(item => {
const { slug } = item.fields;
const { categories } = item.frontmatter;
// In this example, the first category listed is always
// the canonical one.
const firstCategory = categories[0];
categories.forEach(category => {
const pathname = getPathnameForMdxNode(category, slug);
createPage({
path: pathname,
component: path.resolve('./src/components/TemplateTutorial/TemplateTutorial.js'),
context: {
isCanonical: category === firstCategory,
},
});
});
});
};
const getPathnameForMdxNode = (category, slug) => {
return `${category}/${slug}`;
};