Chapter 3. Adding Features to Gatsby Sites

Now that you’re equipped with an understanding of Gatsby fundamentals and core elements, including the Gatsby CLI, starters, pages, components, CSS, and plugins, we can direct our attention to how to introduce and implement certain key features that are common on websites.

In this chapter, we’ll take a brief detour from the conceptual underpinnings of Gatsby to focus on real-world use cases and requirements that many Gatsby developers encounter when developing websites. Adding critical features to Gatsby sites such as analytics, authentication, and form handling will help you hone your React and Gatsby skills. In this chapter, we’ll build a basic Gatsby site with all of these features, putting what you’ve learned so far to use.

Pages and Routing in Gatsby

One of the primary selling points of Gatsby is that it is a static site generator, as we discussed in Chapter 1. Nonetheless, thanks to Gatsby’s dependency on React, a library for building interactive user interfaces, Gatsby sites can blur the line between static sites and more dynamic applications. This is a general trend in websites today, with dynamic forms and dynamic search becoming more common than search features and contact forms that require a full-page refresh, and Gatsby follows suit. Once a static rendering of the site is made available to the browser, Gatsby passes the baton to React, which performs all further dynamic or asynchronous operations that need to occur to decorate and enrich the static site with more interactive behavior.

In this section, we won’t be adding new features just yet. Instead, we’ll establish the background you need to understand how to implement different features in Gatsby, including some of the key ways in which Gatsby allows developers to add those features, whether they are static or dynamic in nature.

Rehydration

Once Gatsby’s generated static files are flushed (i.e., transmitted) to the browser, Gatsby sites perform rehydration, a process common in universal JavaScript (JavaScript that can run both on the client and the server) in which static HTML that was rendered through ReactDOM APIs on the server is bound to dynamic JavaScript initialized through the client-side React bundle. Rehydration occurs in the following sequence:

  1. First, Gatsby builds and renders static HTML through ReactDOM APIs on the server side, with the retrieval of content and pages occurring during build-time compilation. This is initiated by execution of the gatsby build command, which launches a Node.js server to render HTML into static files in the /public folder.

  2. Next, Gatsby invokes ReactDOM’s hydrate method to pick up any further rendering from where the static HTML left off. ReactDOM.hydrate() is used for those areas whose HTML contents were rendered by ReactDOMServer.

  3. Finally, Gatsby transfers rendering to the React reconciler, which performs rehydration of the Gatsby-generated static site. The React reconciler is also responsible for tracking changes in the DOM tree and implementing updates as needed based on state and prop changes.

In other words, Gatsby allows rendering to happen arbitrarily in two locations: build-time compilation on the server side is responsible for generating the initial static HTML, and React reconciliation and rehydration on the client side are responsible for any further dynamic behavior the page requires. In this way, Gatsby sites can make calls for dynamic data and perform asynchronous actions like user authentication without requiring the use of a completely separate development paradigm.

Gatsby makes three types of routes (equivalent to pages in Gatsby) available: static, dynamic, and a hybrid of the two. We’ll cover each of them in turn in the coming three sections.

Static Pages

Static pages are the primary approach to working with Gatsby. As you saw in the previous chapters, Gatsby automatically detects new JavaScript files that are located in the src/pages folder in order to convert them into static pages. Later in the book, you’ll see that programmatic page creation also follows this pattern to generate static pages based on particular parameters.

Figure 3-1 shows how Gatsby can automatically create pages from files placed in src/pages as well as programmatically create pages through the createPages API, which we cover at length in Chapter 6.

Figure 3-1. An illustration of the difference between static page creation, driven by developers placing a page in the src/pages directory, and programmatic page creation through the createPages API
Note

Gatsby plugins and themes can also implement the createPages API and create Gatsby pages on your behalf programmatically. We cover this workflow in Chapter 6.

Hybrid Application Pages

In Gatsby, hybrid application pages are pages that contain both static HTML generated by Gatsby and dynamic HTML and JavaScript, which means they connect to external services and APIs serving data asynchronously through API requests. We call these pages “hybrid” because they leverage Gatsby’s performance benefits in the form of static site performance and the client-side benefits of greater interactivity and dynamism in the browser.

