Mihai Moraru
Mihai Moraru

Reputation: 404

Is there any way to create dynamic slugs with Gatsby using a template component / page?

I am quite new to Gatsby and I'm wondering if I can create custom routes (slugs) as templates. The use case would be:

  1. Access /articles/name-of-the-article route
  2. Serve component Article.js populated with the information retrieved from an API (i.e Strapi headless CMS) using the name-of-the-article slug.

Upvotes: 4

Views: 2714

Answers (2)

Mihai Moraru
Mihai Moraru

Reputation: 404

After some investigations, I found out that there is a much easier way to do so by using gatsby-plugin-create-client-paths. All you need to do is install it with yarn or npm and then in gatsby-config.js you'll add these:

{
      resolve: `gatsby-plugin-create-client-paths`,
      options: { prefixes: [`/articles/*`] },
},

This means that every request slug like this: /articles/the-slug will request the articles.js page and using Link that provided by Gatsby, you can pass props through state prop like this:

<Link to="/articles/the-slug" state={{ slug: "the-slug", ...etc }}>Anchor Text</Link>

In this way, src/pages/articles.js becomes the template page for slugs prefixed with /articles.

Upvotes: 6

EliteRaceElephant
EliteRaceElephant

Reputation: 8162

Yes you can. Gatsby has docs for this: Creating pages from data programmatically. You need to create page slugs: Creating slugs for pages. You need to add gatsby-source-strapi to your gatsby-config.js.

I have little experience with Strapi so you need to do some research how you can handle slug creation with Strapi.

Example code:

gatsby-node.js

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions;
  if (node.internal.type === "The Nodes as defined by Strapi") {
    const slug = createFilePath({ node, getNode, basePath: "The base paths as defined by Strapi" });
    createNodeField({ node, name: "slug", value: slug });
  }
};

exports.createPages = async function({ actions, graphql }) {
  const { data } = await graphql(`
{
  allStrapiArticle {
    edges {
      node {
        id
        title
        content
      }
    }
  }
}
  `)
  data.allMarkdownRemark.edges.forEach(edge => {
    const slug = edge.node.fields.slug
    actions.createPage({
      path: slug,
      component: require.resolve(`./src/templates/article-template.js`),
      context: { slug: slug },
    })
  })
}

Upvotes: 2

Related Questions