{"id":1906,"date":"2025-04-01T18:57:13","date_gmt":"2025-04-01T15:57:13","guid":{"rendered":"https:\/\/upcloud.com\/global\/us\/resources\/tutorials\/how-to-create-a-fast-seo-friendly-website-with-gatsby-on-upcloud\/"},"modified":"2025-04-01T18:57:13","modified_gmt":"2025-04-01T15:57:13","slug":"how-to-create-a-fast-seo-friendly-website-with-gatsby-on-upcloud","status":"publish","type":"tutorial","link":"https:\/\/upcloud.com\/global\/resources\/tutorials\/how-to-create-a-fast-seo-friendly-website-with-gatsby-on-upcloud\/","title":{"rendered":"How to Create a Fast, SEO-Friendly Website with Gatsby on UpCloud"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Gatsby is an open source React-based web framework and <a href=\"https:\/\/www.gatsbyjs.com\/docs\/glossary\/static-site-generator\/\" target=\"_blank\" rel=\"noopener\">static site generator<\/a> (SSG) that enables developers to build fast, scalable, and secure websites. Although it\u2019s mainly an SSG, Gatsby-powered websites are also capable of serving dynamic content, thanks to the underlying React functionality.&nbsp;<\/p>\n\n\n\n<p>Gatsby offers some major benefits for both the developer experience and website user experience. From a development standpoint, Gatsby helps you get started quickly with your project by providing a <a href=\"https:\/\/www.gatsbyjs.com\/starters\/\" target=\"_blank\" rel=\"noopener\">starter library<\/a> that includes reusable templates and boilerplate code that fits different project needs.<\/p>\n\n\n\n<p>From a website user experience, Gatsby is well-known for creating extremely fast and performant websites by pre-rendering the content delivered at the first request on the server side, while also offering client-side rendering for subsequent requests using <a href=\"https:\/\/www.gatsbyjs.com\/docs\/conceptual\/react-hydration\/\" target=\"_blank\" rel=\"noopener\">React\u2019s hydration technique<\/a>.<\/p>\n\n\n\n<p>Another key feature of Gatsby is its ability to load data from various sources including filesystems, databases, CMS, or APIs. This is done by relying on <a href=\"https:\/\/www.gatsbyjs.com\/docs\/graphql\/\" target=\"_blank\" rel=\"noopener\">GraphQL<\/a> for querying these different data sources. The Gatsby data layer powered by GraphQL combines the data from different sources offering a unified point for data access.<\/p>\n\n\n\n<p>Gatsby is also known for \u201cplaying nicely\u201d with SEO. Because it pre-renders the page on the server side and generates a resulting static HTML, it allows web crawlers to retrieve and index the content. This is in contrast to <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/SPA\" target=\"_blank\" rel=\"noopener\">SPA frameworks<\/a> that rely on client-side Javascript rendering which might be challenging for some web crawlers to use.<\/p>\n\n\n\n<p>We can double down on the performance features of Gatsby by using <a href=\"https:\/\/upcloud.com\/global\/products\/cloud-servers\/\">UpCloud\u2019s ultra-fast servers<\/a> to deploy our Gatsby websites. This also brings the scalability and resilience features of the Cloud to further enhance our application\u2019s user experience.<\/p>\n\n\n\n<p>In this guide, we\u2019re going to cover the fundamental concepts and use cases of Gatsby, along with a practical example for building and deploying a Gatsby project to a Cloud server on UpCloud. Throughout this guide, you\u2019ll be able to understand the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How Gatsby works and its common use cases<\/li>\n\n\n\n<li>How to install Gatsby and work on a new project<\/li>\n\n\n\n<li>How to deploy your Gatsby project to a Cloud server<\/li>\n\n\n\n<li>How to optimize your project for SEO and performance<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>To follow along with this guide, you\u2019ll need to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Create an <\/strong><a href=\"https:\/\/signup.upcloud.com\/\"><strong>UpCloud account<\/strong><\/a><strong>:<\/strong> This gives you access to different UpCloud services using the GUI control panel, <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/upcloud-command-line-interface\/\">command-line interface<\/a>, or the <a href=\"https:\/\/upcloud.com\/global\/resources\/tools\/category\/api-clients\/\">API<\/a>.<\/li>\n\n\n\n<li><a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/deploy-server\/\"><strong>Deploy a Cloud server on UpCloud<\/strong><\/a><strong>:<\/strong> This is going to be our target server where we\u2019ll deploy our Gatsby application.<\/li>\n\n\n\n<li><strong>Install Node.js and npm:<\/strong> npm is used to install the gatsby-cli and other required dependencies or plugins for the project. A common way to install Node.js and npm is through the <a href=\"https:\/\/github.com\/nvm-sh\/nvm\" target=\"_blank\" rel=\"noopener\">node version manager<\/a>.<\/li>\n\n\n\n<li><strong>Familiarity with using the CLI:<\/strong> We\u2019ll be using some basic commands throughout this guide to install our tools, navigate project directories, and work with SSH.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What is Gatsby and Why Use It?<\/h2>\n\n\n\n<p>Gatsby is a web framework that is capable of building super fast web pages by leveraging SSG pre-rendering techniques. That is, when a user sends a request to get a page, the HTML is already generated previously and ready to be served instantly.<\/p>\n\n\n\n<p>Let\u2019s clarify this more with a simple analogy.<\/p>\n\n\n\n<p>Imagine you walk into a coffee shop to order a drink, upon receiving your request, the barista starts \u201cbuilding\u201d your drink by assembling the different components required. After waiting for this \u201cbuild\u201d process to finish, you finally get your drink.<\/p>\n\n\n\n<p>Now what if the barista already \u201cpre-built\u201d this drink and has it ready to be served before you order it? You now don\u2019t have to wait for the process of making your drink to finish, you just put your order and you have it delivered.&nbsp;<\/p>\n\n\n\n<p>This is roughly what Gatsby or other static site generators do.<\/p>\n\n\n\n<p>Gatsby prepares the HTML document that should be delivered to the user prior to receiving the actual user request. This process happens at build time and not runtime, meaning that when you build your Gatsby project, it starts rendering the page to make it ready for requests, instead of rendering it at runtime when receiving the request.<\/p>\n\n\n\n<p>It\u2019s worth mentioning that newer versions of Gatsby also offer other <a href=\"https:\/\/www.gatsbyjs.com\/docs\/conceptual\/rendering-options\/\" target=\"_blank\" rel=\"noopener\">rendering options<\/a> besides the SSG method.<\/p>\n\n\n\n<p>To further extend our analogy, let\u2019s assume that not all of the ingredients of your drink are actually there in the coffee shop, and they need to request it from other external sources to be able to prepare your drink.<\/p>\n\n\n\n<p>For example, they need to use a specific type of coffee bean that is required for your drink, but it\u2019s currently not in-stock, so they will order it from an external provider of this coffee bean. Now you\u2019ll also have to wait for the time it takes for the ingredient to be \u201cpulled\u201d from its source.<\/p>\n\n\n\n<p>Gatsby also saves this time as it pulls any required data from external sources during the build process when rendering the page. Now the generated HTML has all what\u2019s needed to be served to the user upon request, no extra server-side processing is needed.<\/p>\n\n\n\n<p>The process of pulling data from data sources in Gatsby relies on using GraphQL. This provides Gatsby with a lot of flexibility to query data from a variety of sources like external APIs, databases, or content management systems.<\/p>\n\n\n\n<p>Although Gatsby can be used to build almost any type of website, it\u2019s widely popular for content websites like blogs, documentation, and e-commerce.<\/p>\n\n\n\n<p>Gatsby is also well-suited for SEO, it provides built-in support for server rendering of metadata like description and title, and it includes them in the generated HTML pages. This capability is provided through a Gatsby SEO component and plugins like <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-react-helmet\/\" target=\"_blank\" rel=\"noopener\">Gatsby React Helmet<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Choose UpCloud for Hosting Gatsby Websites?<\/h2>\n\n\n\n<p>The performance and scalability features of Gatsby are only one piece of the puzzle. At the end, there\u2019s still a critical role that the underlying infrastructure plays in the overall user experience. That\u2019s why choosing the right hosting option for your Gatsby website should be of a top priority.<\/p>\n\n\n\n<p>Taking advantage of the Cloud is considered one of the best options for hosting your application. By leveraging the massive scalability and performance features offered by the Cloud, you can satisfy your application\u2019s non-functional requirements with less manual operations and overhead, and this is what the <a href=\"https:\/\/upcloud.com\/global\/docs\/products\/cloud-servers\/\">UpCloud servers<\/a> excel at.<\/p>\n\n\n\n<p>UpCloud servers deliver world-class performance and reliability by utilizing the underlying technologies that UpCloud uses at every component of their infrastructure. Starting from the storage component, UpCloud servers can use the <a href=\"https:\/\/upcloud.com\/global\/docs\/products\/block-storage\/tiers\/#maxiops\">MaxIOPS<\/a> block storage system, an UpCloud-developed storage technology that <a href=\"https:\/\/upcloud.com\/global\/blog\/going-beyond-ssd-with-maxiops\/\">outperforms industry-standard SSD<\/a>. Additionally, the block storage systems are served from a clustered <a href=\"https:\/\/www.snia.org\/education\/storage_networking_primer\/san\/what_san#:~:text=A%20Storage%20Area%20Network%20(SAN)%20is%20a%20specialized%2C%20high,SANs%20may%20span%20multiple%20sites.\" target=\"_blank\" rel=\"noopener\">storage area network<\/a> backend, and not from the local hypervisor, which provides higher levels of availability and recovery against hardware failures.<\/p>\n\n\n\n<p>Another differentiating component for UpCloud servers is the underlying <a href=\"https:\/\/upcloud.com\/global\/docs\/products\/cloud-servers\/system-architecture\/#cloud-server-hosts\">compute hosts<\/a>, which are designed for availability and use enterprise-grade virtualisation and hardware resources.<\/p>\n\n\n\n<p>UpCloud also has a <a href=\"https:\/\/upcloud.com\/global\/docs\/getting-started\/locations\/\">global presence<\/a> across multiple geographical locations, which provides the flexibility to deploy applications as close as possible to the end-users, improving their user experience.<br>Combining all of these features with affordable and simple <a href=\"https:\/\/upcloud.com\/global\/docs\/products\/cloud-servers\/configurations\/\">configurations<\/a> makes UpCloud a perfect choice for hosting different types of workloads, especially those that will benefit the most from the performance capabilities like Gatsby websites.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Gatsby on UpCloud<\/h2>\n\n\n\n<p>Now let\u2019s get into a practical scenario by installing Gatsby on our UpCloud server, then creating and testing a project. As mentioned in the prerequisites section, you need to already have your UpCloud server deployed and prepared with Node.js and npm.<\/p>\n\n\n\n<p>Connect to your UpCloud server using SSH. You\u2019ll first need to <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/use-ssh-keys-authentication\/\">generate an SSH key and use it for your server<\/a>. Then you can use the command <code>ssh -i &lt;key-file&gt; root@&lt;server-IP&gt;.<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby1-1024x1024.png\" alt=\"-\" class=\"wp-image-49174\" \/><\/figure>\n\n\n\n<p>Verify your Node.js and npm installation with the commands <code>node -v <\/code>and <code>npm -v.<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby2-1024x262.png\" alt=\"-\" class=\"wp-image-49175\" \/><\/figure>\n\n\n\n<p>Install Gatsby CLI to initialize, build, and develop your Gatsby projects. There are multiple ways to use the Gatsby CLI, we can install it with npm using the command <code>npm install -g gatsby-cli,<\/code> or we can execute it directly as a node package using <code>npx gatsby <\/code>followed by the Gatsby command we need. For this guide, we\u2019ll be installing it using npm.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby3-1024x305.png\" alt=\"-\" class=\"wp-image-49176\" \/><\/figure>\n\n\n\n<p><br>Create a new project using the command <code>gatsby new &lt;project-name&gt;<\/code><strong><em>.<\/em><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby4-1024x357.png\" alt=\"-\" class=\"wp-image-49177\" \/><\/figure>\n\n\n\n<p><br>This will automatically clone and use the <a href=\"https:\/\/github.com\/gatsbyjs\/gatsby-starter-default\" target=\"_blank\" rel=\"noopener\">default Gatsby starter<\/a> that includes boilerplate code and configuration to get started quickly with your project.<\/p>\n\n\n\n<p>Now, navigate to your project directory and start the local development server with the command <code>gatsby develop.<\/code> This development server is useful for testing your project locally.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby5-1024x913.png\" alt=\"-\" class=\"wp-image-49178\" \/><\/figure>\n\n\n\n<p><br>The above command starts the dev server locally on port 8000. By default, it can only accept requests on the localhost, meaning that you need to connect to it from the same server. Since our Ubuntu server doesn\u2019t have a browser installed, we can test the connectivity using curl with the command <code>curl localhost:8000<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby6-1024x306.png\" alt=\"-\" class=\"wp-image-49180\" \/><\/figure>\n\n\n\n<p><br>As we can see, we get a response with the HTML content of the Gatsby website. To enable connecting to our development server from anywhere, we can modify the <code>gatsby develop <\/code>command by adding <code>-H 0.0.0.0 <\/code>option, which specifies that the server should listen to requests on any interface IP address and not only the localhost.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby7-1024x386.png\" alt=\"-\" class=\"wp-image-49181\" \/><\/figure>\n\n\n\n<p><br>We can now connect to our server using its public IP from a browser on any other machine.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/image-132-1024x769.png\" alt=\"-\" class=\"wp-image-49182\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding Gatsby project structure<\/h2>\n\n\n\n<p>Now let\u2019s navigate our project folder and understand its most important contents:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby8.png\" alt=\"-\" class=\"wp-image-49183\" \/><\/figure>\n\n\n\n<p><br><code>\/src <\/code>: This is the directory that contains the source code that generates everything in the frontend of your site. For example, there\u2019s a <code>\/pages <\/code>subdirectory under the <em>\/src<\/em> directory where you can create React components that are transformed into pages in your website with their path equal to their file name.<br><br>Let\u2019s clarify this by creating a file called <code>about.js<\/code> under <code>\/src\/pages<\/code>. This file will contain the following React component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">\/\/ src\/pages\/about.js\n\nimport * as React from \"react\"\n\nfunction AboutPage() {\n  return (\n    &lt;div className=\"about-container\"&gt;\n      &lt;p&gt;This is the about page of the website&lt;\/p&gt;\n    &lt;\/div&gt;\n  )\n}\n\nexport default AboutPage<\/code><\/pre>\n\n\n\n<p>Now when we build our project, we\u2019ll be able to navigate to the <code>\/about <\/code>path in the website:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby9.png\" alt=\"-\" class=\"wp-image-49184\" \/><\/figure>\n\n\n\n<p><code>\/public<\/code>: This directory will contain the output of the build process for our Gatsby project. For example, the HTML document generated from the React components under the <code>\/src\/pages<\/code> will be added to their own subdirectory under this <code>\/public <\/code>directory. Let\u2019s check this for the previous <code>\/about <\/code>page:<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" data-id=\"49186\" src=\"https:\/\/upcloud.com\/media\/gatsby10.png\" alt=\"-\" class=\"wp-image-49186\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" data-id=\"49187\" src=\"https:\/\/upcloud.com\/media\/gatsby11.png\" alt=\"-\" class=\"wp-image-49187\" \/><\/figure>\n<\/figure>\n\n\n\n<p>As we can see, the <code>index.html <\/code>file was created in the <code>\/about <\/code>subdirectory under the <code>\/public <\/code>directory. Which contains our HTML code generated from the React component.<\/p>\n\n\n\n<p><code>\/static<\/code><strong><em>:<\/em><\/strong> Any file that you add under this directory will be copied under the <code>\/public<\/code><em> <\/em>folder as it is with no changes. This can be considered one way to add assets to your project.<\/p>\n\n\n\n<p>We can try this by adding a simple logo image to our website:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby12.png\" alt=\"-\" class=\"wp-image-49188\" \/><\/figure>\n\n\n\n<p>Next we\u2019ll create a component under<code> \/src\/pages<\/code> to display this image:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby13-1024x425.png\" alt=\"-\" class=\"wp-image-49189\" \/><\/figure>\n\n\n\n<p>Now let\u2019s try the<code> \/logo <\/code>path for our website:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby14-1024x609.png\" alt=\"-\" class=\"wp-image-49190\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Deploying Gatsby using Nginx<\/h2>\n\n\n\n<p>So far we\u2019ve been testing our website using the<code> gatsby develop<\/code> command, which starts a development server on the fly and starts serving the requests.<\/p>\n\n\n\n<p>However, this setup is not production-ready, so we need to do some additional steps to prepare our website to run in a production environment. In these steps we\u2019ll be installing and configuring Nginx to serve our Gatsby website instead of relying on the local development server, and we\u2019ll also compile and build our project files instead of just serving them in the development mode.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install Nginx on our UpCloud server. As we\u2019re running Ubuntu, we\u2019ll use the <code>apt update <\/code>and <code>apt install nginx <\/code>commands. You can use the corresponding package manager of your operating system.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby15-1024x574.png\" alt=\"-\" class=\"wp-image-49194\" \/><\/figure>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Verify that the service is running using the command <code>systemctl status nginx.<\/code> We can also test the service by connecting from a browser to our server IP.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"49195\" src=\"https:\/\/upcloud.com\/media\/gatsby16-1024x282.png\" alt=\"-\" class=\"wp-image-49195\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"49196\" src=\"https:\/\/upcloud.com\/media\/gatsby17-1024x402.png\" alt=\"-\" class=\"wp-image-49196\" \/><\/figure>\n<\/figure>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Now that we\u2019ve our nginx web server ready, let\u2019s build our Gatsby project. From inside the root directory of the project use the command <code>gatsby build.<\/code> This will compile the related project files and generate the final HTML pages under the <code>\/public <\/code>subdirectory.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby18-1024x399.png\" alt=\"-\" class=\"wp-image-49197\" \/><\/figure>\n\n\n\n<p>You\u2019ll find the list of pages rendered for your project at the end of the command output.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby19-1024x614.png\" alt=\"-\" class=\"wp-image-49198\" \/><\/figure>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>Copy your project\u2019s <code>\/public <\/code>directory to <code>\/var\/www\/ <\/code>with the command <code>cp -r public\/ \/var\/www\/<\/code>, this will be the web root that we\u2019ll configure for our nginx server.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby20.png\" alt=\"-\" class=\"wp-image-49200\" \/><\/figure>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>Modify your Nginx server configuration to use your <code>\/public<\/code> directory as the web root. The Nginx configuration files location depends on your operating system, but in most cases it will be under the <code>\/etc\/nginx\/ <\/code>directory.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby21-1024x436.png\" alt=\"-\" class=\"wp-image-49201\" \/><\/figure>\n\n\n\n<p>In the above configuration, we first set this server as the default, meaning that requests that have no matching host name in the Host header will be served from this server. Next we set our <code>\/public<\/code> directory that we copied under the <code>\/var\/www <\/code>as our web root, so our Nginx server will process requests by searching for files starting from this location. Finally, we configure two locations for our website <code>root <strong><em>\/<\/em><\/strong> <\/code>and <code>\/about<\/code> pages.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">server {\n        listen 80 default_server;\n\n        root \/var\/www\/public;\n\n            location \/ {\n            }\n\n            location \/about\/ {\n            }<\/code><\/pre>\n\n\n\n<ol start=\"6\" class=\"wp-block-list\">\n<li>Restart the Nginx service using the command <code>systemctl restart nginx<\/code>, then test access to the website pages from the browser.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby22-1024x299.png\" alt=\"-\" class=\"wp-image-49202\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"49203\" src=\"https:\/\/upcloud.com\/media\/gatsby23-1024x403.png\" alt=\"-\" class=\"wp-image-49203\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"49204\" src=\"https:\/\/upcloud.com\/media\/gatsby24.png\" alt=\"-\" class=\"wp-image-49204\" \/><\/figure>\n<\/figure>\n\n\n\n<p>Now we\u2019ve our production-ready Gatsby website served using Nginx!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Optimizing Gatsby for SEO<\/h2>\n\n\n\n<p>One of the major benefits of using Gatsby is its ability to boost your website&#8217;s SEO ranking. Of course, the SEO algorithms are complicated with a lot of factors taken into consideration, but we\u2019ll cover the key features of Gatsby that optimize SEO performance:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Static page generation:<\/strong> The SSG rendering technique of Gatsby creates the static HTML pages ahead of time on the server, this helps web crawlers in understanding and indexing the page contents. This is unlike client-side rendering, which sends a minimal empty HTML document and relies on executing JavaScript code on the client to manipulate the DOM and create additional content, and because some web crawlers cannot efficiently run JavaScript code, this might cause delays in rendering the page or even errors, which impacts the website ranking.<br><br>Additionally, because website performance is a key factor in SEO ranking,&nbsp; the performance optimization offered by the SSG rendering helps improve Gatsby\u2019s SEO results.<\/li>\n<\/ol>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Page titles and Meta descriptions:<\/strong> When you get the search results for a specific keyword, chances are you\u2019ll click on the link that has a description that caught your eyes, and this is the importance of meta information of a website page.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/gatsby25-1024x203.png\" alt=\"-\" class=\"wp-image-49208\" \/><\/figure>\n\n\n\n<p>Meta description and title informs the user about the content included in the page, it\u2019s like a summary of what to expect when visiting this page. So, a compelling description should be a critical factor for driving organic traffic to your website.<br><br>Gatsby enables you to dynamically set these tags for your pages in an easy and efficient way using the <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-react-helmet\/\" target=\"_blank\" rel=\"noopener\"><strong><em>gatsby react helmet plugin<\/em><\/strong><\/a> or <a href=\"https:\/\/www.gatsbyjs.com\/docs\/reference\/built-in-components\/gatsby-head\/\" target=\"_blank\" rel=\"noopener\"><strong><em>Gatsby Head API<\/em><\/strong><\/a>.<br><br>A sample component that uses gatsby react helmet to generate page title and description can look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import React from 'react';\nimport { Helmet } from 'react-helmet';\n\nconst MyPage = () =&gt; {\n  return (\n    &lt;div&gt;\n      &lt;Helmet&gt;\n        &lt;title&gt;Deploy high performance website with Gatsby and UpCloud&lt;\/title&gt;\n        &lt;meta name=\"description\" content=\"In this tutorial you\u2019ll learn how to create a Gatsby website and optimize its performance with UpCloud servers\" \/&gt;\n      &lt;\/Helmet&gt;\n    &lt;\/div&gt;\n  );\n};\n\nexport default MyPage;<\/code><\/pre>\n\n\n\n<p>Note that you\u2019ll need to install the plugin first using the command <code>npm install gatsby-plugin-react-helmet react-helmet.<\/code><br><\/p>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>URL structure and permalinks:<\/strong> Imagine a user reading a post on your website where the URL showing in the browser is <strong><em>https:\/\/your-site-name\/28h79dks0-dnhfs<\/em><\/strong>, this of course doesn\u2019t give any context about what content is included in the post or which category does it belong to. Compare this to a URL that is showing <strong><em>https:\/\/your-site-name\/tutorials\/install-gatsby-upcloud<\/em><\/strong>, which can definitely tell the story of what content you\u2019re viewing.<br><br>This URL structuring is crucial for improving your site\u2019s SEO performance and even for the experience of your site visitors. URLs and permalinks for a specific resource on a website should be descriptive, this helps search engines better understand and index the content.<br><br>Gatsby allows setting custom SEO-friendly URLs and slugs by <a href=\"https:\/\/www.gatsbyjs.com\/docs\/creating-slugs-for-pages\/\" target=\"_blank\" rel=\"noopener\">modifying the gatsby-node.js<\/a> file and using the <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-slug\/\" target=\"_blank\" rel=\"noopener\">Gatsby slug plugin<\/a>.<br><\/li>\n<\/ol>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>HTML heading tags:<\/strong> Adding proper heading tags to your page (e.g. &lt;h1&gt;, &lt;h2&gt;, &lt;h3&gt;) can greatly improve your website\u2019s SEO performance. Page headings can help search engines better understand the content structure, also adding relevant keywords to the headings can boost the page SEO ranking.&nbsp;<\/li>\n<\/ol>\n\n\n\n<p>You can use Gatsby to set your generated HTML page headings by configuring the page contents in its relative component.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import React from \"react\"\nimport { Link } from \"gatsby\"\n\nimport Layout from \"..\/components\/layout\"\nimport SEO from \"..\/components\/seo\"\n\nconst DocsPage = () =&gt; (\n  &lt;Layout&gt;\n    &lt;SEO title=\"Home\" \/&gt;\n    &lt;h1&gt;Explore Gatsby Documentation&lt;\/h1&gt;\n    &lt;h2&gt;Gatsby Rendering Options&lt;\/h2&gt;\n    &lt;h2&gt;Gatsby SEO Component&lt;\/h2&gt;\n  &lt;\/Layout&gt;\n)\n\nexport default DocsPage<\/code><\/pre>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li><strong>Image Optimization:<\/strong> Images are one of the assets that play a significant role in improving a page SEO ranking. Optimizing images for SEO includes multiple techniques like resizing and compressing images for better performance, using descriptive file names for the images, and adding alt text to the images.<\/li>\n<\/ol>\n\n\n\n<p>The <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/images-and-media\/using-gatsby-plugin-image\" target=\"_blank\" rel=\"noopener\">Gatsby image plugin<\/a> takes care of implementing the underlying complexities of image optimization while providing an easy way for the developer to leverage and customize the functionality of the plugin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import { StaticImage } from \"gatsby-plugin-image\"\n\nexport function Smartphone() {\n  return (\n    &lt;StaticImage\n      src=\"..\/images\/smartphone.png\"\n      alt=\"A smartphone device\"\n    \/&gt;\n  )\n}<\/code><\/pre>\n\n\n\n<p>In the above example, we\u2019re using the <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/images-and-media\/using-gatsby-plugin-image#static-images\" target=\"_blank\" rel=\"noopener\"><strong><em>StaticImage<\/em><\/strong><\/a> component from the Gatsby image plugin to add the <strong><em>smartphone.png<\/em><\/strong> image to our page and use the alt text <strong><em>A smartphone device<\/em><\/strong> to describe our image content.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Optimizing Gatsby for Performance<\/h2>\n\n\n\n<p>We can improve our website performance by implementing some Gatsby optimization techniques. These techniques can be generally divided into the following categories:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Third-party scripts enhancement:<\/strong> Some third-party scripts are \u201cmore demanding\u201d in terms of resource consumption. This might impact the page load performance and cause delays. We need to identify any third-party scripts and understand their purpose and what type of data they use, this will help us remove any unnecessary scripts.<br><br>Additionally, Gatsby includes a built-in <a href=\"https:\/\/www.gatsbyjs.com\/blog\/using-gatsby-script-component-to-decrease-page-load-times\/\" target=\"_blank\" rel=\"noopener\"><strong><em>&lt;Script&gt;<\/em><\/strong><\/a> component that provides a more efficient and performant way for loading scripts. With this component, we can control the technique by which we load the script at a specific stage of serving our content. These techniques include <strong><em>post-hydrate<\/em><\/strong>, <strong><em>idle<\/em><\/strong>, and <strong><em>off-main-thread<\/em><\/strong>.<br><\/li>\n<\/ol>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Reduce JavaScript code size:<\/strong> JavaScript is a resource-consuming asset due to its dynamic nature of execution. The more intensive and large your JavaScript code is, the more it can impact a page\u2019s performance. Also as more npm modules are added to the project, chances are there might be some JavaScript code that is unused.<\/li>\n<\/ol>\n\n\n\n<p>Gatsby provides plugins such as <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-webpack-bundle-analyser-v2\/\" target=\"_blank\" rel=\"noopener\"><strong><em>gatsby-plugin-webpack-bundle-analyser-v2<\/em><\/strong><\/a> that help analyze and understand the used JavaScript bundle; we can later use these insights to optimize the JavaScript bundle.<\/p>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Styling and Fonts efficiency:<\/strong> Globally scoped CSS styling applies to all the elements in the node tree that match a selector. This can result in a large CSS bundle getting pulled in every page. So, you need to properly scope and import the CSS so that only a small needed bundle is imported.<\/li>\n<\/ol>\n\n\n\n<p>Another styling improvement is to use Gatsby plugins that correspond to CSS-in-JS libraries. This will help render the styles on the server side and avoid the browser recalculating the size and position of elements on the page, also known as <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Reflow\" target=\"_blank\" rel=\"noopener\">reflow<\/a>. Examples of these plugins are Gatsby <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-styled-components\/\" target=\"_blank\" rel=\"noopener\">styled components plugin<\/a> and <a href=\"https:\/\/www.gatsbyjs.com\/plugins\/gatsby-plugin-emotion\/\" target=\"_blank\" rel=\"noopener\">emotions plugin<\/a>, which provide support for using <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/styling\/styled-components\/\" target=\"_blank\" rel=\"noopener\">styled-components<\/a> and <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/styling\/emotion\/\" target=\"_blank\" rel=\"noopener\">emotions<\/a> libraries respectively.<\/p>\n\n\n\n<p>We can also implement some minor font optimization techniques by reducing the font file size, <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/styling\/using-web-fonts\/#self-host-google-fonts-with-fontsource\" target=\"_blank\" rel=\"noopener\">store the font file locally<\/a> instead of installing it from an external source, and avoid including font extensions that you don\u2019t need.<\/p>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Optimize images and media assets:<\/strong> As mentioned in the previous SEO section, the <a href=\"https:\/\/www.gatsbyjs.com\/docs\/how-to\/images-and-media\/using-gatsby-plugin-image\/\" target=\"_blank\" rel=\"noopener\">Gatsby image plugin<\/a> handles the most part of optimizing images and media-related files. This includes reducing the image file size, using a placeholder during image fetch, and delaying work for images that are not currently visible to the user within the scope of the screen (also called not above the fold).<\/li>\n<\/ol>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li><strong>Use CDN for caching:<\/strong> CDNs are known for boosting website performance by caching static content closer to the end user. Implementing proper CDN caching policies can reduce the network latency caused by retrieving the content from the origin servers each time.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Gatsby is a web framework for building fast, scalable, and SEO-friendly websites. It uses SSG pre-rendering techniques to optimize website performance and improve user experience. Gatsby also has the ability to load data from a variety of data sources using GraphQL. This offers great flexibility in generating the content of the web pages created by Gatsby.<\/p>\n\n\n\n<p>In this guide, we covered the fundamental concepts of Gatsby and why we should use it for building a website. We used UpCloud high performance servers to install Gatsby and set up our first project. Then we tested our Gatsby project in the development mode and also in the production mode by using Nginx. Finally, we explored some techniques that we can use in Gatsby to optimize our website SEO and performance.<\/p>\n\n\n\n<p>Ready to deploy your SEO-friendly and performance-optimized Gatsby website in the Cloud? <a href=\"https:\/\/signup.upcloud.com\/\">Try UpCloud<\/a> now and explore a rich set of Cloud services that will help satisfy your website requirements.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQs<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>What is Gatsby, and why is it great for SEO?<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Gatsby is a modern framework for building static sites. It optimizes speed, ensures accessibility, and integrates components for different SEO optimization techniques.<\/p>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>How do I install Gatsby on a server?<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Install Node.js and Gatsby CLI, create a project, and test it locally. This guide provides step-by-step installation instructions.<\/p>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>How can I deploy a Gatsby site on UpCloud?<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Use <code>gatsby build<\/code> to generate static files, then deploy them on an Nginx server.<\/p>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>What makes Gatsby fast and high-performing?<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Gatsby pre-renders static assets, uses image optimization plugins, and leverages caching for blazing-fast load times.<\/p>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li><strong>Why is UpCloud the best hosting option for Gatsby websites?<\/strong><br><br>UpCloud provides high-speed SSD storage, scalable infrastructure, and global data centers, making it ideal for fast-loading Gatsby sites.<\/li>\n<\/ol>\n","protected":false},"author":85,"featured_media":49221,"comment_status":"open","ping_status":"closed","template":"","community-category":[250],"class_list":["post-1906","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/1906","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/users\/85"}],"replies":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/comments?post=1906"}],"version-history":[{"count":0,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/1906\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/media?parent=1906"}],"wp:term":[{"taxonomy":"community-category","embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/community-category?post=1906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}