Gatsby client-side pages return 404 error

Site name: wondrous-sunflower-dafe85.netlify.app
Framework: GatsbyJS
Custom domain not set up
No build error

In my gatsby app, I have created client-side routes with the help of official gatsby guide Client-only Routes & User Authentication | Gatsby. I’ve also installed gatsby-plugin-netlify for the client-side routing to work. Everything is working fine in development, even there is no build error, yet all client-side routes return 404 errors.

Here is my [...].js file -

pages/admin/[...].js

"use client"

import React from "react"
import { Router, Link } from "@reach/router"
import NotFound from "../404"

const App = ({ children }) => (
    <div>
        <Router>
            <Home path="/admin" />
            <Dashboard path="/admin/dashboard" />
            <NotFound default />
        </Router>
    </div>
)

const Home = () => (
    <div>
        <h2>Welcome</h2>
    </div>
)

const Dashboard = () => (
    <div>
        <h2>Dashboard</h2>
    </div>
)

export default App

You’ve added some redirects:

[[redirects]]
    from = "/admin/*"
    to = "/admin/[...]/index.html"
    status = 200

which I don’t think should exist.

You’ve some more:

## Created with gatsby-plugin-netlify
/admin/*  /admin/[...]/index.html  200
/admin/*  /admin/[...]/  200

but that seem to be generated by the plugin and are also incorrect. This sounds like a bug with the plugin and should be filed on its repo.

Hello Hrishikesh,

Thanks for the reply! I added the redirects in the netlify.toml file as one of the solutions I found online. But with the netlify.toml redirects removed, netlify still returns 404 errors when accessing client-sided routes.

As per the redirects added by gatsby-plugin-netlify, I think these redirects are added to handle client-side routing. For client-side routing to work, gatsby client-side routing guide suggests to add certain redirects. Please see this small para on redirects - Client-only Routes & User Authentication | Gatsby

When hosting gatsby site that create client-side routes on a self-hosted server, the redirects need to be added manually. But when hosting on Netlify, the plugin handles redirects itself automatically. Please let me know if I misunderstood anything or need to change anything.

I analyzed a few gatsby projects on github that implement client-side routing. I noticed all of them add the following snippet in gatsby-node.js to create conditional server-side route/page -

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(/^\/admin/)) {
        page.matchPath = `/admin/*`

        // Update the page.
        createPage(page)
    }
}

I have also added it but nothing changed. The client-side routing is working in development mode but not in production.

My gatsby-node.js file content -

const path = require(`path`)
const { slash } = require(`gatsby-core-utils`)

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(/^\/admin/)) {
        page.matchPath = `/admin/*`

        // Update the page.
        createPage(page)
    }
}

exports.onPostBuild = ({ reporter }) => {
    reporter.info(`Your Gatsby site has been built!`)
}

Please let me know if there is any issue with it.

Thank you!

I know, but that redirect is invalid. It should instead be pointing to /admin/index.html and not /admin/[...]/index.html. I believe that’s the problem and a bug in how the redrects are being created.

Gatsby official guide on client-side routing mentions the following about creating redirects -

Site hosting software and services need some help in order to serve client-only routes correctly. Most Gatsby pages have a corresponding html file that the server responds with when a user visits the page e.g. visiting /blog/my-blog-post/ makes the server respond with /blog/my-blog-post/index.html . But client-only routes like /app/why-gatsby-is-awesome/ don’t have a corresponding html file. The server needs to be configured to know to serve /app/[...]/index.html instead.

If we go by the official documentation, the plugin is creating the correct redirects. But when we see the ultimate output, the official guide isn’t working.

I also installed gatsby-plugin-gatsby-cloud, and notice that it also adds similar redirects in the build.

{"redirects":[],"rewrites":[{"fromPath":"/admin/*","toPath":"/admin/[...]/"}]}

I deployed a bare-minimum app and it seems to work fine: forums-98351.netlify.app/admin

Repo here: Hrishikesh-K/forums-98351 (github.com)

If it’s not working for you, please share a minimal reproduction.

First of all, thanks a lot for putting so much efforts. I really appreciate that.

About the minimal reproduction, every bit of code makes sense to me and it’s working fine. I forked it and created a site https://glistening-pony-4ec2e1.netlify.app and it’s working fine. Client-side routing is showing correct page.

And my website is using the exact same method to create client-side routes but it’s rendering 404. There must be other plugins that are interfering and causing 404. Did you check the _redirect file and found what redirects gatsby-plugin-netlify is creating?

Yes, it’s creating the same redirect you have:

/admin/*  /admin/[...]/  200

That’s the only 1 though.

There is a lot of confusion. I deleted 7-8 plugins and it’s still not working. It seems like I will have to start over and this time, I should start with creating client-side routing and then rest of the server-side things. If you have any recommendation, please let me know.

Thanks a lot for the help!

Unfortunately, I’m not sure without seeing your project. Something specific to your setup is most likely causing this, which makes it difficult for me to guess what could be happening. If the issue had occured in the minimal setup I created, it would have been easier to debug, but that seems to work fine.

On a side note, why not simply use Server Side Rendering for such routes? As you can probably see, even loading just a simple <h2> tag adds a delay of about a second. On the first load, the page is blank till the chunks load and then suddenly the text appears. I would only imagine that getting worse as the page gets bloated. It would probably end up being poor user-experience.

I think I may have messed up when I added multiple tailwind configs. I found it difficult to use different tailwind configs on different pages. So I may have made certain changes that I should not have. If you have any better/simple solution to use different tailwind configs on different pages, please let me know.

I am trying to migrate from WordPress to gatsby static website. I did so successfully. But I also want to use Gatsby to create posts or pages. So it’d be a simple CMS. I am using client-side rendering for admin pages such as create post or pages. These will not be static pages. Now that you mentioned, I do notice that one heading is taking around 1 second to load, so it may get worse as the page loads more data dynamically.