Figure 3-2 depicts how Gatsby can provide static HTML that outlines the initial markup for a form, with a subsequent asynchronous POST request occurring once the form is submitted.

Figure 3-2. In hybrid application pages, a static page contains a dynamic component that issues an asynchronous POST request to communicate with an external service

Note that any asynchronous API requests can be realized through this paradigm, including GET requests to populate a section of the page that requires much more “live” or “real-time” data than Gatsby’s build-time compilation would be able to facilitate. Though this paradigm depends on the constant availability of backend services, which isn’t the case in static pages, these more dynamic integrations are often of critical importance for business logic.

Client-Only Routes

Because Gatsby is built on top of React, it’s possible to leverage React’s client-side router to provide client-only routes that don’t represent a full static page or a full hybrid application page. Gatsby ships with the accessible router @reach/router, now part of the core React Router library, which allows you to refrain from introducing other routing dependencies from the React ecosystem. In short, client-only routes made available by React on the client side are not registered among the statically rendered files or pages created during Gatsby’s build-time compilation.

Figure 3-3 shows an example of how client-only routes can enrich static Gatsby sites with dynamic and asynchronous routing based on information such as the logged-in user’s profile or a response in a form field earlier in the page.

Figure 3-3. A client-side router in React provides client-only routes to dynamic areas of the site where authentication is needed or where a static page isn’t possible; in this scenario, Gatsby delegates client-only routes to React
Warning

In order to allow users to bookmark or link to the URL for a client-only route directly, you will need to use a plugin to create those pages under Gatsby’s purview so Gatsby is aware of them.

Differences Between Gatsby Sites and React Applications

This section covers the differences between React development paradigms like the Create React App (CRA) project and Gatsby. Though a site built with React’s official Create React App boilerplate can easily be ported to Gatsby, it’s important to recognize these differences, particularly for developers context-switching between the two approaches.

Gatsby differs from normal Create React App applications in a few crucial ways:

  1. React uses App.js; Gatsby uses pages. Instead of a single global App.js component, which is common in Create React App and registers all client routes on that component, Gatsby delivers a collection of multiple pages that can be either hybrid or static.

  2. React requires routers; Gatsby automates routing. Instead of creating pages through setting up a React-compatible router, Gatsby provides automatic and programmatic ways to generate pages that represent routes. When files are placed into the src/pages directory, Gatsby generates fixed URLs for each based on the component name. For client-side routing, developers can introduce routing driven by React on the client side.

Porting Create React App applications to Gatsby sites is beyond the scope of this book, but the documentation includes a guide to migrating Create React App implementations to Gatsby.

Now that you understand how implementing additional features in Gatsby often requires distinct approaches to pages and routing, we can move ahead to adding key features to our sites. Remember that many of these implementations will require some combination of static pages, hybrid application pages, and client-only routes, depending on the desired user experience.

Adding Forms

One of the most common needs in any website is HTML forms that collect information from users, whether that data is intended for authentication or for some response from an external service. Because Gatsby is built on top of React, many of the same approaches used to build and handle forms in React carry over into Gatsby.

Basic Forms

Let’s take a look at how we can introduce basic form markup and handling into any Gatsby site. To begin, we’ll create another version of the Gatsby default starter (we’ll build on top of the default starter throughout the remainder of this chapter, ending up with a Gatsby site with a variety of features):

$ gatsby new gtdg-ch3-features gatsbyjs/gatsby-starter-default
$ cd gtdg-ch3-features

Let’s add another page named src/pages/basic-form.js with the following code. Note that here we’re introducing several state properties that we want to ensure Gatsby tracks, so we are instantiating a new class based on React.Component:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

