Gatsby project structure
Tags: gatsby, react, node
Published: 2021-01-17 09:33:32

__Gatsby Boilerplate__

The Gatsby boilerplate gives us a set of files and directories which we use to build static sites. It consists of the following files and directories :

```
|-- /.cache
|-- /public
|-- /src
    |-- /pages
    |-- /templates
|-- gatsby-config.js
|-- gatsby-node.js
|-- gatsby-ssr.js
|-- gatsby-browser.js
```

Let's not follow the order with respect to the above file structure. Instead we would have a close look over each file and directory.

__package.json and package-lock.json__

The node dependencies required for the Gatsby project development are mentioned in the __package.json__ file. The __package-lock.json__ keeps track of what already has been installed. The Gatsby cli and Gatsby itself will be installed using the system from npm. These files also allow us to specify how we want our scripts to run and compile our code.

__gatsby-config.js__

This is important to create the global metadata information about the website. It is the file where we add our configuration options for our Gatsby site. For example : we add our site name and description, the Gatsby plugins, and their settings etc.

__gatsby-source-firestore__ plugin in the below config file generates GraphQL end points with cloud firestore as the datasource. During build time, Gatsby pulls data from this endpoint and then generates the static HTML content. We can also have datasource from any RDS or No-SQL database.
 
```
module.exports = {
  siteMetadata: {
    title: `My first gatsby project`,
    description: `My first gatsby site's description`,
    author: `@Hari Krishnan`,
  },
  plugins: [
    {
      resolve: `gatsby-source-firestore`,
      options: {
        // firebase.json contains the credentials and other metadata to connect to your firebase server
        // below code generates the graphql endpoints with the firebase cloud firestore as the source
        credential: require('./firebase.json'),
        types:[
          {
            type: 'Products',
            collection: 'products',
            map: doc => ({
              name: doc.name,
              id: doc.id,
              description: doc.description,
              price: doc.price
            })
          }
        ]
      }
    },
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-postcss`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
  ],
}

```

__gatsby-node.js__

We use this file to create our custom pages. For example: in an e-commerce site, we may have n number of products, for each product Gatsby creates a separate html static file during build time. We specify how each product file should be built and how the url should look like etc. 

In this node file, we specify from which server endpoint (ex: GraphQL endpoint) we need to get the data to build the static custom pages during build time. So this node file will actually execute before the application is built, this feature makes Gatsby so powerful.

Once we get the data from the endpoints, Gatsby uses the function called __createPages__ to create static pages with data from an external source. Most important point to note is that we list only Gatsby plugins here, not any other plugin.

```
exports.createPages = ({graphql,actions}) => {
    const { createPage } = actions;
    // product template is the html page whose layout will be 
    // reused for each product page in an e-commerce site.
    // This file resides in the src/templates folder
    const productTemplate = path.resolve('src/templates/productTemplate.js');
    // the below graphql query gets the data from a firebase 
    // server and then generates the 
    return graphql(`
        {
            allProducts {
                edges {
                    node {
                            name
                            price
                            id
                            description
                    }
                }
            }
        }
    `).then((result) => {
        if(result.errors) {
            throw result.errors;
        }
        result.data.allProducts.edges.forEach(product => {
            createPage({
                path: `/product/${product.node.id}`,
                component: productTemplate,
                context: product.node
                // context is the data that we pass to the productTemplate component
                // we can access it in the productTemplate component using the props 
            })
        })
    });
}
```

__src/templates__

All the custom page layouts are defined in the templates folder. For example : each product page will follow this template to create the HTML output page.

```
const ProductTemplate = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
      <h2>{props.price}</h2>
      <p>{props.description}</p>
    </div>
  );
}

export default ProductTemplate;
```

__gatsby-browser.js__

This file gives you control over Gatsby's behaviour in the browser. Like we can trigger some method or function when the user changes the routes. Even more, you can call a function when the user first opens any page. For example, when the client-side rendering happens, we can wrap all the page content in a special React component using the __wrapPageElement__ or the __wrapRootElement__. Also you can do some executions while the client opens the page by __onClientEntry__ (called when the site is first rendered on to the browser) or give an order to the __serviceWorkers__ .

This file is for advanced use cases when we want a customised __what happens__ when your site appears in the browser. For most use cases we won't need this file, if we want we can also delete this.

__gatsby-ssr.js__

SSR stands for __server-side rendering__ . This file lets you customise how Gatsby generates the static HTML files that your browser uses to load your site quickly. If you have known about Sapper (another SSR framework), this concept is something similar to the sapper's __preload function__ , where we will get the data from the browser and the page is served as HTML content from the server itself. If we don't need SSR, we can also delete this file. 

SSR is best suitable when we need SEO, because web crawlers do not wait until the page is loaded with all the data, so server-side rendering can be used to load the data from the server itself. This makes our HTML page easily visible for web-crawlers.
  
__src__

This folder contains the main views for our Gatsby site. These are the front end pages that our users will see and interact with. 

__src/components__

All the basic layout files and the templates that typically get included with every page; such as the overall __'Layout.js'__ file, your __'Header.js'__ file which contains your top of the page __'<head>'__ html and may be your navbar etc.. is put into this folder. These are structured as React components and are translated into your HTML page by the Gatsby core API itself when __'building'__.

__src/pages__

All the main pages of your site, including your initial index.js page is put to this folder. __index.js__ is the page which users land on when they land on the home page of your website. You also have your other pages referenced here, such as your __'about-us.js'__ page and your __'contact.js'__ page etc.. . These are also structured as React components and are translated into your HTML page by the Gatsby core API itself when __'building'__. 

``` 
//(index.js file)
import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

// when we export a query like this in our page
// gatsby automatically executes the query and  gets the
// result
// and injects it into the props fo the below react component 

export const query = graphql`
  {
    allProducts {
      edges {
        node {
          id
          price
          description
          name
        }
      }
    }
  }
`;


const IndexPage = (props) => {
  console.log(props);
  return (
    <Layout>
      {props.data.allProducts.edges.map(edge => (
        <div key={edge.node.id}>
          <h2>
            {edge.node.name} - <small>{edge.node.price}</small>
          </h2>
          <div>
            {edge.node.description}
          </div>
          <Link to={`/product/${edge.node.id}`}>
            Route to individual product page
          </Link>
        </div>
      ))}
    </Layout>
  );
}


export default IndexPage;
```

__public/__

This is the folder where your built files live. Once we have run our build scripts, this is the path where the files that will ultimately be served end up.

__Page Routing__

Gatsby automatically turns the pages in the src/pages (which are structured in the form of react components) into your final HTML output pages. For example your __'about-us.js'__ would be accessible via __'yoursite.com/about-us.js'__


If you have any kind of feedback, suggestions or ideas - feel free to comment this post!