'How to create several pages using the same template with gatsby-node?
Individual Project Pages I'm creating a unique page for each markdown file using Template A and this is working as expected. They're each children of the following Project Type pages (e.g., www.site/motion-graphics/project-1)
Project Type Pages I'm also trying to create 4 different pages using Template B (project-type.jsx). Each will have a unique path and I will be passing a different "key" for each page. That key will be used to grab specific markdown files with a matching "key". All of these markdown files with the matching key will be displayed. These 4 pages are the Project Type pages (e.g., www.site/motion-graphics).
Essentially what is happening, is the individual project pages are being created correctly, but the 4 project type pages are not being generated at all. I double-checked in GraphQL for all generated pages, as instructed at https://www.gatsbyjs.com/docs/creating-and-modifying-pages/. What am I doing wrong in the generation of the 4 Project Type pages?
Here is my gatsby-node.js file:
const path = require('path')
exports.createPages = async ({ graphql, actions }) => {
const { data } = await graphql(`
query Projects {
mograph: allMarkdownRemark(
filter: {frontmatter: {typeKey: {eq: "mograph"}}}
) {
nodes {
frontmatter {
slug
}
}
}
photoedit: allMarkdownRemark(
filter: {frontmatter: {typeKey: {eq: "photoedit"}}}
) {
nodes {
frontmatter {
slug
}
}
}
photoman: allMarkdownRemark(
filter: {frontmatter: {typeKey: {eq: "photoman"}}}
) {
nodes {
frontmatter {
slug
}
}
}
webdev: allMarkdownRemark(
filter: {frontmatter: {typeKey: {eq: "webdev"}}}
) {
nodes {
frontmatter {
slug
}
}
}
}
`)
// Individual Project Pages
data.mograph.nodes.forEach(node => {
actions.createPage({
path: '/motion-graphics/' + node.frontmatter.slug,
component: path.resolve('./src/templates/project-details.jsx'),
context: { slug: node.frontmatter.slug }
})
})
data.photoedit.nodes.forEach(node => {
actions.createPage({
path: '/photo-editing/' + node.frontmatter.slug,
component: path.resolve('./src/templates/project-details.jsx'),
context: { slug: node.frontmatter.slug }
})
})
data.photoman.nodes.forEach(node => {
actions.createPage({
path: '/photo-manipulation/' + node.frontmatter.slug,
component: path.resolve('./src/templates/project-details.jsx'),
context: { slug: node.frontmatter.slug }
})
})
data.webdev.nodes.forEach(node => {
actions.createPage({
path: '/web-development/' + node.frontmatter.slug,
component: path.resolve('./src/templates/project-details.jsx'),
context: { slug: node.frontmatter.slug }
})
})
//Project Type Pages
createPage({
path: '/motion-graphics',
component: require.resolve('./src/templates/project-type.jsx'),
context: { typeKey: 'mograph' }
})
createPage({
path: '/photo-editing',
component: require.resolve('./src/templates/project-type.jsx'),
context: { typeKey: 'photoedit' }
})
createPage({
path: '/photo-manipulation',
component: require.resolve('./src/templates/project-type.jsx'),
context: { typeKey: 'photoman' }
})
createPage({
path: '/web-development',
component: require.resolve('./src/templates/project-type.jsx'),
context: { typeKey: 'webdev' }
})
}
And here's my template file, project-type.jsx:
import * as React from "react"
import { graphql } from "gatsby"
import { Themed } from "theme-ui"
import Layout from "@lekoarts/gatsby-theme-cara/src/components/layout"
import { UpDown, UpDownWide } from "@lekoarts/gatsby-theme-cara/src/styles/animations"
import Svg from "@lekoarts/gatsby-theme-cara/src/components/svg"
import Seo from "@lekoarts/gatsby-theme-cara/src/components/seo"
import Inner from "@lekoarts/gatsby-theme-cara/src/elements/inner"
import "../styles/projects.scss"
import Navbar from "../@lekoarts/gatsby-theme-cara/components/project-nav"
import { GatsbyImage } from "gatsby-plugin-image"
import ProjectCard from "../@lekoarts/gatsby-theme-cara/components/project-card"
import ContentNoParallax from "../elements/content-no-parallax.tsx"
const ProjectType = ({ data }) => {
const projects = data.projects.nodes
const typeKey = data.projects.nodes.frontmatter.typeKey
return (
<Layout>
<Seo title={ typeKey } />
<div>
<UpDown>
<Svg icon="triangle" hiddenMobile width={48} stroke color="icon_orange" left="10%" top="20%" />
<Svg icon="hexa" width={48} stroke color="icon_red" left="60%" top="70%" />
<Svg icon="box" width={6} color="icon_darker" left="60%" top="15%" />
</UpDown>
<UpDownWide>
<Svg icon="arrowUp" hiddenMobile width={16} color="icon_blue" left="80%" top="10%" />
<Svg icon="triangle" width={12} stroke color="icon_brightest" left="90%" top="50%" />
<Svg icon="circle" width={16} color="icon_darker" left="70%" top="90%" />
<Svg icon="triangle" width={16} stroke color="icon_darkest" left="30%" top="65%" />
<Svg icon="cross" width={16} stroke color="icon_pink" left="28%" top="15%" />
<Svg icon="circle" width={6} color="icon_darkest" left="75%" top="10%" />
<Svg icon="upDown" hiddenMobile width={8} color="icon_darkest" left="45%" top="10%" />
</UpDownWide>
<Svg icon="circle" hiddenMobile width={24} color="icon_darker" left="5%" top="70%" />
<Svg icon="circle" width={6} color="icon_darkest" left="4%" top="20%" />
<Svg icon="circle" width={12} color="icon_darkest" left="50%" top="60%" />
<Svg icon="upDown" width={8} color="icon_darkest" left="95%" top="90%" />
<Svg icon="upDown" hiddenMobile width={24} color="icon_darker" left="40%" top="80%" />
<Svg icon="triangle" width={8} stroke color="icon_darker" left="25%" top="5%" />
<Svg icon="circle" width={64} color="icon_green" left="95%" top="5%" />
<Svg icon="box" hiddenMobile width={64} color="icon_purple" left="5%" top="90%" />
<Svg icon="box" width={6} color="icon_darkest" left="10%" top="10%" />
<Svg icon="box" width={12} color="icon_darkest" left="40%" top="30%" />
<Svg icon="hexa" width={16} stroke color="icon_darker" left="10%" top="50%" />
<Svg icon="hexa" width={8} stroke color="icon_darker" left="80%" top="70%" />
<ContentNoParallax>
<Inner>
<Themed.h1>Projects</Themed.h1>
<Themed.h2>
{ typeKey }
</Themed.h2>
<Navbar></Navbar>
<Themed.div className="projects">
{projects.map(project => (
<ProjectCard className="project" link={ typeKey } key={ project.id } bg="linear-gradient(to right, #D4145A 0%, #FBB03B 100%)" title={ project.frontmatter.title }>
<GatsbyImage image={ project.frontmatter.thumb.childImageSharp.gatsbyImageData }></GatsbyImage>
<Themed.p>{ project.frontmatter.description }</Themed.p>
</ProjectCard>
))}
</Themed.div>
</Inner>
</ContentNoParallax>
</div>
</Layout>
);
}
export const query = graphql`
query ProjectData($typeKey: String) {
projects: allMarkdownRemark(
sort: {fields: frontmatter___date, order: DESC}
filter: {frontmatter: {typeKey: {eq: $typeKey}}}
) {
nodes {
id
frontmatter {
title
slug
description
typeKey
thumb {
childImageSharp {
gatsbyImageData(
placeholder: BLURRED
)
}
}
}
}
}
}
`;
export default ProjectType
Solution 1:[1]
Have you tried filtering by key instead of typeKey in the project-type.jsx?
export const query = graphql`
query ProjectData($key: String) {
projects: allMarkdownRemark(
sort: {fields: frontmatter___date, order: DESC}
filter: {frontmatter: {typeKey: {eq: $key}}}
) {
nodes {
id
frontmatter {
title
slug
description
typeKey
thumb {
childImageSharp {
gatsbyImageData(
placeholder: BLURRED
)
}
}
}
}
}
}
`;
I assume the field in the markdown file is named typeKey because you are querying it (despite in your question you said key), however, the variable you are passing to your template is named key because of:
context: { key: 'photoman' }
I suggest using the same naming convention to avoid this kind of issue, but essentially, you are passing a key field that was being received as typeKey, which doesn't match, so the query wasn't filtering.
As per the project template, I think you don't need to create pages using gatsby-node.js as long as you already know the slug (/motion-graphics, /photo-editing, /photo-manipulation and /web-development) so you can just create 4 files inside /pages folder named motion-graphics.js, photo-editing.js, photo-manipulation.js and web-development.js and place there a filtered (by key) page query.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