export default class BasicFormPage extends React.Component {
  state = {
    firstName: "",
    lastName: "",
    country: "",
    city: "",
  }
  render() {
    return (
      <Layout>
        <Seo title="Basic form" />
        <h1>Hi from the basic form page</h1>
        <p>Welcome to the basic form page</p>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

Now, we can add several HTML <input> elements to render a form on the basic form page. As you can see, we’ve replaced the “Welcome to the basic form page” paragraph with an HTML form:

export default class BasicFormPage extends React.Component {
  state = {
    firstName: "",
    lastName: "",
    city: "",
    country: "",
  }
  render() {
    return (
      <Layout>
        <Seo title="Basic form" />
        <h1>Hi from the basic form page</h1>
        <form>
          <label>
            First name
            <input type="text" name="firstName" />
          </label>
          <label>
            Last name
            <input type="text" name="lastName" />
          </label>
          <label>
            City
            <input type="text" name="city" />
          </label>
          <label>
            Country
            <input type="text" name="country" />
          </label>
          <button type="submit">Submit</button>
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

In React, one of the key tenets of state management is that any change to user input in a form element should result in an update to the state properties we’ve defined (firstName, lastName, city, and country). To handle changes to input, let’s add an onChange prop to each <input> element and a value prop to keep the input up to date:

export default class BasicFormPage extends React.Component {
  state = {
    firstName: "",
    lastName: "",
    city: "",
    country: "",
  }

  handleInputChange = event => {
    const target = event.target
    const value = target.value
    const name = target.name

    this.setState({
      [name]: value,
    })
  }

  render() {
    return (
      <Layout>
        <Seo title="Basic form" />
        <h1>Hi from the basic form page</h1>
        <form>
          <label>
            First name
            <input
              type="text"
              name="firstName"
              value={this.state.firstName}
              onChange={this.handleInputChange}
            />
          </label>
          <label>
            Last name
            <input
              type="text"
              name="lastName"
              value={this.state.lastName}
              onChange={this.handleInputChange}
            />
          </label>
          <label>
            City
            <input
              type="text"
              name="city"
              value={this.state.city}
              onChange={this.handleInputChange}
            />
          </label>
          <label>
            Country
            <input
              type="text"
              name="country"
              value={this.state.country}
              onChange={this.handleInputChange}
            />
          </label>
          <button type="submit">Submit</button>
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}
Note

This example does not use React Hooks, a common paradigm Gatsby developers can use to replace class-based components. We’ll see some examples of its use in the next chapter.

Now, whenever we change any of the contents of the <input> elements on the page, our state will update with the new values in those form elements. But what happens when we submit the form? Currently, because we haven’t added an onSubmit event handler, the submit button won’t work as expected.

What we need to do is add another method right underneath handleInputChange that handles our submit event: handleSubmit. For brevity’s sake, the following example below shows just the definitions of handleInputChange and handleSubmit:

// ...

  handleInputChange = event => {
    const target = event.target
    const value = target.value
    const name = target.name

    this.setState({
      [name]: value,
    })
  }

  handleSubmit = event => {
    event.preventDefault()
    alert(`Howdy ${this.state.firstName} ${this.state.lastName} from ${this.state.city}, ${this.state.country}!`)
  }

// ...

We also need to invoke the handleSubmit handler when the form is submitted, which we do by adding an onSubmit attribute to the form element:

<form onSubmit={this.handleSubmit}>

Now, our basic form performs a submit action by displaying an alert message containing our newly input values. But now that we have a submission handler, how do we extend it so that we can pass user input on to an external service as needed?

Note

The React ecosystem has several libraries that make developing forms much easier in React applications and Gatsby sites, such as Formik and Final Form.

Handling Form Submissions

In many traditional websites, whenever a form is submitted, the contents of the user-provided inputs are passed to a server, which handles the data and responds in some fashion. In the example from the previous section, we wrote some rudimentary logic for an alert message to display the user-submitted data.

If the logic handling form submissions is all housed within the confines of your React application, you’ll write React code to control what happens when the user submits a form. But in the case of common forms like contact forms, you’ll want to store that information somewhere else, such as in an external database or CRM system. Let’s copy the contents of src/pages/page-2.js into another file named src/pages/contact.js. Replace the paragraph element again with a form whose purpose is to request a name, an email address, and a message:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

export default class ContactPage extends React.Component {
  render() {
    return (
      <Layout>
        <Seo title="Contact" />
        <h1>Hi from the contact page</h1>
        <form method="post" action="#">
          <label>
            Name
            <input type="text" name="name" id="name" />
          </label>
          <label>
            Email
            <input type="email" name="email" id="email" />
          </label>
          <label>
            Message
            <textarea name="message" id="message" rows="6" />
          </label>
          <button type="submit">Submit</button>
          <input type="reset" value="Reset" />
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

There are four ways to handle form submissions in Gatsby:

  1. Getform

  2. Netlify Forms

  3. Formspree

  4. Roll your own server

We’ll cover the first three in the next three sections. The final approach, setting up your own form handler in an HTTP server, is well beyond the scope of this book. If you have a working form handler, the value of the action attribute becomes the endpoint at which your server accepts form submissions:

<form method="post" 
      action="https://my-form-handler-wxyz789.vercel.app/contact">
Note

Getform, Netlify Forms, and Formspree all offer code examples for common requirements such as Ajax-based form submissions and reCAPTCHAs to prevent spam.

Getform

Getform is a backend form service that offers a free tier for handling form submissions that originate from static sites. As you can see here, you only need to make one small modification to the form we wrote earlier:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

export default class ContactPage extends React.Component {
  render() {
    return (
      <Layout>
        <Seo title="Contact" />
        <h1>Hi from the contact page</h1>
        <form
          method="post"
          action="https://getform.io/your-getform-endpoint-here" 
        >
          <label>
            Name
            <input type="text" name="name" id="name" />
          </label>
          <label>
            Email
            <input type="email" name="email" id="email" />
          </label>
          <label>
            Message
            <textarea name="message" id="message" rows="6" />
          </label>
          <button type="submit">Submit</button>
          <input type="reset" value="Reset" />
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

Point the value of the action attribute to your unique Getform endpoint.

Then, once the changes are applied and your Getform endpoint is configured, you’ll begin to see your Getform dashboard populated with the form submissions.

Note

For more information about Getform, consult the Getform website.

Netlify Forms

Netlify Forms is a form submission collection feature available for free on the Netlify hosting platform, which offers infrastructure for static sites. Netlify has its own form handling feature that works similarly to Getform and again requires only a few updates to the original form:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

export default class ContactPage extends React.Component {
  render() {
    return (
      <Layout>
        <Seo title="Contact" />
        <h1>Hi from the contact page</h1>
        <form
          method="post"
          netlify-honeypot="bot-field" 
          data-netlify="true"
          name="contact"
        >
          <input type="hidden" name="bot-field" /> 
          <input type="hidden" name="form-name" value="contact" /> 
          <label>
            Name
            <input type="text" name="name" id="name" />
          </label>
          <label>
            Email
            <input type="email" name="email" id="email" />
          </label>
          <label>
            Message
            <textarea name="message" id="message" rows="6" />
          </label>
          <button type="submit">Submit</button>
          <input type="reset" value="Reset" />
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

Add Netlify’s required form attributes.

Add Netlify’s two required hidden input fields.

Once Netlify recognizes the form, you’ll see your Forms dashboard in Netlify being populated with form submissions.

Note

For more information about Netlify Forms, consult the Netlify Forms documentation.

Formspree

Formspree differs from both Getform and Netlify Forms in that it provides a free tier for form submissions to be delivered to an email address rather than a web dashboard. All form submissions will be sent to the configured address:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

export default class ContactPage extends React.Component {
  render() {
    return (
      <Layout>
        <Seo title="Contact" />
        <h1>Hi from the contact page</h1>
        <form
          method="post"
          action="https://formspree.io/[email protected]" 
        >
          <label>
            Name
            <input type="text" name="name" id="name" />
          </label>
          <label>
            Email
            <input type="email" name="_replyto" id="email" /> 
          </label>
          <label>
            Message
            <textarea name="message" id="message" rows="6" />
          </label>
          <button type="submit">Submit</button>
          <input type="reset" value="Reset" />
        </form>
        <Link to="/">Go back to the homepage</Link>
      </Layout>
    )
  }
}

Point the value of the form’s action attribute to your email address.

Add the Formspree-specific value of the name attribute (_replyto) on the <input> element collecting a visitor’s email address.

Also note that while Formspree comes with reCAPTCHA enabled by default, you can also enable spam filtering through Honeypot by adding a hidden <input> element with the name _gotcha, similarly to how Netlify Forms includes hidden <input> elements to prevent spam:

<input type="hidden" name="_gotcha" />
Note

For more information about Formspree, consult the Formspree website.

Adding Localization and Internationalization

For Gatsby sites with multiple audiences, whether that means different regions or different language communities, localization (l10n) and internationalization (i18n) comprise essential functionality. Generally speaking, the processes of localization and internationalization entail providing translations of text, date formats, numbers, and other elements that adhere to the expectations of a user’s location. As an example, though dates in the United States follow the MM/DD/YYYY date format, Japanese users follow the YYYY-MM-DD format.

The React ecosystem makes available several different packages for internationalization, each with its own advantages and disadvantages. For this reason, it’s best to evaluate each package based on factors such as whether you are already using that internationalization package on other projects, how well it serves your users’ requirements, and how well documented and well maintained the package is.

In this section, we cover three of the available packages, starting with the Gatsby ecosystem’s own internationalization plugin.

gatsby-plugin-i18n

The gatsby-plugin-i18n plugin integrates directly with the react-intl and react-i18next libraries (discussed next) to facilitate integration with Gatsby sites. Though gatsby-plugin-i18n itself does not perform any translation or reformatting, it uses Gatsby’s built-in page system to create routes for each localization or internationalization and to permit layout changes (e.g., for right-to-left languages). Once you install gatsby-plugin-i18n, your localized or internationalized versions of Gatsby pages will adhere to the format in Table 3-1.

Table 3-1. How page filenames and resulting URLs change based on the use of the gatsby-plugin-i18n plugin
Scenario Page filename Page URL
No localization or internationalization src/pages/contact.js mygatsbysite.com/contact
With localization or internationalization src/pages/contact.en.js mygatsbysite.com/en/contact

react-intl

The react-intl library, part of the FormatJS collection of internationalization libraries, is based on JavaScript’s standard Internationalization API and offers built-in support for more than 150 languages. react-intl uses React context and higher-order components (HOCs) in React to provide translations. In React parlance, this means that you can dynamically load language modules as you require them and remove them from bundles when they aren’t needed. react-intl integrates with gatsby-plugin-i18n and a polyfill for browsers that don’t yet support the JavaScript i18n API.

react-i18next

The react-i18next library is built on top of the i18next framework and leverages components to ensure that translations are rendered where needed and to dynamically update page content when the user selects a new language. react-i18next can be more flexible than react-intl depending on your needs, especially if they involve caching, server-side translations, and bundling translations using Webpack. The react-i18next library also makes use of modern React APIs such as the Suspense API and React Hooks.

Examining these React libraries would require considerable discussion of projects specific to the React ecosystem and be well outside the scope of this book, so we’ll end our exploration of localization and internationalization here. Just be aware that because multilingual and multilocale capabilities remain in significant flux in both the React and Gatsby ecosystems, the Gatsby community has not yet unified around a standard set of best practices.

Note

For more comprehensive information about these libraries, consult the respective documentation for gatsby-plugin-i18n, react-intl, and react-i18next. A tutorial by Samuel Goudie called “Building i18n with Gatsby” is also available in the Gatsby blog.

Adding an XML Sitemap

In traditional websites, sitemaps are important means for visitors to understand the overarching structure and information architecture as quickly as possible. Generally, XML sitemaps display the website’s most critical pages and ensure that search engines discover them all. In other words, sitemaps are like maps for your website.

Gatsby has an official plugin, gatsby-plugin-sitemap, which provides automatic generation of XML sitemaps on every Gatsby build. To install gatsby-plugin-sitemap, change directories to the root of your Gatsby project and execute one of the following commands:

# If using NPM
$ npm install gatsby-plugin-sitemap

# If using Yarn
$ yarn add gatsby-plugin-sitemap

Then, in your gatsby-config.js file housing site information and plugins, add gatsby-plugin-sitemap to the plugins array:

module.exports = {
  siteMetadata: {
    siteUrl: `https://www.mygatsbyurl.com`,
  },
  plugins: [`gatsby-plugin-sitemap`],
}
Note

The gatsby-plugin-sitemap plugin requires the siteUrl value to be populated and not empty in order to function properly. In addition, gatsby-plugin-sitemap has a variety of options that can be overridden based on configuration in gatsby-config.js. For a full account of the options, consult the plugin documentation.

Now, when you run a production build (with gatsby build or npm run build), gatsby-plugin-sitemap will automatically generate a new sitemap based on the current state of your pages located at /sitemap.xml (Figure 3-4).

Figure 3-4. The sitemap generated by the gatsby-plugin-sitemap plugin upon execution of the gatsby build command

To avoid any unexpected surprises, it’s important to note that gatsby-plugin-sitemap always excludes these pages: /dev-404-page (Gatsby’s development 404 page), /404 (a developer-defined 404 page), and /offline-plugin-app-shell-fallback (an offline fallback). These cannot be modified; we’ll discuss the first two in the next section.

Note

A gatsby-plugin-advanced-sitemap plugin is available which offers more configuration possibilities and options to generate single or multiple sitemaps that contain XSL templates for better formatting. For more information, consult the plugin page and Aileen Nowak’s blog post about its usage.

Adding a 404 Page

One of the most important error pages in any website is the 404 page, which handles 404 Not Found errors for users who have clicked a broken link or entered a nonexistent URL. The most common and straightforward method to add a 404 page to a Gatsby website is to simply create a new page at src/pages/404.js.

Because many static hosting platforms default to sending users to a 404.html page, naming your 404 page in this way will ensure that Gatsby automatically detects it and places it in the expected location in the /public directory. Fortunately, our Gatsby default starter already creates a 404 page for us. Open the file src/pages/404.js, and you’ll see the following code:

import React from "react"

import Layout from "../components/layout"
import Seo from "../components/seo"

const NotFoundPage = () => (
  <Layout>
    <Seo title="404: Not found" />
    <h1>404: Not Found</h1>
    <p>You just hit a route that doesn&#39;t exist... the sadness.</p>
  </Layout>
)

export default NotFoundPage

You can replace this with your own desired 404 page content, such as a link back to the home page or a list of common destinations for users who have landed in the wrong place. When you deploy your Gatsby site online, whenever you type in a URL absent from the site, the 404 page will display (Figure 3-5).

Figure 3-5. The default 404 page built into the Gatsby default starter
Tip

If you have a local development server running with gatsby develop, Gatsby will override your custom 404 page with its own internal “Gatsby.js development 404 page,” which provides some useful developer actions. It also makes a “Preview custom 404 page” button available so you can still access your custom 404 page from the Gatsby development server’s own 404 page.

Adding Analytics

Often one of the aspects of web development left to the end of the implementation process, analytics is one of the best ways to gain insights into how your visitors and users interact with your website, including which areas are the most visited, where users are coming across your site, and at what times they come by.

Though there are a variety of analytics services available, the most commonly used with Gatsby sites is Google Analytics, which provides a free tier for up to 10 million hits per month per Tracking ID (a single Google Analytics property).

Once you’ve set up a Google Analytics account (if you don’t have one already), you’ll be prompted by the interface to create a new property, which is associated with a single Tracking ID. Each website will generally need a separate Tracking ID to avoid corrupting the incoming data. Tracking IDs have the format UA-XXXXXXXXX-X.

Now, we’ll add Google Analytics support to our Gatsby site using the gatsby-plugin-gtag plugin, which can be installed using the following commands:

# If using NPM
$ npm install gatsby-plugin-gtag

# If using Yarn
$ yarn add gatsby-plugin-gtag

In gatsby-config.js, add your plugin to the plugins array and configure it by adding an options object that contains your own trackingId from Google Analytics:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-gtag`,
      options: {
        trackingId: `UA-XXXXXXXX-X`,
      },
    },
  ],
}

Now, when you check your Google Analytics dashboard for your Gatsby property, you’ll begin to see analytics data streaming in.

Conclusion

In this chapter, we took a closer look at some of the most common requirements that web developers face when implementing a new website, including form handling, localization and internationalization, analytics, and necessities like an XML sitemap and a 404 page. In the process, we revisited many of the concepts from the first two chapters, including the Gatsby CLI, JSX in Gatsby, Gatsby pages and components, and working with Gatsby plugins. We also implemented a variety of forms, sitemaps, 404 pages, and analytics.

Though this chapter involved many interactions with external services and use cases that may be less useful for your purposes, it allowed us to engage in a comprehensive review of some of the foundational concepts in Chapters 1 and 2. This is important because in Chapters Chapter 4 and Chapter 5 we’ll move into the Gatsby data layer, GraphQL, and source plugins, which interact in rich ways to facilitate the retrieval and management of external data. With a few more features in our Gatsby site, we can begin to substitute hardcoded content and data for real-world information coming from disparate sources.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.172.68