1

My goal is to enable the following types of static and dynamic paths with the best pattern possible when using Gatsby (v2) and @reach/router. The problem I've run into is that the Gatsby docs set you up to prefix the path /app on every dynamic route, which does not fit my use case.

Desired paths:

  • /: static route and build-time generated
  • /about: static route and build-time generated
  • /:username: dynamic route and run-time generated
  • /:username/:postTitleSlug: dynamic route and run-time generated

Following the Gatsby docs, I have this folder structure:

/pages
  index.jsx
  about.jsx
  app.jsx
/templates
  profile.jsx // for the /:username path
  post.jsx // for the /:username/:postTitleSlug path

app.jsx

const Routes = () => (
  <Router>
    <Profile path="/:username" />
    <Read path="/:username/:slug" />
  </Router>
);

gatsby-node.js

exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions;

  if (page.path.match(/^\/app/)) {
    await createPage({
      path: 'app',
      matchPath: '/app/*',
      component: path.resolve('src/templates/Profile/index.js'),
    });
  }
};

Is it possible to unwind the "app" nomenclature and key some dynamic routes off of the base path, /?

FWIW, my first attempted fix was to make pages/index.jsx just a router, similar to this post. It seems like a potential solution, but I'm not clear on the required updates to gatsby-node.js.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
Kwhitejr
  • 2,206
  • 5
  • 29
  • 49

1 Answers1

1
  • For your / just create an index.js file inside your /pages folder, Gatsby will take it as a home page by default.
  • For your /about page, just create an about.js inside your /pages folder. Since Gatsby is a file-path based it will take it to build your /about page. The same approach works for all static pages.

For the client-only routes, the "first" slug (:username) needs to be handled by Gatsby in order to avoid a 404 error, while the second (:slug) can be handled by the @reach/router. Something like:

// Implement the Gatsby API “onCreatePage”. This is
// called after every page is created.
exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions

  // page.matchPath is a special key that's used for matching pages
  // only on the client.
  if (page.path.match(/^\/user\/$/)) {
    createPage({
      ...page,
      matchPath: '/:username/*'
    })
  }
}

Then in your template:

 <Router>
        <User path="/user/:username" />
        <UserAsset path="/user/:username/:slug" />
 </Router>

This approach handles /user/:username/:slug but you can adapt it to your needs.

Alternatively, you can save this workaround by using gatsby-plugin-create-client-paths plugin simply by:

{
  resolve: `gatsby-plugin-create-client-paths`,
  options: { prefixes: [`/username/*`] },
},
Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67