Static websites have made a comeback in recent years thanks to their speed, security, and simplicity. One of the leading tools for building static sites today is Gatsby, a blazing-fast Static Site Generator (SSG).
Whether you’re a web developer looking to create a personal blog, a portfolio site, or a business website, Gatsby can help you achieve your goals. This comprehensive guide takes you through the process of building static sites with Gatsby. It covers everything from the basics to advanced topics.
Understanding Static Sites
Static sites are web pages containing pre-rendered HTML, CSS, and JavaScript files. Unlike dynamic websites, they don’t rely on server-side processing for each request. Instead, all the content is generated ahead of time and served directly to the user’s browser. This approach offers several advantages:
- Speed: Static sites load quickly since there’s no server-side processing.
- Security: With no server-side code execution, static sites are less vulnerable to security threats.
- Scalability: It’s easy to cache and distribute static sites through Content Delivery Networks (CDNs).
- Simplicity: They are easier to develop, deploy, and maintain.
Now that you understand what static sites are and their benefits let’s dive into Gatsby.
What Is Gatsby?
Gatsby is an open-source framework based on the React JavaScript library that simplifies the process of building static websites. It combines the power of React components with GraphQL for data management, making it an excellent choice for developers of all levels. Here’s why Gatsby stands out:
- Blazingly Fast: Gatsby optimizes your site for speed using techniques like code splitting and lazy loading, resulting in near-instantaneous page loads.
- Flexible Data Sourcing: It can source data from various places, including Markdown files, APIs, and databases.
- Rich Plugin Ecosystem: Gatsby’s extensive plugin ecosystem allows you to extend its functionality effortlessly.
- SEO and Performance: Gatsby automatically generates optimized HTML for better SEO and performance.
Getting Started With Gatsby
To follow along with this guide, you should have:
- Fundamental understanding of HTML, CSS, and JavaScript
- Basic knowledge of React
- Node.js and npm (Node Package Manager) or yarn installed on your computer
To get started with Gatsby and create a project, you can use one of the many examples in the Gatsby Starter Library or create a project from scratch.
For this guide, let’s use the official hello world starter for GatsbyJS as it gives us a plain project with no plugins or extra files.
- First, install the Gatsby CLI on your computer by running the following command:
npm install -g gatsby-cli
Run gatsby --version
to verify if the installation is successful.
- Next, navigate into the folder you wish to create your project and run the following command:
npx gatsby new <project-name> https://github.com/gatsbyjs/gatsby-starter-hello-world
Change <project-name>
above to the preferred name for your project.
- Once this is successful, navigate into the project folder and start the development server:
cd <project-name>
gatsby develop
The local development server will start at http://localhost:8000, where you can access your Gatsby site.
Understanding Gatsby File Structure
When you open your project in a code editor, you will see the following structure:
/
|-- /public
|-- /src
|-- /pages
|-- index.js
|-- /static
|-- gatsby-config.js
- /public: This directory contains the output of your Gatsby build process. It’s where the generated HTML, CSS, JavaScript, and other assets reside.
- /src: This is the heart of your Gatsby project, where you’ll spend most of your time. It contains various subdirectories and files:
- /pages: This is where all pages for your project are stored. Each JavaScript file here corresponds to a route on your website.
- /static: This directory is used for static files that you want to include in your site, such as images, fonts, or downloadable files. These files are served as-is and won’t be processed by Gatsby.
- gatsby-config.js: This configuration file is where you define various settings for your Gatsby site. You can specify plugins, site metadata, and other configurations here.
Creating Pages and Components
In Gatsby, building web pages is a straightforward process. Any JavaScript file you create within the /src/pages folder automatically becomes a page with its corresponding route, thanks to Gatsby’s automatic page generation.
You can create as many pages as you need for your website by adding more JavaScript files to the /src/pages folder. For example, you can create an about.js file for an “About” page.
While you can create individual JavaScript files for each page directly in the /src/pages folder, it’s also possible to organize your pages further. You can create subfolders to group related pages. For instance, you might create a blog folder to organize all your blog-related pages.
For this project, this is what the page structure will look like:
|-- /src
|-- /pages
|-- about.js
|-- index.js
|-- /blog
|-- index.js
Utilizing JSX for Pages
Since Gatsby is built on top of React, its pages and components are written in JSX (JavaScript XML). JSX is a syntax extension for JavaScript that allows you to define the structure and layout of your user interfaces in a highly readable and expressive manner.
For instance, you can create the content for your Home page (index.js) like this:
import React from 'react';
export default function Home() {
return (
<>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
</div>
</>
);
}
Linking Pages in Gatsby
To create a link to another page, you can use the Link
component as follows:
import React from 'react';
import { Link } from 'gatsby';
export default function Home() {
return (
<>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<Link> to="/about">About Us</Link>
<Link> to="/blog">Blog</Link>
</div>
</>
);
}
In the example above, we’ve imported the Link
component from gatsby
and used it to create links to the “About Us” page and a blog. The “About Us” page, for example, has the route /about
. When users click on the “About Us” link, they will be taken to the /about
page.
To create links to external websites, you can use regular anchor (<a>
) tags with the href
attribute:
import React from 'react';
export default function Home() {
return (
<>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<a href="https://kinsta.com/docs/static-site-hosting/" target="_blank" rel="noreferrer">
<div>Read more</div>
</a>
</div>
</div>
</>
);
}
In this case, the link opens the external website in a new browser tab due to the target="_blank"
and rel="noreferrer"
attributes.
Creating Components in Gatsby
Gatsby’s component-based architecture allows you to create reusable building blocks for your web pages. Instead of duplicating code across multiple pages, you can encapsulate common elements into components, making your codebase more organized, maintainable, and efficient.
Suppose your Homepage’s code includes the navigation section, main content, and a footer:
import React from 'react';
import { Link } from 'gatsby';
export default function Home() {
return (
<>
<div className="nav-links">
<Link> to="/">Home</Link>
<Link> to="/about">About</Link>
<Link> to="/blog">Blog</Link>
</div>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<a href="https://kinsta.com/docs/static-site-hosting/">
<div>Read more</div>
</a>
</div>
<div className="footer">
<p>
Hosted with ❤️ by Kinsta's{' '}
<a> href="https://kinsta.com/static-site-hosting">
Static Site Hosting
</a>
.
</p>
</div>
</>
);
}
Imagine having to duplicate the navbar and footer code for every page on your site. This is where the power of components comes into play. You can create reusable components for the navbar, footer, and every piece of code that would be repeated across multiple pages and components.
To work with components in Gatsby, create a components folder in the src folder to store all components. Next, create your components, e.g. Navbar.js and Footer.js. In the Navbar.js file, separate the code this way:
import { Link } from 'gatsby';
import React from 'react';
const Navbar = () => {
return (
<nav>
<div className="nav-links">
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/blog">Blog</Link>
</div>
</nav>
);
};
export default Navbar;
And also your Footer.js:
import React from 'react';
const Footer = () => {
return (
<div className="footer">
<p>
Hosted with ❤️ by Kinsta's{' '}
<a> href="https://kinsta.com/static-site-hosting">Static Site Hosting</a>
.
</p>
</div>
);
};
export default Footer;
Next, import your components files into your pages or components and use this way:
import React from 'react';
import Navbar from '../components/Navbar';
import Footer from '../components/Footer';
export default function Home() {
return (
<>
<Navbar />
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<a href="https://kinsta.com/docs/static-site-hosting/">
<div>Read more</div>
</a>
</div>
<Footer />
</>
);
}
Creating Layout Component
A common practice in web development is to create a layout component that encapsulates the overall structure of your site. The layout component typically includes elements that appear on every page, such as headers, footers, navigation menus, and sidebars.
Create a new file called Layout.js in your /src/components folder. Next, define the layout structure. For this guide, the layout structure will only include the navbar and footer:
import React from 'react';
import Navbar from './Navbar';
import Footer from './Footer';
const Layout = ({ children }) => {
return (
<div className="layout">
<Navbar />
<div> className="content">{children}</div>
<Footer />
</div>
);
};
export default Layout;
In this layout component, we use the components to wrap the page content (provided as children
). To use the layout component in your pages, import it and wrap your page content with it. For example, in your index.js page:
import React from 'react';
import Layout from '../components/Layout';
export default function Home() {
return (
<Layout>
<div>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<a href="https://kinsta.com/docs/static-site-hosting/">
<div>Read more</div>
</a>
</div>
</Layout>
);
}
By using a layout component, you ensure a consistent structure and appearance across all your pages while keeping your code organized and maintainable. It’s a powerful way to manage the common elements of your site efficiently.
Styling Pages and Components In Gatsby
Styling your Gatsby site is flexible and allows you to use various approaches, including plain CSS, CSS-in-JS, or CSS preprocessors like Sass. Let’s learn how to create normal and module styling for pages.
CSS Styling
In Gatsby, you can easily create a CSS file and link it to whatever component or page, and it would work perfectly well. For example, you can create a styles folder in the src folder and then create a global.css file with your CSS code.
For example, here are some basic global stylings for the components created earlier:
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #ddd;
font-family: 'Poppins',
sans-serif;
width: 1200px;
margin: 0 auto;
}
a {
text-decoration: none;
}
img {
width: 100%;
}
nav {
display: flex;
justify-content: space-between;
height: 200px;
align-items: center;
}
nav .logo-img {
width: 100px;
}
nav .nav-links a {
padding: 0 20px;
font-size: 18px;
}
@media (max-width:700px) {
body {
width: 100%;
padding: 0 20px;
}
nav .nav-links a {
padding: 0 18px;
}
}
.footer {
width: 100%;
text-align: center;
margin: 100px 0 20px;
}
In the code above, you are importing the Poppins font from Google Fonts and then defining basic styles to apply to all your components.
Next, import the CSS file into the components you wish to style, but for this project, you can add it to your Layout component so it applies globally:
import React from 'react';
import Navbar from './Navbar';
import Footer from './Footer';
import '../styles/global.css';
const Layout = ({ children }) => {
return (
<div>
<Navbar />
<div> className="content">{children}</div>
<Footer />
</div>
);
};
export default Layout;
Module CSS Styling
CSS Modules allow you to scope your styles to specific components or pages. This prevents style conflicts and makes it easier to maintain your code. In the styles folder, create your CSS modules using the format <pageName>.module.css and add the specific style to the file.
For example, create home.module.css for the homepage and add the following code:
.home_hero {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
}
.home_hero h1 {
font-size: 60px;
width: 70%;
}
.home_hero p {
color: #6E7076;
font-size: 20px;
}
.btn {
background-color: #5333ed;
padding: 20px 30px;
margin-top: 40px;
border-radius: 5px;
color: #fff;
}
@media (max-width:700px) {
.home_hero h1 {
font-size: 40px;
}
.home_hero p {
font-size: 16px;
}
}
To use module CSS styles in your Gatsby page or component, import the styles from your CSS module as an object at the top of your page or component file and use this way:
import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/home.module.css';
export default function Home() {
return (
<Layout>
<div className={styles.home_hero}>
<h1>Enjoy Static Site Hosting With Kinsta StSH.</h1>
<p>Fast, Secure, Reliable Hosting Solution.</p>
<a href="https://kinsta.com/docs/static-site-hosting/">
<div className={styles.btn}>Read more</div>
</a>
</div>
</Layout>
);
}
Using Static Files in Gatsby
In Gatsby, static files refer to assets like images, fonts, CSS files, and other resources that are served directly to the client’s browser without any server-side processing. These files are added to the /static directory at the root of your project.
For example, if you add an image kinsta-logo.png to the /static directory, you can display it in your component like this:
import { Link } from 'gatsby';
import React from 'react';
const Navbar = () => {
return (
<nav>
<Link> to="/">
<img src="/kinsta-logo.png" alt="Kinsta Logo" className="logo-img" />
</Link>
<div className="nav-links">
<Link> to="/">Home</Link>
<Link> to="/about">About</Link>
<Link> to="/blog">Blog</Link>
</div>
</nav>
);
};
export default Navbar;
Gatsby automatically resolves these relative paths to the correct URL when your site is built. Later in this guide, you will learn how to optimize images in Gatsby.
Plugins and Integrations
Gatsby has a rich ecosystem of plugins that can extend its functionality. You can find plugins for SEO, analytics, image optimization, markdown transformation, and much more. Installing and configuring plugins is straightforward, and they can greatly enhance your site’s capabilities.
In this guide, we use four plugins:
- gatsby-transformer-remark: This plugin allows you to transform Markdown files into HTML content, making it easy to create and manage blog posts, documentation, or any text-based content.
- gatsby-transformer-sharp and gatsby-plugin-sharp: These plugins work together to optimize and manipulate images in your Gatsby project.
- gatsby-source-filesystem: This plugin enables you to source files from your project directory and make them available to query with GraphQL.
To use these plugins in your Gatsby project, run the following command in your project’s root directory to install them:
npm install gatsby-transformer-remark gatsby-transformer-sharp gatsby-plugin-sharp gatsby-source-filesystem
Next, configure them in your gatsby-config.js file. Here’s an example of how to set up the plugins:
module.exports = {
plugins: [
// ...other plugins
// Transform Markdown files into HTML
'gatsby-transformer-remark',
// Optimize and manipulate images
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
// Source files from your project directory
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/src/posts/`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images/`,
},
},
],
};
Two gatsby-source-filesystem
configurations are created, pointing to two folders: posts and images. Posts will store some markdown files (blog posts) that would be transformed with gatsby-transformer-remark
, and images will store images for the blog and other images you wish to optimize.
Always remember to restart your local development server when you make changes to the gatsby-config.js file.
Creating Blog Posts
Now that we’ve configured our plugins create a posts folder in the src directory and then create two Markdown files with the following content:
post-1.md:
---
title: "Introduction to Gatsby"
date: "2023-10-01"
slug: "introduction-to-gatsby"
description: "Learn the basics of Gatsby and its features."
featureImg: ../images/featured/image-1.jpeg
---
Welcome to the world of Gatsby! In this post, we will introduce you to the basics of Gatsby and its powerful features.
And post-2.md:
---
title: "Optimizing Images in Gatsby"
date: "2023-10-05"
slug: "optimizing-images-in-gatsby"
description: "Explore how to optimize images in your Gatsby project."
featureImg: ../images/featured/image-2.jpeg
---
Images play a crucial role in web development. In this post, we'll dive into how to optimize images in Gatsby using plugins.
These Markdown files contain frontmatter with metadata about the blog posts, including titles, dates, slugs, descriptions, and image paths.
Querying in Gatsby With GraphQL
Gatsby uses GraphQL to query and retrieve data for your website. GraphQL is a powerful query language that allows you to request exactly the data you need, making it efficient and flexible. Let’s learn how to query data in Gatsby using GraphQL.
When you run gatsby develop
in your terminal, you’ll notice that, in addition to the link gatsby-source-filesystem, which opens your project on the web, you also see the http://localhost:8000/___graphql URL. This URL provides access to the GraphiQL editor for your Gatsby project.
When you open the editor, you see this interface:
You can query as much information about your site from this editor. But since you have created markdown files and done all the configurations in the gatsby-config.js file. Let’s query the Markdown files and their content by running the following query in the editor:
query BlogList {
allMarkdownRemark {
nodes {
frontmatter {
title
slug
description
}
id
}
}
}
This query fetches data from all Markdown files using allMarkdownRemark
. It retrieves the title
, slug
, and description
from each file’s frontmatter and also their id
.
After writing your query, click the “Play” button (a right-facing triangle icon) to execute the query. The results will be displayed on the right-hand side of the editor.
You can then use GraphQL to query the Markdown data in your components or pages. To query this data in the blog/index.js page, first import graphql
from gatsby
. Then, at the bottom of the JSX code, add the following:
export const query = graphql`
query BlogList {
allMarkdownRemark {
nodes {
frontmatter {
title
slug
description
}
id
}
}
}
`;
In the code above, we use the graphql
tag to create a GraphQL query called query
. This is what your blog/index.js file should look like:
import { graphql, Link } from 'gatsby';
import React from 'react';
import Layout from '../../components/Layout';
import * as styles from '../../styles/blog.module.css';
const blog = ({ data }) => {
const posts = data.allMarkdownRemark.nodes;
return (
<Layout>
<div className={styles.blog_cont}>
<h2>Blog</h2>
<div className={styles.blog_grid}>
{posts.map((post) => (
<Link
to={`/blog/${post.frontmatter.slug}`}
className={styles.blog_card}
key={post.id}
>
<h3>{post.frontmatter.title}</h3>
<p>{post.frontmatter.description}</p>
</Link>
))}
</div>
</div>
</Layout>
);
};
export default blog;
export const query = graphql`
query BlogList {
allMarkdownRemark {
nodes {
frontmatter {
title
slug
description
}
id
}
}
}
`;
In the code above, you access the query
result via the data
prop in your component. Next, loop through the posts
data using the map()
JavaScript method and then display the titles in a list.
To avoid errors, create a blog.module.css file in the styles folder and add the following code:
.blog_cont h2 {
font-size: 40px;
margin-bottom: 20px;
}
.blog_grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
}
@media (max-width:700px) {
.blog_grid {
grid-template-columns: 1fr;
}
}
.blog_card {
background-color: #bfbfbf;
padding: 20px;
border-radius: 5px;
color: #000;
transition: all .5s ease-in-out;
}
.blog_card:hover {
background-color: #5333ed;
color: #fff;
}
.blog_card h3 {
margin-bottom: 15px;
}
.blog_card p {
margin-bottom: 15px;
}
Understanding Templates and Generating Dynamic Pages In Gatsby With GraphQL
In Gatsby, templates and dynamic pages are essential concepts that enable you to create flexible and data-driven websites. Templates allow you to define the structure and layout of pages, while GraphQL helps you fetch data to populate these templates dynamically.
Creating a Blog Post Template
Let’s say you want to create a blog where each blog post has a consistent structure, including a title and content. You can create a BlogDetails
template to define this layout. In the src folder, create a templates folder, then create a blog-details.js file:
import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/blog-details.module.css';
const BlogDetails = () => {
return (
<Layout>
<div>
<div className={styles.blog_content}>
<Img
className={styles.blog_featured}
/>
<h3>Title</h3>
<div>
className={styles.html}
dangerouslySetInnerHTML={}
/>
</div>
</div>
</Layout>
);
};
export default BlogDetails;
In this example, the BlogDetails
template defines the structure for individual blog posts. Next, let’s use GraphQL to fetch data for specific blog posts and pass it as props to this template.
Generating Dynamic Pages
To generate dynamic pages, create a gatsby-node.js file in your project’s root directory. This file allows you to define how pages are created.
In your gatsby-node.js file, use GraphQL to query the data you want to use for dynamic pages. For example, if you have Markdown blog posts, you can query their slugs:
const path = require(`path`);
exports.createPages = async ({ graphql, actions }) => {
const { data } = await graphql(`
query Articles {
allMarkdownRemark {
nodes {
frontmatter {
slug
}
}
}
}
`);
data.allMarkdownRemark.nodes.forEach((node) => {
actions.createPage({
path: '/blog/' + node.frontmatter.slug,
component: path.resolve('./src/templates/blog-details.js'),
context: { slug: node.frontmatter.slug },
});
});
};
In this example, we query the slugs of all Markdown posts and create dynamic pages for each post using the BlogDetails
template. The context object is used to pass data to the template. This data (slug) is what the template uses to fetch other data that aligns with the slug.
Let’s first understand how image optimization works in Gatsby before adding a GraphQL query to the template page.
Image Optimization In Gatsby
Earlier, you installed and configured the gatsby-transformer-sharp
and gatsby-plugin-sharp
along with gatsby-source-filesystem
for sourcing images.
With those plugins, you can query and optimize images with GraphQL. Here’s an example of how to query and display an optimized image using gatsby-plugin-sharp
:
export const query = graphql`
query {
file(relativePath: { eq: "example.jpg" }) {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
`;
In the code above, you’re querying an image named example.jpg from the images source and using the fluid
property of the queried image to display it with responsive, optimized rendering.
You can then import Img
from gatsby-image
for working with optimized images.
import React from 'react';
import { graphql } from 'gatsby';
import Img from 'gatsby-image';
const ImageExample = ({ data }) => {
const { fluid } = data.file.childImageSharp;
return (
<div>
<Img fluid={fluid} alt="Example Image" />
</div>
);
};
export default ImageExample;
Querying Dynamic Pages
Gatsby will use the specified template to create individual pages for each blog post. Let’s now add GraphQL query to the template page to fetch the data based on the slug:
import { graphql } from 'gatsby';
import Img from 'gatsby-image';
import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/blog-details.module.css';
const BlogDetails = ({ data }) => {
const { html } = data.markdownRemark;
const { title, featureImg } = data.markdownRemark.frontmatter;
return (
<Layout>
<div>
<div className={styles.blog_content}>
<Img
fluid={featureImg.childImageSharp.fluid}
className={styles.blog_featured}
/>
<h3>{title}</h3>
<div
className={styles.html}
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>
</div>
</Layout>
);
};
export default BlogDetails;
export const query = graphql`
query ProjectDetails($slug: String) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html
frontmatter {
title
featureImg {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`;
In the code above, you will notice we are querying for the optimized image and querying for the blog post that matches the slug.
You can check out the full source code for this Gatsby project on GitHub.
Deploy Gatsby Static Sites With Kinsta
Kinsta allows you to host up to 100 static websites for free. This can be done by pushing your code to your preferred Git provider (Bitbucket, GitHub, or GitLab) and then deploying it to Kinsta.
Once your repo is ready, follow these steps to deploy your static site to Kinsta:
- Log in or create an account to view your MyKinsta dashboard.
- Authorize Kinsta with your Git provider.
- Click Static Sites on the left sidebar, then click Add site.
- Select the repository and the branch you wish to deploy from.
- Assign a unique name to your site.
- MyKinsta will detect the build settings for this Gatsby project automatically. You will see the following settings prefilled:
- Build command:
npm run build
- Node version:
18.16.0
- Publish directory:
public
- Build command:
- Finally, click Create site.
And that’s it! You now have a deployed site within a few seconds. A link is provided to access the deployed version of your site. You can later add your custom domain and SSL certificate if you wish.
As an alternative to Static Site Hosting, you can opt for deploying your static site with Kinsta’s Application Hosting, which provides greater hosting flexibility, a wider range of benefits, and access to more robust features. For example, scalability, customized deployment using a Dockerfile, and comprehensive analytics encompassing real-time and historical data.
Summary
This guide covers the fundamentals of data sourcing, routing, styling, image optimization, plugins, deployment, and lots more.
Gatsby’s flexibility, speed, and rich ecosystem make it a powerful choice for building static websites. Whether you’re creating a personal blog, a portfolio site, or a business website, Gatsby has you covered.
Now it’s time to put your knowledge into action and start building your own Gatsby site. Have you utilized Gatsby to build anything? Feel free to share your projects and experiences with us in the comments section below.
Leave a Reply