Recipes
Craving a happy medium between full-length tutorials and crawling the docs? Here’s a cookbook of guiding recipes on how to build things, Gatsby style.
1. Pages and Layouts
Project structure
Inside a Gatsby project, you may see some or all of the following folders and files:
|-- /.cache|-- /plugins|-- /public|-- /src |-- /pages |-- /templates |-- html.js|-- /static|-- gatsby-config.js|-- gatsby-node.js|-- gatsby-ssr.js|-- gatsby-browser.js
Some notable files and their definitions:
gatsby-config.js
— configure options for a Gatsby site, with metadata for project title, description, plugins, etc.gatsby-node.js
— implement Gatsby’s Node.js APIs to customize and extend default settings affecting the build processgatsby-browser.js
— customize and extend default settings affecting the browser, using Gatsby’s browser APIsgatsby-ssr.js
— use Gatsby’s server-side rendering APIs to customize default settings affecting server-side rendering
Additional resources
- For a tour of all the common folders and files, read the docs on Gatsby’s Project Structure
- For common commands, check out the Gatsby CLI docs
- Check out the Gatsby Cheat Sheet for downloadable info at a glance
Creating pages automatically
Gatsby core automatically turns React components in src/pages
into pages with URLs.
For example, components at src/pages/index.js
and src/pages/about.js
would automatically create pages from those filenames for the site’s index page (/
) and /about
.
Prerequisites
- A Gatsby site
- The Gatsby CLI installed
Directions
- Create a directory for
src/pages
if your site doesn’t already have one. - Add a component file to the pages directory:
import React from "react"const AboutPage = () => ( <main> <h1>About the Author</h1> <p>Welcome to my Gatsby site.</p> </main>)export default AboutPage
- Run
gatsby develop
to start the development server. - Visit your new page in the browser: http://localhost:8000/about
Additional resources
Linking between pages
Routing in Gatsby relies on the <Link />
component.
Prerequisites
- A Gatsby site with two page components:
index.js
andcontact.js
- The Gatsby
<Link />
component - The Gatsby CLI to run
gatsby develop
Directions
- Open the index page component (
src/pages/index.js
), import the<Link />
component from Gatsby, add a<Link />
component above the header, and give it ato
property with the value of"/contact/"
for the pathname:
import React from "react"import { Link } from "gatsby"export default () => ( <div style={{ color: `purple` }}> <Link to="/contact/">Contact</Link> <p>What a world.</p> </div>)
- Run
gatsby develop
and navigate to the index page. You should have a link that takes you to the contact page when clicked!
Note: Gatsby’s
<Link />
component is a wrapper around@reach/router
’s Link component. For more information about Gatsby’s<Link />
component, consult the API reference for<Link />
.
Creating a layout component
It’s common to wrap pages with a React layout component, which makes it possible to share markup, styles, and functionality across multiple pages.
Prerequisites
- A Gatsby Site
Directions
- Create a layout component in
src/components
, where child components will be passed in as props:
import React from "react"export default ({ children }) => ( <div style={{ margin: `0 auto`, maxWidth: 650, padding: `0 1rem` }}> {children} </div>)
- Import and use the layout component in a page:
import React from "react"import { Link } from "gatsby"import Layout from "../components/layout"export default () => ( <Layout> <Link to="/contact/">Contact</Link> <p>What a world.</p> </Layout>)
Additional resources
- Create a layout component in tutorial part three
- Styling with Layout Components
Creating pages programmatically with createPage
You can create pages programmatically in the gatsby-node.js
file with helper methods Gatsby provides.
Prerequisites
- A Gatsby site
- A
gatsby-node.js
file
Directions
- In
gatsby-node.js
, add an export forcreatePages
exports.createPages = ({ actions }) => { // ...}
- Destructure the
createPage
action from the available actions so it can be called by itself, and add or get data
exports.createPages = ({ actions }) => { const { createPage } = actions // pull in or use whatever data const dogData = [ { name: "Fido", breed: "Sheltie", }, { name: "Sparky", breed: "Corgi", }, ]}
- Loop through the data in
gatsby-node.js
and provide the path, template, and context (data that will be passed in the props’ pageContext) tocreatePage
for each invocation
exports.createPages = ({ actions }) => { const { createPage } = actions const dogData = [ { name: "Fido", breed: "Sheltie", }, { name: "Sparky", breed: "Corgi", }, ] dogData.forEach(dog => { createPage({ path: `/${dog.name}`, component: require.resolve(`./src/templates/dog-template.js`), context: { dog }, }) })}
- Create a React component to serve as the template for your page that was used in
createPage
import React from "react"export default ({ pageContext: { dog } }) => ( <section> {dog.name} - {dog.breed} </section>)
- Run
gatsby develop
and navigate to the path of one of the pages you created (like at http://localhost:8000/Fido) to see the data you passed it displayed on the page
Additional resources
- Tutorial section on programmatically creating pages from data
- Reference guide on using Gatsby without GraphQL
- Example repo for this recipe
2. Styling with CSS
There are so many ways to add styles to your website; Gatsby supports almost every possible option, through official and community plugins.
Using global CSS files without a Layout component
Prerequisites
- An existing Gatsby site with an index page component
- A
gatsby-browser.js
file
Directions
- Create a global CSS file as
src/styles/global.css
and paste the following into the file:
html { background-color: lavenderblush;}p { color: maroon;}
- Import the global CSS file in the
gatsby-browser.js
file such as the following:
import "./src/styles/global.css"
Note: You can also make use of
require('./src/styles/global.css')
to import the global CSS file in yourgatsby-config.js
file.
- Run
gatsby-develop
to observe the global styling being applied across your site.
Note: This approach is not the best fit if you are using CSS-in-JS for styling your site, in which case a layout page with all the shared components should be used. This is covered in the next recipe.
Additional resources
Using global styles in a layout component
Prerequisites
- A Gatsby site with an index page component
Directions
You can add global styles to a shared layout component. This component is used for things that are common throughout the site, like a header or footer.
If you don’t already have one, create a new directory in your site at
/src/components
.Inside the components directory, create two files:
layout.css
andlayout.js
.Add the following to
layout.css
:
body { background: red;}
- Edit
layout.js
to import the CSS file and output layout markup:
import React from "react"import "./layout.css"export default ({ children }) => <div>{children}</div>
- Now edit your site’s homepage at
/src/pages/index.js
and use the new layout component:
import React from "react"import Layout from "../components/layout"export default () => <Layout>Hello world!</Layout>
Additional resources
Using Styled Components
Prerequisites
- A Gatsby site with an index page component
- gatsby-plugin-styled-components, styled-components, and babel-plugin-styled-components installed in
package.json
Directions
- Inside your
gatsby-config.js
file addgatsby-plugin-styled-components
module.exports = { plugins: [`gatsby-plugin-styled-components`],}
Open the index page component (
src/pages/index.js
) and import thestyled-components
packageStyle components by creating style blocks for each element type
Apply to the page by including styled components in the JSX
import React from "react"import styled from "styled-components"const Container = styled.div` margin: 3rem auto; max-width: 600px; display: flex; flex-direction: column; align-items: center; justify-content: center;`const Avatar = styled.img` flex: 0 0 96px; width: 96px; height: 96px; margin: 0;`const Username = styled.h2` margin: 0 0 12px 0; padding: 0;`const User = props => ( <> <Avatar src={props.avatar} alt={props.username} /> <Username>{props.username}</Username> </>)export default () => ( <Container> <h1>About Styled Components</h1> <p>Styled Components is cool</p> <User username="Jane Doe" avatar="https://s3.amazonaws.com/uifaces/faces/twitter/adellecharles/128.jpg" /> <User username="Bob Smith" avatar="https://s3.amazonaws.com/uifaces/faces/twitter/vladarbatov/128.jpg" /> </Container>)
- Run
gatsby develop
to see the changes
Additional resources
Using CSS Modules
Prerequisites
- An existing Gatsby site with an index page component
Directions
- Create a CSS module as
src/pages/index.module.css
and paste the following into the module:
.feature { margin: 2rem auto; max-width: 500px;}
- Import the CSS module as a JSX object
style
in theindex.js
file by modifying the page so it looks like the following:
import React from "react"import style from "./index.module.css"export default () => ( <section className={style.feature}> <h1>Using CSS Modules</h1> </section>)
- Run
gatsby develop
to see the changes.
Note:
Notice that the file extension is .module.css
instead of .css
, which tells Gatsby that this is a CSS module.
Additional resources
Using Sass/SCSS
Sass is an extension of CSS that gives you more advanced features like nested rules, variables, mixins, and more.
Sass has 2 syntaxes. The most commonly used syntax is “SCSS”, and is a superset of CSS. That means all valid CSS syntax, is valid SCSS syntax. SCSS files use the extension .scss
Sass will compile .scss and .sass files to .css files for you, so you can write your stylesheets with more advanced features.
Prerequisites
- A Gatsby site.
Directions
- Install the Gatsby plugin gatsby-plugin-sass and
node-sass
.
npm install --save node-sass gatsby-plugin-sass
- Include the plugin in your
gatsby-config.js
file.
plugins: [`gatsby-plugin-sass`],
- Write your stylesheets as
.sass
or.scss
files and import them. If you don’t know how to import styles, take a look at Styling with CSS
$font-stack: Helvetica, sans-serif;$primary-color: #333;body { font: 100% $font-stack; color: $primary-color;}
$font-stack: Helvetica, sans-serif$primary-color: #333body font: 100% $font-stack color: $primary-color
import "./styles.scss"import "./styles.sass"
Note: You can use Sass/SCSS files as modules too, like mentioned in the previous recipe about CSS modules, with the difference that instead of .css the extensions have to be .scss or .sass
Additional resources
- Difference between .sass and .scss
- Sass guide from the official Sass website
- A more complete installation tutorial on Sass with some more explanations and more resources
Adding a Local Font
Prerequisites
- A Gatsby site
- A font file:
.woff2
,.ttf
, etc.
Directions
- Copy a font file into your Gatsby project, such as
src/fonts/fontname.woff2
.
src/fonts/fontname.woff2
- Import the font asset into a CSS file to bundle it into your Gatsby site:
@font-face { font-family: "Font Name"; src: url("../fonts/fontname.woff2");}
Note: Make sure the font name is referenced from the relevant CSS, e.g.:
body { font-family: "Font Name", sans-serif;}
By targeting the HTML body
element, your font will apply to most text on the page. Additional CSS can target other elements, such as button
or textarea
.
If fonts are not updating following steps above, make sure to replace the existing font-family in relevant CSS.
Additional resources
- More on importing assets into files
Using Emotion
Emotion is a powerful CSS-in-JS library that supports both inline CSS styles and styled components. You can use each styling feature individually or together in the same file.
Prerequisites
Directions
- Install the Gatsby Emotion plugin and Emotion packages.
npm install --save gatsby-plugin-emotion @emotion/core @emotion/styled
- Add the
gatsby-plugin-emotion
plugin to yourgatsby-config.js
file:
module.exports = { plugins: [`gatsby-plugin-emotion`],}
- If you don’t already have one, create a page in your Gatsby site at
src/pages/emotion-sample.js
.
Import Emotion’s css
core package. You can then use the css
prop to add Emotion object styles to any element inside a component:
import React from "react"import { css } from "@emotion/core"export default () => ( <div> <p css={{ background: "pink", color: "blue", }} > This page is using Emotion. </p> </div>)
- To use Emotion’s styled components, import the package and define them using the
styled
function.
import React from "react"import styled from "@emotion/styled"const Content = styled.div` text-align: center; margin-top: 10px; p { font-weight: bold; }`export default () => ( <Content> <p>This page is using Emotion.</p> </Content>)
Additional resources
Using Google Fonts
Hosting your own Google Fonts locally within a project means they won’t have to be fetched over the network when your site loads, increasing your site’s speed index by up to ~300 milliseconds on desktop and 1+ seconds on 3G. It’s also recommended to limit custom font usage to only the essential for performance.
Prerequisites
- A Gatsby site
- The Gatsby CLI installed
- Choosing a font package from the typefaces project
Directions
- Run
npm install --save typeface-your-chosen-font
, replacingyour-chosen-font
with the name of the font you want to install from the typefaces project.
An example to load the popular ‘Source Sans Pro’ font would be: npm install --save typeface-source-sans-pro
.
- Add
import "typeface-your-chosen-font"
to a layout template, page component, orgatsby-browser.js
.
import "typeface-your-chosen-font"
- Once it’s imported, you can reference the font name in a CSS stylesheet, CSS Module, or CSS-in-JS.
body { font-family: "Your Chosen Font";}
NOTE: So for the above example, the relevant CSS declaration would be font-family: 'Source Sans Pro';
Additional resources
- Typography.js - Another option for using Google fonts on a Gatsby site
- The Typefaces Project Docs
- Live example on Kyle Mathews’ blog
3. Working with starters
Starters are boilerplate Gatsby sites maintained officially, or by the community.
Using a starter
Prerequisites
- The Gatsby CLI installed
Directions
Find the starter you’d like to use. (The Starter Library is a good place to look!)
Generate a new site based on the starter. In the terminal, run:
gatsby new {your-project-name} {link-to-starter}
Don’t run the above command as-is — remember to replace {your-project-name} and {link-to-starter}!
- Run your new site:
cd {your-project-name}gatsby develop
Additional resources
- Follow a more detailed guide on using Gatsby starters.
- Learn how to use the Gatsby CLI tool to use starters in tutorial part one
- Browse the Starter Library
- Check out Gatsby’s official default starter
4. Working with themes
A Gatsby theme abstracts Gatsby configuration (shared functionality, data sourcing, design) into an installable package. This means that the configuration and functionality isn’t directly written into your project, but rather versioned, centrally managed, and installed as a dependency. You can seamlessly update a theme, compose themes together, and even swap out one compatible theme for another.
- Read more on What is a Gatsby Theme?
Creating a new site using a theme starter
Creating a site based on a starter that configures a theme follows the same process as creating a site based on a starter that doesn’t configure a theme. In this example you can use the starter for creating a new site that uses the official Gatsby blog theme.
Prerequisites
- The Gatsby CLI installed
Directions
- Generate a new site based on the blog theme starter:
gatsby new {your-project-name} https://github.com/gatsbyjs/gatsby-starter-blog-theme
- Run your new site:
cd {your-project-name}gatsby develop
Additional resources
- Learn how to use an existing Gatsby theme in the shorter conceptual guide or the more detailed step-by-step tutorial.
Building a new theme
Video hosted on egghead.io.
Prerequisites
- The Gatsby CLI installed
- Yarn installed
Directions
- Generate a new theme workspace using the Gatsby theme workspace starter:
gatsby new {your-project-name} https://github.com/gatsbyjs/gatsby-starter-theme-workspace
- Run the example site in the workspace:
yarn workspace example develop
Additional resources
- Follow a more detailed guide on using the Gatsby theme workspace starter.
- Learn how to build your own theme in the Gatsby Theme Authoring video course on Egghead, or in the video course’s complementary written tutorial companion.
5. Sourcing data
Data sourcing in Gatsby is plugin-driven; Source plugins fetch data from their source (e.g. the gatsby-source-filesystem
plugin fetches data from the file system, the gatsby-source-wordpress
plugin fetches data from the WordPress API, etc). You can also source the data yourself.
Adding data to GraphQL
Gatsby’s GraphQL data layer uses nodes to model chunks of data. Gatsby source plugins add source nodes that you can query for, but you can also create source nodes yourself. To add custom data to the GraphQL data layer yourself, Gatsby provides methods you can leverage.
This recipe shows you how to add custom data using createNode()
.
Directions
- In
gatsby-node.js
usesourceNodes()
andactions.createNode()
to create and export nodes to be able to query the data.
exports.sourceNodes = ({ actions, createNodeId, createContentDigest }) => { const pokemons = [ { name: "Pikachu", type: "electric" }, { name: "Squirtle", type: "water" }, ] pokemons.forEach(pokemon => { const node = { name: pokemon.name, type: pokemon.type, id: createNodeId(`Pokemon-${pokemon.name}`), internal: { type: "Pokemon", contentDigest: createContentDigest(pokemon), }, } actions.createNode(node) })}
Run
gatsby develop
.Note: After making changes in
gatsby-node.js
you need to re-rungatsby develop
for the changes to take effect.Query the data (in GraphiQL or in your components).
query MyPokemonQuery { allPokemon { nodes { name type id } }}
Additional resources
- Walk through an example using the
gatsby-source-filesystem
plugin in tutorial part five - Search available source plugins in the Gatsby library
- Understand source plugins by building one in the Pixabay source plugin tutorial
- The createNode function documentation
Sourcing Markdown data for blog posts and pages with GraphQL
You can source Markdown data and use Gatsby’s createPages
API to create pages dynamically.
This recipe shows how to create pages from Markdown files on your local filesystem using Gatsby’s GraphQL data layer.
Prerequisites
- A Gatsby site with a
gatsby-config.js
file - The Gatsby CLI installed
- The gatsby-source-filesystem plugin installed
- The gatsby-transformer-remark plugin installed
- A
gatsby-node.js
file
Directions
- In
gatsby-config.js
, configuregatsby-transformer-remark
along withgatsby-source-filesystem
to pull in Markdown files from a source folder. This would be in addition to any previousgatsby-source-filesystem
entries, such as for images:
module.exports = { plugins: [ `gatsby-transformer-remark`, { resolve: `gatsby-source-filesystem`, options: { name: `content`, path: `${__dirname}/src/content`, }, }, ]
- Add a Markdown post to
src/content
, including frontmatter for the title, date, and path, with some initial content for the body of the post:
---title: My First Postdate: 2019-07-10path: /my-first-post---This is my first Gatsby post written in Markdown!
- Start up the development server with
gatsby develop
, navigate to the GraphiQL explorer at http://localhost:8000/___graphql, and write a query to get all markdown data:
{ allMarkdownRemark { edges { node { frontmatter { path } } } }}
- Add the JavaScript code to generate pages from Markdown posts at build time by copying the GraphQL query into
gatsby-node.js
and looping through the results:
const path = require(`path`)exports.createPages = async ({ actions, graphql }) => { const { createPage } = actions const result = await graphql(` { allMarkdownRemark { edges { node { frontmatter { path } } } } } `) if (result.errors) { console.error(result.errors) } result.data.allMarkdownRemark.edges.forEach(({ node }) => { createPage({ path: node.frontmatter.path, component: path.resolve(`src/templates/post.js`), }) })}
- Add a post template in
src/templates
, including a GraphQL query for generating pages dynamically from Markdown content at build time:
import React from "react"import { graphql } from "gatsby"export default function Template({ data }) { const { markdownRemark } = data // data.markdownRemark holds your post data const { frontmatter, html } = markdownRemark return ( <div className="blog-post"> <h1>{frontmatter.title}</h1> <h2>{frontmatter.date}</h2> <div className="blog-post-content" dangerouslySetInnerHTML={{ __html: html }} /> </div> )}export const pageQuery = graphql` query($path: String!) { markdownRemark(frontmatter: { path: { eq: $path } }) { html frontmatter { date(formatString: "MMMM DD, YYYY") path title } } }`
- Run
gatsby develop
to restart the development server. View your post in the browser: http://localhost:8000/my-first-post
Additional resources
- Tutorial: Programmatically create pages from data
- Creating and modifying pages
- Adding Markdown pages
- Guide to creating pages from data programmatically
- Example repo for this recipe
Sourcing from WordPress
Prerequisites
- An existing Gatsby site with a
gatsby-config.js
andgatsby-node.js
file - A WordPress instance, either self-hosted or on Wordpress.com
Directions
- Install the
gatsby-source-wordpress
plugin by running the following command:
npm install gatsby-source-wordpress --save
- Configure the plugin by modifying the
gatsby-config.js
file such that it includes the following:
module.exports = { ... plugins: [ { resolve: `gatsby-source-wordpress`, options: { // baseUrl will need to be updated with your WordPress source baseUrl: `wpexample.com`, protocol: `https`, // is it hosted on wordpress.com, or self-hosted? hostingWPCOM: false, // does your site use the Advanced Custom Fields Plugin? useACF: false } }, ]}
Note: Refer to the
gatsby-source-wordpress
plugin docs to know more about configuring your plugins.
- Create a template component such as
src/templates/post.js
with the following code in it:
import React, { Component } from "react"import { graphql } from "gatsby"import PropTypes from "prop-types"class Post extends Component { render() { const post = this.props.data.wordpressPost return ( <> <h1>{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </> ) }}Post.propTypes = { data: PropTypes.object.isRequired, edges: PropTypes.array,}export default Postexport const pageQuery = graphql` query($id: String!) { wordpressPost(id: { eq: $id }) { title content } }`
- Create dynamic pages for your WordPress posts by pasting the following sample code in
gatsby-node.js
:
const path = require(`path`)const slash = require(`slash`)exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // query content for WordPress posts const result = await graphql(` query { allWordpressPost { edges { node { id slug } } } } `) const postTemplate = path.resolve(`./src/templates/post.js`) result.data.allWordpressPost.edges.forEach(edge => { createPage({ // `path` will be the url for the page path: edge.node.slug, // specify the component template of your choice component: slash(postTemplate), // In the ^template's GraphQL query, 'id' will be available // as a GraphQL variable to query for this posts's data. context: { id: edge.node.id, }, }) })}
Run
gatsby-develop
to see the newly generated pages and navigate through them.Open the
GraphiQL IDE
atlocalhost:8000/__graphql
and open the Docs or Explorer to observe the queryable fields forallWordpressPosts
.
The dynamic pages created above in gatsby-node.js
have unique paths for navigating to particular posts, using a template component for the posts and a sample GraphQL query to source WordPress post content.
Additional resources
- Getting Started with WordPress and Gatsby
- More on Sourcing from WordPress
- Live example on Sourcing from WordPress
Sourcing data from Contentful
Prerequisites
- A Gatsby site
- A Contentful account
- The Contentful CLI installed
Directions
- Log in to Contentful with the CLI and follow the steps. It will help you create an account if you don’t have one.
contentful login
- Create a new space if you don’t already have one. Make sure to save the space ID given to you at the end of the command. If you already have a Contentful space and space ID, you can skip steps 2 and 3.
Note: for new accounts, you can overwrite the default onboarding space. Check to see the spaces included with your account.
contentful space create --name 'Gatsby example'
- Seed the new space with example blog content using the new space ID returned from the previous command, in place of
<space ID>
.
contentful space seed -s '<space ID>' -t blog
For example, with a space ID in place: contentful space seed -s '22fzx88spbp7' -t blog
- Create a new access token for your space. Remember this token, as you will need it in step 6.
contentful space accesstoken create -s '<space ID>' --name 'Example token'
- Install the
gatsby-source-contentful
plugin in your Gatsby site:
npm install --save gatsby-source-contentful
- Edit the file
gatsby-config.js
and add thegatsby-source-contentful
to theplugins
array to enable the plugin. You should strongly consider using environment variables to store your space ID and token for security purposes.
plugins: [ // add to array along with any other installed plugins { resolve: `gatsby-source-contentful`, options: { spaceId: `<space ID>`, // or process.env.CONTENTFUL_SPACE_ID accessToken: `<access token>`, // or process.env.CONTENTFUL_TOKEN }, },],
Run
gatsby develop
and make sure the site compiled successfully.Query data with the GraphiQL editor at https://localhost:8000/___graphql. The Contentful plugin adds several new node types to your site, including every content type in your Contentful website. Your example space with a “Blog Post” content type produces a
allContentfulBlogPost
node type in GraphQL.
To query for Blog Post titles from Contentful, use the following GraphQL query:
{ allContentfulBlogPost { edges { node { title } } }}
Contentful nodes also include several metadata fields like createdAt
or node_locale
.
- To show a list of links to the blog posts, create a new file in
/src/pages/blog.js
. This page will display all posts, sorted by updated date.
import React from "react"import { graphql, Link } from "gatsby"const BlogPage = ({ data }) => ( <div> <h1>Blog</h1> <ul> {data.allContentfulBlogPost.edges.map(({ node, index }) => ( <li key={index}> <Link to={`/blog/${node.slug}`}>{node.title}</Link> </li> ))} </ul> </div>)export default BlogPageexport const query = graphql` { allContentfulBlogPost(sort: { fields: [updatedAt] }) { edges { node { title slug } } } }`
To continue building out your Contentful site including post detail pages, check out the rest of the Gatsby docs and additional resources below.
Additional resources
- Building a Site with React and Contentful
- More on Sourcing from Contentful
- Contentful source plugin
- Long-text field types returned as objects
- Example repository for this recipe
Pulling data from an external source and creating pages without GraphQL
You don’t have to use the GraphQL data layer to include data in pages, though there are reasons why you should consider GraphQL. You can use the node createPages
API to pull unstructured data directly into Gatsby sites rather than through GraphQL and source plugins.
In this recipe, you’ll create dynamic pages from data fetched from the PokéAPI’s REST endpoints. The full example can be found on GitHub.
Prerequisites
- A Gatsby Site with a
gatsby-node.js
file - The Gatsby CLI installed
- The axios package installed through npm
Directions
- In
gatsby-node.js
, add the JavaScript code to fetch data from the PokéAPI and programmatically create an index page:
const axios = require("axios")const get = endpoint => axios.get(`https://pokeapi.co/api/v2${endpoint}`)const getPokemonData = names => Promise.all( names.map(async name => { const { data: pokemon } = await get(`/pokemon/${name}`) return { ...pokemon } }) )exports.createPages = async ({ actions: { createPage } }) => { const allPokemon = await getPokemonData(["pikachu", "charizard", "squirtle"]) // Create a page that lists Pokémon. createPage({ path: `/`, component: require.resolve("./src/templates/all-pokemon.js"), context: { allPokemon }, })}
- Create a template to display Pokémon on the homepage:
import React from "react"export default ({ pageContext: { allPokemon } }) => ( <div> <h1>Behold, the Pokémon!</h1> <ul> {allPokemon.map(pokemon => ( <li key={pokemon.id}> <img src={pokemon.sprites.front_default} alt={pokemon.name} /> <p>{pokemon.name}</p> </li> ))} </ul> </div>)
- Run
gatsby develop
to fetch the data, build pages, and start the development server. - View your homepage in a browser: http://localhost:8000
Additional resources
- Full Pokemon data repo
- More on using unstructured data in Using Gatsby without GraphQL
- When and how to query data with GraphQL for more complex Gatsby sites
Sourcing content from Drupal
Prerequisites
- A Gatsby site
- A Drupal site
- The JSON:API module installed and enabled on the Drupal site
Directions
- Install the
gatsby-source-drupal
plugin.
npm install --save gatsby-source-drupal
- Edit your
gatsby-config.js
file to enable the plugin and configure it.
module.exports = { plugins: [ { resolve: `gatsby-source-drupal`, options: { baseUrl: `https://your-website/`, apiBase: `api`, // optional, defaults to `jsonapi` }, }, ],}
- Start the development server with
gatsby develop
, and open the GraphiQL explorer at http://localhost:8000/___graphql. Under the Explorer tab, you should see new node types, such asallBlockBlock
for Drupal blocks, and one for every content type in your Drupal site. For example, if you have a “Page” content type, it will be available asallNodePage
. To query all “Page” nodes for their title and body, use a query like:
{ allNodePage { edges { node { title body { value } } } }}
- To use your Drupal data, create a new page in your Gatsby site at
src/pages/drupal.js
. This page will list all Drupal “Page” nodes.
Note: the exact GraphQL schema will depend on your how Drupal instance is structured.
import React from "react"import { graphql } from "gatsby"const DrupalPage = ({ data }) => ( <div> <h1>Drupal pages</h1> <ul> {data.allNodePage.edges.map(({ node, index }) => ( <li key={index}> <h2>{node.title}</h2> <div> {node.body.value} </div> </li> ))} </ul> </div>)export default DrupalPageexport const query = graphql` { allNodePage { edges { node { title body { value } } } }}
- With the development server running, you can view the new page by visiting http://localhost:8000/drupal.
Additional Resources
- Using Decoupled Drupal with Gatsby
- More on sourcing from Drupal
- Tutorial: Programmatically create pages from data
6. Querying data
Querying data with a Page Query
You can use the graphql
tag to query data in the pages of your Gatsby site. This gives you access to anything included in Gatsby’s data layer, such as site metadata, source plugins, images, and more.
Directions
Import
graphql
fromgatsby
.Export a constant named
query
and set its value to be agraphql
template with the query between two backticks.Pass in
data
as a prop to the component.The
data
variable holds the queried data and can be referenced in JSX to output HTML.
import React from "react"import { graphql } from "gatsby"import Layout from "../components/layout"export const query = graphql` query HomePageQuery { site { siteMetadata { title } } }`const IndexPage = ({ data }) => ( <Layout> <h1>{data.site.siteMetadata.title}</h1> </Layout>)export default IndexPage
Additional resources
- GraphQL and Gatsby: understanding the expected shape of your data
- More on querying data in pages with GraphQL
- MDN on Tagged Template Literals like the ones used in GraphQL
Querying data with the StaticQuery Component
StaticQuery
is a component for retrieving data from Gatsby’s data layer in non-page components, such as a header, navigation, or any other child component.
Directions
- The
StaticQuery
Component requires two render props:query
andrender
.
import React from "react"import { StaticQuery, graphql } from "gatsby"const NonPageComponent = () => ( <StaticQuery query={graphql` query NonPageQuery { site { siteMetadata { title } } } `} render={( data ) => ( <h1> Querying title from NonPageComponent with StaticQuery: {data.site.siteMetadata.title} </h1> )} />)export default NonPageComponent
- You can now use this component as you would any other component by importing it into a larger page of JSX components and HTML markup.
Querying data with the useStaticQuery hook
Since Gatsby v2.1.0, you can use the useStaticQuery
hook to query data with a JavaScript function instead of a component. The syntax removes the need for a <StaticQuery>
component to wrap everything, which some people find simpler to write.
The useStaticQuery
hook takes a GraphQL query and returns the requested data. It can be stored in a variable and used later in your JSX templates.
Prerequisites
- You’ll need React and ReactDOM 16.8.0 or later (keeping Gatsby updated handles this)
- Recommended reading: the Rules of React Hooks
Directions
Import
useStaticQuery
andgraphql
fromgatsby
in order to use the hook query the data.In the start of a stateless functional component, assign a variable to the value of
useStaticQuery
with yourgraphql
query passed as an argument.In the JSX code returned from your component, you can reference that variable to handle the returned data.
import React from "react"import { useStaticQuery, graphql } from "gatsby"const NonPageComponent = () => { const data = useStaticQuery(graphql` query NonPageQuery { site { siteMetadata { title } } } `) return ( <h1> Querying title from NonPageComponent: {data.site.siteMetadata.title}{" "} </h1> )}export default NonPageComponent
Additional resources
- More on Static Query for querying data in components
- The difference between a static query and a page query
- More on the useStaticQuery hook
- Visualize your data with GraphiQL
Limiting with GraphQL
When querying for data with GraphQL, you can limit the number of results returned with a specific number. This is helpful if you only need a few pieces of data or need to paginate data.
To limit data, you’ll need a Gatsby site with some nodes in the GraphQL data layer. All sites have some nodes like allSitePage
and sitePage
created automatically: more can be added by installing source plugins like gatsby-source-filesystem
in gatsby-config.js
.
Prerequisites
Directions
- Run
gatsby develop
to start the development server. - Open a tab in your browser at: http://localhost:8000/___graphql.
- Add a query in the editor with the following fields on
allSitePage
to start off:
{ allSitePage { edges { node { id path } } }}
- Add a
limit
argument to theallSitePage
field and give it an integer value3
.
{ allSitePage(limit: 3) { edges { node { id path } } }}
- Click the play button in the GraphiQL page and the data in the
edges
field will be limited to the number specified.
Additional resources
- Learn about nodes in Gatsby’s GraphQL data API
- Gatsby GraphQL reference for limiting
- Live example:
Sorting with GraphQL
The ordering of your results can be specified with the GraphQL sort
argument. You can specify which fields to sort by and the order to sort in.
For this recipe, you’ll need a Gatsby site with a collection of nodes to sort in the GraphQL data layer. All sites have some nodes like allSitePage
created automatically: more can be added by installing source plugins.
Prerequisites
- A Gatsby site
- Queryable fields prefixed with
all
, e.g.allSitePage
Directions
- Run
gatsby develop
to start the development server. - Open the GraphiQL explorer in a browser tab at: http://localhost:8000/___graphql
- Add a query in the editor with the following fields on
allSitePage
to start off:
{ allSitePage { edges { node { id path } } }}
- Add a
sort
argument to theallSitePage
field and give it an object with thefields
andorder
attributes. The value forfields
can be a field or an array of fields to sort by (this example uses thepath
field), theorder
can be eitherASC
orDESC
for ascending and descending respectively.
{ allSitePage(sort: {fields: path, order: ASC}) { edges { node { id path } } }}
- Click the play button in the GraphiQL page and the data returned will be sorted ascending by the
path
field.
Additional resources
- Gatsby GraphQL reference for sorting
- Learn about nodes in Gatsby’s GraphQL data API
- Live example:
Filtering with GraphQL
Queried results can be filtered down with operators like eq
(equals), ne
(not equals), in
, and regex
on specified fields.
For this recipe, you’ll need a Gatsby site with a collection of nodes to filter in the GraphQL data layer. All sites have some nodes like allSitePage
created automatically: more can be added by installing source and transformer plugins like gatsby-source-filesystem
and gatsby-transformer-remark
in gatsby-config.js
to produce allMarkdownRemark
.
Prerequisites
- A Gatsby site
- Queryable fields prefixed with
all
, e.g.allSitePage
orallMarkdownRemark
Directions
- Run
gatsby develop
to start the development server. - Open the GraphiQL explorer in a browser tab at: http://localhost:8000/___graphql
- Add a query in the editor using a field prefixed by ‘all’, like
allMarkdownRemark
(meaning that it will return a list of nodes)
{ allMarkdownRemark { edges { node { frontmatter { title categories } } } }}
- Add a
filter
argument to theallMarkdownRemark
field and give it an object with the fields you’d like to filter by. In this example, Markdown content is filtered by thecategories
attribute in frontmatter metadata. The next value is the operator: in this caseeq
, or equals, with a value of ‘magical creatures’.
{ allMarkdownRemark(filter: {frontmatter: {categories: {eq: "magical creatures"}}}) { edges { node { frontmatter { title categories } } } }}
- Click the play button in the GraphiQL page. The data that matches the filter parameters should be returned, in this case only sourced Markdown files tagged with a category of ‘magical creatures’.
Additional resources
- Gatsby GraphQL reference for filtering
- Complete list of possible operators
- Learn about nodes in Gatsby’s GraphQL data API
- Live example:
GraphQL Query Aliases
You can rename any field in a GraphQL query with an alias.
If you would like to run two queries on the same datasource, you can use an alias to avoid a naming collision with two queries of the same name.
Directions
- Run
gatsby develop
to start the development server. - Open the GraphiQL explorer in a browser tab at: http://localhost:8000/___graphql
- Add a query in the editor using two fields of the same name like
allFile
{ allFile { totalCount } allFile { pageInfo { currentPage } }}
- Add the name you would like to use for any field before the name of the field in your GraphQL schema, separated by a colon. (E.g.
[alias-name]: [original-name]
)
{ fileCount: allFile { totalCount } filePageInfo: allFile { pageInfo { currentPage } }}
- Click the play button in the GraphiQL page and 2 objects with alias names you provided should be output.
Additional resources
- Gatsby GraphQL reference for aliasing
- Live example:
GraphQL Query Fragments
GraphQL fragments are shareable chunks of a query that can be reused.
You might want to use them to share multiple fields between queries or to colocate a component with the data it uses.
Directions
- Declare a
graphql
template string with a Fragment in it. The fragment should be made up of the keywordfragment
, a name, the GraphQL type it is associated with (in this case of typeSite
, as demonstrated byon Site
), and the fields that make up the fragment:
export const query = graphql` fragment SiteInformation on Site { title description }`
- Now, include the fragment in a query for a field of the type specified by the fragment. This includes those fields without having to declare them all independently:
export const pageQuery = graphql` query SiteQuery { site {- title- description+ ...SiteInformation } }`
Note: Fragments don’t need to be imported in Gatsby. Exporting a query with a Fragment makes that Fragment available in all queries in your project.
Fragments can be nested inside other fragments, and multiple fragments can be used in the same query.
Additional resources
- Simple example repo using fragments
- Gatsby GraphQL reference for fragments
- Gatsby image fragments
- Example repo with co-located data
7. Working with images
Import an image into a component with webpack
Images can be imported right into a JavaScript module with webpack. This process automatically minifies and copies the image to your site’s public
folder, providing a dynamic image URL for you to pass to an HTML <img>
element like a regular file path.
Video hosted on egghead.io.
Prerequisites
- A Gatsby Site with a
.js
file exporting a React component - an image (
.jpg
,.png
,.gif
,.svg
, etc.) in thesrc
folder
Directions
- Import your file from its path in the
src
folder:
import React from "react"// Tell webpack this JS file uses this imageimport FiestaImg from "../assets/fiesta.jpg"
- In
index.js
, add an<img>
tag with thesrc
as the name of the import you used from webpack (in this caseFiestaImg
), and add analt
attribute describing the image:
import React from "react"import FiestaImg from "../assets/fiesta.jpg"export default () => ( // The import result is the URL of your image <img src={FiestaImg} alt="A dog smiling in a party hat" />)
- Run
gatsby develop
to start the development server. - View your image in the browser: http://localhost:8000/
Additional resources
Reference an image from the static
folder
As an alternative to importing assets with webpack, the static
folder allows access to content that gets automatically copied into the public
folder when built.
This is an escape route for specific use cases, and other methods like importing with webpack are recommended to leverage optimizations made by Gatsby.
Video hosted on egghead.io.
Prerequisites
- A Gatsby Site with a
.js
file exporting a React component - An image (
.jpg
,.png
,.gif
,.svg
, etc.) in thestatic
folder
Directions
- Ensure that the image is in your
static
folder at the root of the project. Your project structure might look something like this:
├── gatsby-config.js├── src│ └── pages│ └── index.js├── static│ └── fiesta.jpg
- In
index.js
, add an<img>
tag with thesrc
as the relative path of the file from thestatic
folder, and add analt
attribute describing the image:
import React from "react"export default () => ( <img src={`fiesta.jpg`} alt="A dog smiling in a party hat" />)
- Run
gatsby develop
to start the development server. - View your image in the browser: http://localhost:8000/
Additional resources
- Example repo referencing an image from the static folder
- Using the Static Folder
- More on all image techniques in Gatsby
Optimizing and querying local images with gatsby-image
The gatsby-image
plugin can relieve much of the pain associated with optimizing images in your site.
Gatsby will generate optimized resources which can be queried with GraphQL and passed into Gatsby’s image component. This takes care of the heavy lifting including creating several image sizes and loading them at the right time.
Prerequisites
- The
gatsby-image
,gatsby-transformer-sharp
, andgatsby-plugin-sharp
packages installed and added to the plugins array ingatsby-config
- Images sourced in your
gatsby-config
using a plugin likegatsby-source-filesystem
Directions
- First, import
Img
fromgatsby-image
, as well asgraphql
anduseStaticQuery
fromgatsby
import { useStaticQuery, graphql } from "gatsby" // to query for image dataimport Img from "gatsby-image" // to take image data and render it
- Write a query to get image data, and pass the data into the
<Img />
component:
Choose any of the following options or a combination of them.
a. a single image queried by its file path (Example: images/corgi.jpg
)
const data = useStaticQuery(graphql` query { file(relativePath: { eq: "corgi.jpg" }) { childImageSharp { fluid { base64 aspectRatio src srcSet sizes } } } }`)return ( <Img fluid={data.file.childImageSharp.fluid} alt="A corgi smiling happily" />)
b. using a GraphQL fragment, to query for the necessary fields more tersely
const data = useStaticQuery(graphql` query { file(relativePath: { eq: "corgi.jpg" }) { childImageSharp { fluid { ...GatsbyImageSharpFluid } } } }`)return ( <Img fluid={data.file.childImageSharp.fluid} alt="A corgi smiling happily" />)
c. several images from a directory (Example: images/dogs
) filtered by the extension
and relativeDirectory
fields, and then mapped into Img
components
const data = useStaticQuery(graphql` query { allFile( filter: { extension: { regex: "/(jpg)|(png)|(jpeg)/" } relativeDirectory: { eq: "dogs" } } ) { edges { node { base childImageSharp { fluid { ...GatsbyImageSharpFluid } } } } } }`)return ( <div> {data.allFile.edges.map(image => ( <Img fluid={image.node.childImageSharp.fluid} alt={image.node.base.split(".")[0]} // only use section of the file extension with the filename /> ))} </div>)
Note: This method can make it difficult to match images with alt
text for accessibility. This example uses images with alt
text included in the filename, like dog in a party hat.jpg
.
d. an image of a fixed size using the fixed
field instead of fluid
const data = useStaticQuery(graphql` query { file(relativePath: { eq: "corgi.jpg" }) { childImageSharp { fixed(width: 250, height: 250) { ...GatsbyImageSharpFixed } } } }`)return ( <Img fixed={data.file.childImageSharp.fixed} alt="A corgi smiling happily" />)
e. an image of a fixed size with a maxWidth
const data = useStaticQuery(graphql` query { file(relativePath: { eq: "corgi.jpg" }) { childImageSharp { fixed(maxWidth: 250) { ...GatsbyImageSharpFixed } } } }`)return ( <Img fixed={data.file.childImageSharp.fixed} alt="A corgi smiling happily" />)
f. an image filling a fluid container with a max width (in pixels) and a higher quality (the default value is 50 i.e. 50%)
const data = useStaticQuery(graphql` query { file(relativePath: { eq: "corgi.jpg" }) { childImageSharp { fluid(maxWidth: 800, quality: 75) { ...GatsbyImageSharpFluid } } } }`)return ( <Img fluid={data.file.childImageSharp.fluid} alt="A corgi smiling happily" />)
- (Optional) Add inline styles to the
<Img />
like you would to other components
<Img fluid={data.file.childImageSharp.fluid} alt="A corgi smiling happily" style={{ border: "2px solid rebeccapurple", borderRadius: 5, height: 250 }}/>
- (Optional) Force an image into a desired aspect ratio by overriding the
aspectRatio
field returned by the GraphQL query before it is passed into the<Img />
component
<Img fluid={{ ...data.file.childImageSharp.fluid, aspectRatio: 1.6, // 1280 / 800 = 1.6 }} alt="A corgi smiling happily"/>
- Run
gatsby develop
, to generate images from files in the filesystem (if not done already) and cache them
Additional resources
- Example repository illustrating these examples
- Gatsby Image API
- Using Gatsby Image
- More on working with images in Gatsby
- Free egghead.io videos explaining these steps
Optimizing and querying images in post frontmatter with gatsby-image
For use cases like a featured image in a blog post, you can still use gatsby-image
. The Img
component needs processed image data, which can come from a local (or remote) file, including from a URL in the frontmatter of a .md
or .mdx
file.
To inline images in markdown (using the ![]()
syntax), consider using a plugin like gatsby-remark-images
Prerequisites
- The
gatsby-image
,gatsby-transformer-sharp
, andgatsby-plugin-sharp
packages installed and added to the plugins array ingatsby-config
- Images sourced in your
gatsby-config
using a plugin likegatsby-source-filesystem
- Markdown files sourced in your
gatsby-config
with image URLs in frontmatter - Pages created from Markdown using
createPages
Directions
- Verify that the Markdown file has an image URL with a valid path to an image file in your project
---title: My First PostfeaturedImage: ./corgi.png---Post content...
- Verify that a unique identifier (a slug in this example) is passed in context when
createPages
is called ingatsby-node.js
, which will later be passed into a GraphQL query in the Layout component
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // query for all markdown result.data.allMdx.edges.forEach(({ node }) => { createPage({ path: node.fields.slug, component: path.resolve(`./src/components/markdown-layout.js`), context: { slug: node.fields.slug, }, }) })}
- Now, import
Img
fromgatsby-image
, andgraphql
fromgatsby
into the template component, write a pageQuery to get image data based on the passed inslug
and pass that data to the<Img />
component:
import React from "react"import { graphql } from "gatsby"import Img from "gatsby-image"export default ({ children, data }) => ( <main> <Img fluid={data.markdown.frontmatter.image.childImageSharp.fluid} alt="A corgi smiling happily" /> {children} </main>)export const pageQuery = graphql` query PostQuery($slug: String) { markdown: mdx(fields: { slug: { eq: $slug } }) { id frontmatter { image { childImageSharp { fluid { ...GatsbyImageSharpFluid } } } } } }`
- Run
gatsby develop
, which will generate images for files sourced in the filesystem
Additional resources
- Example repository using this recipe
- Featured images with frontmatter
- Gatsby Image API
- Using Gatsby Image
- More on working with images in Gatsby
8. Transforming data
Transforming data in Gatsby is plugin-driven. Transformer plugins take data fetched using source plugins, and process it into something more usable (e.g. JSON into JavaScript objects, and more).
Transforming Markdown into HTML
The gatsby-transformer-remark
plugin can transform Markdown files to HTML.
Prerequisites
- A Gatsby site with
gatsby-config.js
and anindex.js
page - A Markdown file saved in your Gatsby site
src
directory - A source plugin installed, such as
gatsby-source-filesystem
- The
gatsby-transformer-remark
plugin installed
Directions
- Add the transformer plugin in your
gatsby-config.js
:
plugins: [ // not shown: gatsby-source-filesystem for creating nodes to transform `gatsby-transformer-remark`],
- Add a GraphQL query to the
index.js
file of your Gatsby site to fetchMarkdownRemark
nodes:
export const query = graphql` query { allMarkdownRemark { totalCount edges { node { id frontmatter { title date(formatString: "DD MMMM, YYYY") } excerpt } } } }`
- Restart the development server and open GraphiQL at http://localhost:8000/___graphql. Explore the fields available on the
MarkdownRemark
node.
Additional resources
- Tutorial on transforming Markdown to HTML using
gatsby-transformer-remark
- Browse available transformer plugins in the Gatsby plugin library
9. Deploying your site
Showtime. Once you are happy with your site, you are ready to go live with it!
Preparing for deployment
Prerequisites
- A Gatsby site
- The Gatsby CLI installed
Directions
Stop your development server if it is running (
Ctrl + C
on your command line in most cases)For the standard site path at the root directory (
/
), rungatsby build
using the Gatsby CLI on the command line. The built files will now be in thepublic
folder.
gatsby build
- To include a site path other than
/
(such as/site-name/
), set a path prefix by adding the following to yourgatsby-config.js
and replacingyourpathprefix
with your desired path prefix:
module.exports = { pathPrefix: `/yourpathprefix`,}
There are a few reasons to do this — for instance, hosting a blog built with Gatsby on a domain with another site not built on Gatsby. The main site would direct to example.com
, and the Gatsby site with a path prefix could live at example.com/blog
.
- With a path prefix set in
gatsby-config.js
, rungatsby build
with the--prefix-paths
flag to automatically add the prefix to the beginning of all Gatsby site URLs and<Link>
tags.
gatsby build --prefix-paths
- Make sure that your site looks the same when running
gatsby build
as withgatsby develop
. By runninggatsby serve
when you build your site, you can test out (and debug if necessary) the finished product before deploying it live.
gatsby build && gatsby serve
Additional resources
- Walk through building and deploying an example site in tutorial part one
- Learn about performance optimization
- Read about other deployment related topics
- Check out the deployment docs for specific hosting platforms and how to deploy to them
Deploying to Netlify
Use netlify-cli
to deploy your Gatsby application without leaving the command-line interface.
Prerequisites
- A Gatsby site with a single component
index.js
- The netlify-cli package installed
- The Gatsby CLI installed
Directions
Build your gatsby application using
gatsby build
Login into Netlify using
netlify login
Run the command
netlify init
. Select the “Create & configure a new site” option.Choose a custom website name if you want or press enter to receive a random one.
Choose your Team.
Change the deploy path to
public/
Make sure that everything looks fine before deploying to production using
netlify deploy --prod
Additional resources
Deploying to ZEIT Now
Use Now CLI to deploy your Gatsby application without leaving the command-line interface.
Prerequisites
- A ZEIT Now account
- A Gatsby site with a single component
index.js
- Now CLI package installed
- Gatsby CLI installed
Directions
Login into Now CLI using
now login
Change to the directory of your Gatsby.js application in the Terminal if you aren’t already there
Run
now
to deploy it
Additional resources
Edit this page on GitHub