Client-only Routes & User Authentication
Often you want to create a site with client-only portions, which allows you to gate them by authentication or load different content based on URL parameters.
A classic example would be a site that has a landing page, various marketing pages, a login page, and then an app section for logged-in users. The logged-in section doesn’t need to be server rendered as all data will be loaded live from your API after the user logs in. So it makes sense to make this portion of your site client-only.
Client-only routes will exist on the client only and will not correspond to
index.html files in an app’s built assets in the
/public directory. If you’d like site users to be able to visit client routes directly, you need to set up your site to handle those routes appropriately. Or, if you have control over the configuration of the file server yourself, you can set up the server to handle these routes.
A sample site might be set up like this:
Gatsby converts components in the
pages folder into static HTML files for the Home page and the App page. A
<Router /> is added to the App page so that the profile and details components can be rendered from the App page; they don’t have static assets built for them because they exist only on the client. The profile page can
POST data about a user back to an API, and the details page can dynamically load data about a user with a specific id from an API.
Gatsby uses @reach/router under the hood so we’ll use it to set up client-only routes within our app.
You first need to set up routes on a page that is built by Gatsby. You can see the routes added to
src/pages/app/[...].js in the code example below:
Briefly, when a page loads, Reach Router looks at the
path prop of each component nested under
<Router />, and chooses one to render that best matches
window.location (you can learn more about how routing works from the @reach/router documentation). In the case of the
/app/profile path, the
Profile component will be rendered, as its prefix matches the base path of
/app, and the remaining part is identical to the child’s path.
With authentication set up on your site, you can create a component like a
<PrivateRoute/> to extend the example above and gate content:
<PrivateRoute /> component would look something like this one (taken from the Authentication Tutorial, which implements this behavior):
Tip: For applications with complex routing, you may want to override Gatsby’s default scroll behavior with the shouldUpdateScroll Browser API.
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
Popular hosting services like Gatsby Cloud, Netlify, and Vercel have plugins that automatically configure hosting to handle client-only routes.
Your server configuration should handle
GET requests to
/app/[...]/index.html and let the client handle the rendering of the route with the matching path. It is important to note that the response code should be a 200 (an OK) and not a 301 (a redirect). This can be done with NGINX using
try_files, or an equivalent directive if using Apache.