---
title: GatsbyJS
pagination_prev: demos/net/index
pagination_next: demos/mobile/index
sidebar_custom_props:
  type: native
---

import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';

Gatsby is a framework for creating websites. It uses React components for page
templates and GraphQL for loading data.

[`gatsby-transformer-excel`](https://www.gatsbyjs.com/plugins/gatsby-transformer-excel/)
is a transformer that generates GraphQL nodes for each row of each worksheet.
The plugin is officially supported by the Gatsby team. The plugin documentation
includes examples and more detailed usage instructions.

:::note

`gatsby-transformer-excel` is maintained by the Gatsby core team and all bugs
should be directed to the main Gatsby project.  If it is determined to be a bug
in the parsing logic, issues should then be raised with the SheetJS project.

:::

:::caution

`gatsby-transformer-excel` uses an older version of the library.  It can be
overridden through a `package.json` override in the latest versions of NodeJS:

<CodeBlock language="json">{`\
{
  "overrides": {
    "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
  }
}`}
</CodeBlock>

:::

## GraphQL details

`gatsby-transformer-excel` generates nodes for each data row of each worksheet.
Under the hood, it uses [`sheet_to_json`](/docs/api/utilities#array-output)
to generate row objects using the headers in the first row as keys.

![pres.xlsx](pathname:///pres.png)

Assuming the file name is `pres.xlsx` and the data is stored in "Sheet1", the
following nodes will be created:

```js
[
  { Name: "Bill Clinton", Index: 42, type: "PresXlsxSheet1" },
  { Name: "GeorgeW Bush", Index: 43, type: "PresXlsxSheet1" },
  { Name: "Barack Obama", Index: 44, type: "PresXlsxSheet1" },
  { Name: "Donald Trump", Index: 45, type: "PresXlsxSheet1" },
  { Name: "Joseph Biden", Index: 46, type: "PresXlsxSheet1" },
]
```

The type is a proper casing of the file name concatenated with the sheet name.

The following query pulls the `Name` and `Index` fields from each row:

```graphql
{
  allPresXlsxSheet1 { # "all" followed by type
    edges {
      node { # each line in this block should be a field in the data
        Name
        Index
      }
    }
  }
}
```

## GatsbyJS Demo

:::note

This demo was tested on 2023 April 06 against `create-gatsby@3.8.0`. The
generated project used `gatsby@5.8.1` and `react@18.2.0`.

:::

### Project setup

1) Run `npm init gatsby -- -y sheetjs-gatsby` to create the template site.

2) Follow the on-screen instructions for starting the local development server:

```bash
cd sheetjs-gatsby
npm run develop
```

Open a web browser to the displayed URL (typically `http://localhost:8000/`)

3) Edit `package.json` and add the highlighted lines in the JSON object:

<CodeBlock language="json">{`\
{
  // highlight-start
  "overrides": {
    "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
  },
  // highlight-end
  "name": "sheetjs-gatsby",
  "version": "1.0.0",
`}
</CodeBlock>

4) Install the library and plugins:

<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm i --save gatsby-transformer-excel gatsby-source-filesystem
`}
</CodeBlock>

5) Make a `src/data` directory, download <https://sheetjs.com/pres.xlsx>, and
move the downloaded file into the new folder:

```bash
mkdir -p src/data
curl -L -o src/data/pres.xlsx https://sheetjs.com/pres.xlsx
```

6) Edit `gatsby-config.js` and add the following lines to the `plugins` array:

```js title="gatsby-config.js"
module.exports = {
  siteMetadata: {
    title: `sheetjs-gatsby`,
    siteUrl: `https://www.yourdomain.tld`,
  },
// highlight-start
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/src/data/`,
      },
    },
    `gatsby-transformer-excel`,
  ],
// highlight-end
}
```

Stop and restart the development server process (`npm run develop`).

### GraphiQL test

7) Open the GraphiQL editor at `http://localhost:8000/___graphql`.

There is an editor in the left pane.  Paste the following query into the editor:

```graphql
{
  allPresXlsxSheet1 {
    edges {
      node {
        Name
        Index
      }
    }
  }
}
```

Press the Execute Query button and data should show up in the right pane:

![GraphiQL Screenshot](pathname:///gatsby/graphiql.png)

### React page

8) Create a new file `src/pages/pres.js` that uses the query and displays the result:

```jsx title="src/pages/pres.js"
import { graphql } from "gatsby"
import * as React from "react"

export const query = graphql`query {
  allPresXlsxSheet1 {
    edges {
      node {
        Name
        Index
      }
    }
  }
}`;

const PageComponent = ({data}) => {
  return ( <pre>{JSON.stringify(data, 2, 2)}</pre> );
};
export default PageComponent;
```

After saving the file, access `http://localhost:8000/pres`.  The displayed JSON
is the data that the component receives:

```js
{
  "allPresXlsxSheet1": {
    "edges": [
      {
        "node": {
          "Name": "Bill Clinton",
          "Index": 42
        }
      },
  // ....
```

9) Change `PageComponent` to display a table based on the data:

```jsx title="src/pages/pres.js"
import { graphql } from "gatsby"
import * as React from "react"

export const query = graphql`query {
  allPresXlsxSheet1 {
    edges {
      node {
        Name
        Index
      }
    }
  }
}`;

// highlight-start
const PageComponent = ({data}) => {
  const rows = data.allPresXlsxSheet1.edges.map(r => r.node);
  return ( <table>
    <thead><tr><th>Name</th><th>Index</th></tr></thead>
    <tbody>{rows.map(row => ( <tr>
      <td>{row.Name}</td>
      <td>{row.Index}</td>
    </tr> ))}</tbody>
  </table> );
};
// highlight-end

export default PageComponent;
```

Going back to the browser, `http://localhost:8000/pres` will show a table:

![Data in Table](pathname:///gatsby/table1.png)

### Live refresh

10) Open the file `src/data/pres.xlsx` in Excel or LibreOffice or Numbers.
Add a new row at the end of the file:

![New Row in File](pathname:///gatsby/pres2.png)

Save the file and notice that the table has refreshed with the new data:

![Updated Table](pathname:///gatsby/table2.png)

### Static site

11) Stop the development server and run `npm run build`. Once the build is
finished, the display will confirm that the `/pres` route is static:

```
Pages

┌ src/pages/404.js
│ ├   /404/
│ └   /404.html
├ src/pages/index.js
│ └   /
└ src/pages/pres.js
  └   /pres/

  ╭────────────────────────────────────────────────────────────────╮
  │                                                                │
  │   (SSG) Generated at build time                                │
  │ D (DSG) Deferred static generation - page generated at runtime │
  │ ∞ (SSR) Server-side renders at runtime (uses getServerData)    │
  │ λ (Function) Gatsby function                                   │
  │                                                                │
  ╰────────────────────────────────────────────────────────────────╯
```

The built page will be placed in `public/pres/index.html`. Open the page with a
text editor and search for "SheetJS" to verify raw HTML was generated:

```html
<tr><td>SheetJS Dev</td><td>47</td></tr>
```