- Make your WordPress Rest API queries easy with GraphQL and Gatsby
With the web ecosystem steadily moving towards JAMstacks, JavaScript framework and serverless apps, we created this tutorial to help you build a static WordPress website with GatsbyJS, GraphQL and ReactJS.
Each step of the tutorial will go through the basics and also includes extra details in case you want to dive deeper.
You can also checkout the "workshop-wordpress-gatsby-react" folder to see the final results of the tutorial.
Feel free to suggest with improvements and updates, and contribute to this training repository.
@WordPress #HeadlessCMS @GatsbyJS @GraphQL @ReactJS @SurgeSH
-
You can use the browser of your choice to follow this workshop, but Chrome is the one I'm using.
-
You can also use the IDE of your choice, but I recommend you to install VSCode. It's easy to use, works very well with JavaScript and a built-in terminal (that you will have to use).
-
NodeJS is not a framwork. It's a JavaScript runtime, a low-level server environment. It is closer to C than languages interpreted as PHP, Ruby or Python. Choose the LTS (Long Terme Support) version.
-
Install NPM
NPM (Node Package Manager) makes it easy for JavaScript developers to share and reuse code, and makes it easy to update the code that you’re sharing, so you can build amazing things. It's distributed with Node.js, which means that when you download Node.js, you automatically get npm installed on your computer.
To check if you have Node.js installed, run this command in your terminal:
node -v
To confirm that you have npm installed you can run this command in your terminal:
npm -v
Instead of using NPM, you can use Yarn as well.
-
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. You will need to be able to generate website with Gatsby. :warning: If you are not able to install it, don't worry, there is a gatsby sarter available in this tutorial named
gatsby-starter
. Download it, then do the rest of the workshop inside this project.
🌟 Extra: Install NVM
How install NVM
NVM means "Node Version Manager". It's a:
Simple bash script to manage multiple active node.js versions. — NVM, Github
Once it's installed, you may have to restart your terminal. You can install the wanted NodeJS version and use it like this:
nvm install 10.16.0
nvm alias default 10.16.0
You can install any nodeJS version you want and use it like that. For this workshop, we will be using the NodeJS version 10.16.0.
After running these commands, you might need to open a new shell for them to take effect.
You will not need to install a WordPress. You can use this url wcpboston.eelab.space
.
Something very cool with Gatsby is that you can very easily change the WordPress to the one you want just by changing one line in your code.
Gatsby is a React-based, GraphQL powered, static site generator. What does that even mean? Well, it weaves together the best parts of React, webpack, react-router, GraphQL, and other front-end tools in to one very enjoyable developer experience. Don’t get hung up on the moniker "static site generator". That term has been around for a while, but Gatsby is far more like a modern front-end framework than a static site generator of old.
It uses powerful preconfiguration to build a website that uses only static files for incredibly fast page loads, service workers, code splitting, server-side rendering, intelligent image loading, asset optimization, and data prefetching.
You code and develop your site, Gatsby transforms it into a directory with a single HTML file and your static assets. This folder is uploaded to your favorite hosting provider, and voila.
In order to generate a Gatsby website, we will use Gatsby CLI. First, from the terminal, do:
npm install -g gatsby-cli
Then, to generate the website, go to your favorite location, then do:
gatsby new workshop-wordpress-gatsby-react
Then, move to this directory
cd workshop-wordpress-gatsby-react
Install dependencies:
npm install
And finally, to start the development server, do:
gatsby develop
And now, your website will be available to http://localhost:8000/.
npm rebuild
.
- .cache/: This folder is an internal cache created automatically by Gatsby. The files inside this folder are not meant for modification. Should be added to the .gitignore file if not added already.
- node_modules/: All modules installed by the package.json file. This folder is ignored by git.
- public/: This folder is the build directory. It is also ignored by git.
- src/: Here is where the magic happens. You will find everything you need to build the website inside this folder. =>
- components/: they are the building blocks of any React app. It’s a JavaScript class or function that optionally accepts inputs i.e. properties(props) and returns a React element that describes how a section of the UI (User Interface) should appear.
- pages/: Files in this folder become pages automatically with paths based on their file name. Here is the full documentation.
- templates/: You don't have this folder at the beginning but it will contains templates for programmatically creating pages. Here is the full documentation
- gatsby-browser.js: This is where you put your custom JavaScript. You will have to use Gatsby browser API to make it works. Here is the documentation.
- gatsby-config.js: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. Here is the full documentation.
- gatsby-node.js: This is where you will customize your path, create your page, your single page (files in template folder) … Here is the full documentation.
- gatsby-ssr.js: This file is where Gatsby expects to find any usage of the Gatsby server-side rendering APIs. We are not using it but here is the full documentation.
- package.json: This is where you will add all your modules and scripts that you need for you website.
Create a page with Gatsby is very simple, any React component defined in src/pages/*.js
will automatically become a page.
For instance, let's create a page called posts.js
and past the following code into it:
import React from "react"
export default (props) => {
return (
<h1>Posts page</h1>
)
}
If the server is still running (otherwise, at the root project folder, run the following command from the terminal gatsby develop
), you can now navigate to http://localhost:8000/posts/
and your new page will be accessible.
For that, we will have to install a new Gatsby plugin, gatsby-source-wordpress. It's very simple, open a new terminal window at the root the project and just do the installation by this simple command line: (The --save tag means that a new line with the plugin slug and his version will be added to the package.json file)
npm install --save gatsby-source-wordpress
Once you've installed the plugin, open gatsby-config.js
and paste the following code in the plugins array, at ligne 30 (it's part for the documentation but with only what we need):
{
resolve: "gatsby-source-wordpress",
options: {
/*
* The base URL of the Wordpress site without the trailingslash and the protocol. This is required.
* Example : 'gatsbyjsexamplewordpress.wordpress.com' or 'www.example-site.com'
*/
baseUrl: "wcpboston.eelab.space", // or your custom WordPress url
// The protocol. This can be http or https.
protocol: "https",
// Indicates whether the site is hosted on wordpress.com.
// If false, then the assumption is made that the site is self hosted.
// If true, then the plugin will source its content on wordpress.com using the JSON REST API V2.
// If your site is hosted on wordpress.org, then set this to false.
hostingWPCOM: false,
// If useACF is true, then the source plugin will try to import the Wordpress ACF Plugin contents.
// This feature is untested for sites hosted on Wordpress.com.
// Defaults to true.
auth: null,
useACF: true, // Allows to pull ACF fields
// Set verboseOutput to true to display a verbose output on `npm run develop` or `npm run build`
// It can help you debug specific API Endpoints problems.
verboseOutput: false,
// Exclude specific routes using glob parameters
// See: https://github.com/isaacs/minimatch
// Example: `["/*/*/comments", "/yoast/**"]` will exclude routes ending in `comments` and
// all routes that begin with `yoast` from fetch.
excludedRoutes: ["/*/*/comments", "/yoast/**"],
// use a custom normalizer which is applied after the built-in ones.
normalizer: function({ entities }) {
return entities
},
},
},
We are now able to pull data into Gatsby from WordPress using the WordPress REST API.
NOTE: Every time you modify this file, you will have to restart the server. Press control+c
(ctrl+c
for windows) to stop the server if it's still running, then:
gatsby develop
By default, WordPress don't add data from ACF, Menus, WPLM... in his REST-API so you will have to install a few plugins to your WordPress in order to be able to have those data available with GraphQL.
Show usefull plugins
-
ACF
You will have to first, set the
useACF
property totrue
fromgatsby-source-wordpress
settings ingatsby-config.js
file, and secondly, have the plugin acf-to-rest-api installed in WordPress. -
Menus
You will have to add the plugin wp-api-menus which gives you the menus and menu locations endpoint.
-
WPML
You will have to add the plugin wpml-rest-api which adds the current locale and available translations to all post types translated with WPML.
-
YOAST
You will have to add the plugin wp-api-yoast-meta which allows you to pull the yoast_meta: {...}
GraphQL is a query language (the QL part of its name). If you’re familiar with SQL, it works in a very similar way. Using a special syntax, you describe the data you want in your component and then that data is given to you.
Gatsby uses GraphQL to enable components to declare the data they need.
When you started the server, a second link was displayed in the terminal: http://localhost:8000/___graphql. This is where you can test you query or explore the types and properties of your GraphQL.
Let's learn how to query your data with GraphQL!
Basically, to query contents from WordPress, it would be very similar to:
{
allWordpress${Manufacturer}${Endpoint} {
edges {
node {
id
// Put your fields here
}
}
}
}
where ${Manufacturer}
is the endpoint prefix and ${Endpoint}
is the name of the endpoint from the WordPress URL:
https://wcpboston.eelab.space/wp-json/${Manufacturer}/v2/${Endpoint}
So, for instance, for all posts, url will be:
https://wcpboston.eelab.space/wp-json/wp/v2/posts
and the GraphQL will be:
{
allWordpressPost {
edges {
node {
id
slug
title
content
}
}
}
}
It's almost exactly the same for pages, except that the ${Endpoint}
is different:
https://wcpboston.eelab.space/wp-json/wp/v2/pages
and the GraphQL will be:
{
allWordpressPage {
edges {
node {
id
slug
title
content
excerpt
date
modified
status
}
}
}
}
As you can see, the differences are the Query Type
(allWordpressPost
for posts and allWordpressPage
for pages) and the fields in the node object.
Doing that, you should have this result on the right:
If you don't know which properties are available in GraphQL, you can press Shift+Spacebar
on mac or Ctrl+spacebar
on Windows.
All of that is nice, but how are we implement that for the front-end. It's now ReactJS time!
Arguments are used to filter, limit, skip or sort your results from your query. There are applyed to the query type.
Explore how to use arguments in your query
The sort argument allows you to change the order of your rendered data. It's an object and accepts two properties: the fields name (you can sort on multiple fields, the second sort field gets evaluated when the first field is identical) and the order. By defaut, it's based on the ASC order.
export const query = graphql`
query {
allWordpressPost(
sort: {
fields: [title]
order: DESC
}
) {
edges {
node {
id
title
content
}
}
}
}
`
Your data are now order by the field title and by DESC. Note that [] around the field name are optionnal when there is only one field.
export const query = graphql`
query {
allWordpressPost(
sort: {
fields: [title, status]
order: DESC
}
) {
edges {
node {
id
title
content
}
}
}
}
`
Your data are now order by the fields title and status and by DESC. Each field has to be separated by a comma.
The limit argument allows you to display a certain number of content. It requires an Int as a value:
export const query = graphql`
query {
allWordpressPost(limit: 6) {
edges {
node {
id
title
content
}
}
}
}
`
In this example, we will display only the 6 first last added posts.
The skip argument allows you to skip over a number of results. It requires an Int as a value:
export const query = graphql`
query {
allWordpressPost(skip: 6) {
edges {
node {
id
title
content
}
}
}
}
`
In this example, we will omit the 6 first posts.
The filter argument allows you to filter your data according a specifif field value with an operator. Here is the list (part of the documentation):
- eq: short for equal, must match the given data exactly
- ne: short for not equal, must be different from the given data
- regex: short for regular expression, must match the given pattern. Note that backslashes need to be escaped twice, so /\w+/ needs to be written as "/\\w+/".
- glob: short for global, allows to use wildcard * which acts as a placeholder for any non-empty string
- in: short for in array, must be an element of the array
- nin: short for not in array, must NOT be an element of the array
- gt: short for greater than, must be greater than given value
- gte: short for greater than or equal, must be greater than or equal to given value
- lt: short for less than, must be less than given value
- lte: short for less than or equal, must be less than or equal to given value
- elemMatch: short for element match, this indicates that the field you are filtering will return an array of elements, on which you can apply a filter using the previous operators
For instance, let's filter our posts according to the category named "Boston". First, we have to specify the type, so category: TODO: rajouter le body de la query pour tous les filters
allWordpressPost(
filter: {
categories: {
...
}
}
) {
edges {
node {
id
title
content
}
}
}
Then, we add the operator. We will use elemMatch:
allWordpressPost(
filter: {
categories: {
elemMatch: {
...
}
}
}
) {
edges {
node {
id
title
content
}
}
}
And finally, we have to specify which field we want from the categeory and its value with the eq operator. Let's go with the name.
allWordpressPost(
filter: {
categories: {
elemMatch: {
name: {
eq: "Boston"
}
}
}
}
) {
edges {
node {
id
title
content
}
}
}
The query will only render posts that has the category Boston.
Instead of duplicating your query in multiple component, you can use fragments.
Explore how to declare and use a fragment:
fragment FragmentName on TypeName {
field1
field2
}
It consists of three parts:
- FragmentName: the name of the fragment that will be referenced later, the one of your choice.
- TypeName: the GraphQL type of the object the fragment will be used on. The easiest way to find the GraphQL type is by using the Documentation Explorer from GraphiQL (with the following url: http://localhost:8000/___graphql)
- The body of the query: You can define any fields with any level of nesting in here, like you can do for any other GraphQL query.
Let's see how to create a fragment for all WordPress posts now:
fragment allPosts on wordpress__POSTConnection {
edges {
node {
id
title
date
}
}
}
So here, allPosts is the FragmentName, wordpress__POSTConnection is the TypeName that we found for the GraphiQL Documentations Explorer, and the edges object is the body of the query.
Once our fragment is declared, we can use it in our query by calling the FragmentName preceded by three dots:
{
allWordpressPost {
...allPosts
}
}
Note: When compiling your site, Gatsby preprocesses all GraphQL queries it finds. Therefore, any file that gets included in your project can define a snippet. However, only Pages can define GraphQL queries that actually return data. This is why we can define the fragment in the component file, it doesn’t actually return any data directly. That's why it's a good pratice to create a file who contains all your fragments and, then you call your fragments in your pages, templates, but not in your components.
So, let's do it!
Create a new file in components
folder named fragments.js
, then import graphql
library, and finally create your fragments based with our previous example. Don't forget to export it.
import { graphql } from 'gatsby';
export const fragments = graphql`
fragment allPosts on wordpress__POSTConnection {
edges {
node {
id
title
content
date(formatString: "dddd DD MMMM YYYY")
}
}
}
`
By default, date will be printed as ISO-8601 format. You can format it by adding the formatString function and then give the wanted format:
date(formatString: "dddd DD MMMM YYYY")) // Week day day month year
Finally, you can use your fragments named allPosts
in all wanted pages.
Open your posts.js
file and replace the previous query by calling our fragment:
export const query = graphql`
query {
allWordpressPost {
edges {
node {
id
title
content
}
}
}
}
`
will become:
export const query = graphql`
query {
allWordpressPost {
...allPosts
}
}
`
Note: If you want to run two queries on the same page, you can use an alias. See below based on the previous fragment example:
export const query = graphql`
query {
firstQuery: allWordpressPost(limit: 6) {
...allPosts
}
secondQuery: allWordpressPost(skip: 6) {
...allPosts
}
}
`
So now, instead of using the query name to call your data, you will use the alias. In this example, it would be data.firstQuery or data.secondQuery instead of data.allWordpressPost
Inside the post page that we created earlier posts.js
, import and the Layout
component to keep the header and footer, and wrap the h1 html tag with the new component:
import React from "react"
import Layout from "../components/layout"
export default (props) => {
return (
<Layout>
<h1>Posts page</h1>
</Layout>
)
}
If you server is still running, it should have compiled.
If you go back to the website, you should be able to visit this page: http://localhost:8000/posts
Let's now display all posts title and his content! To do so, it's very simple. You first need to import graphql
from gatsby at the top of your file:
import { graphql } from 'gatsby'
Then after your function, you just need to export a variable who contains the graphql query:
export const query = graphql`
query {
allWordpressPost {
edges {
node {
id
title
content
}
}
}
}
`
And finally, you can update your function to display the content. Because GraphQL returns us an array, you will have to loop throught it:
export default (props) => {
return (
<Layout>
<h1>Posts page</h1>
{props.data.allWordpressPost.edges.map(post => {
return (
<div key={post.node.id}>
<h2 dangerouslySetInnerHTML={{ __html: post.node.title }} />
<div dangerouslySetInnerHTML={{ __html: post.node.content }} />
</div>
)
})}
</Layout>
)
}
Querying with Graphql will returns us an object data (it's always data!). Inside this object, we have another object allWordpressPost (the one we specify from our query, it will be allWordpressPages if we want all pages for instance) and inside this one, we have another one edges who is basically an array of objects which contains all our data, that's why we are using the map() function to loop throught the array.
If you go back to the website, all posts form WordPress are displayed! But you've probably notice that something is not good, HTML is not striped. it's because by default, React escapes the HTML to prevent XSS (Cross-site scripting). So to render HTML, we have to add the following property to our HTML tag:
dangerouslySetInnerHTML={{ __html: ... }}
dangerouslySetInnerHTML is React's replacement for using innerHTML in the browerDOM.
So, your function should looks like that now:
{props.data.allWordpressPost.edges.map(post => {
return (
<div key={post.node.id}>
<h2 dangerouslySetInnerHTML={{ __html: post.node.title }} />
<div dangerouslySetInnerHTML={{ __html: post.node.content }} />
</div>
)
})}
And now, your content is rendered properly!
StaticQuery
called useStaticQuery
, that allows components to retrieve data via GraphQL query (we will see later how yo use it).
If you want to create dynamic template, like single post, you will have to do a few more things.
Explore how to create a single post
In order to create single post, you will have to create a new folder in src/
named templates
and insite this new folder, create a file named post.js
. And, paste the following code in it:
import React from "react"
import Layout from "../components/layout"
export default (props) => {
return (
<Layout>
<h1>Post template</h1>
</Layout>
)
}
Good! Now, the last think you will have to do is to use a hook from Gatsby APIs: createPages
, and you have to do that inside the gatsby-node.js
file. So, open this file, and first, import those two modules at the top of the file:
const Promise = require('bluebird')
const path = require('path')
Then, you can implemente the createPages
hook by doing the following:
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
graphql(`
{
allWordpressPost {
edges {
node {
id
slug
}
}
}
}`
).then(result => {
// Create posts pages.
result.data.allWordpressPost.edges.forEach(({ node }) => {
createPage({
path: `/post/${node.slug}/`,
component: path.resolve(`./src/templates/post.js`),
context: {
id: node.id,
},
})
})
resolve()
})
})
}
createPage
function belongs to createPages hook
and it will be called by Gatsby whenever a new node is created and create a page for you. See the documentation for more informations.
Inside your Promise, this is where you put your wanted GraphQL query. Because we want to create a single post, we need to retrieve all posts, then loop through all of them. createPage
function accepts a few parameters, and you will need path
and component
.
- path: url of your single post. It must start with a forward slash.
- component: absolute path to the template that you will use to display your single post.
You can find all the documentation here.
Finally, restart your server. Don't forget to stop your server: from your terminal, press ctr+c
, and then run the following command gatsby develop
to start it.
But, we are not done yet! There is a last thing to do: add links to your posts.
Open the posts.js
file in src/pages/
folder, then at the top of your file, import a new component from Gatsby, <Link />
. Because you already have imported graphql
from gatsby, replace the former line with this one:
import { graphql, Link } from 'gatsby'
The Gatsby <Link />
component is for linking between pages within your site.
Then, update your graphQL query to add the slug
field:
export const query = graphql`
query {
allWordpressPost {
edges {
node {
slug
id
title
content
}
}
}
}
`
Finally, wrap the title with the <Link />
component by doing the following:
<Link to={`post/${post.node.slug}`}>
<h2 dangerouslySetInnerHTML={{ __html: post.node.title }} />
</Link>
So your function should looks like that:
export default (props) => {
return (
<Layout>
<h1>Posts page</h1>
{props.data.allWordpressPost.edges.map(post => {
return (
<div key={post.node.id}>
<Link to={`post/${post.node.slug}`}>
<h2 dangerouslySetInnerHTML={{ __html: post.node.title }} />
</Link>
<div dangerouslySetInnerHTML={{ __html: post.node.content }} />
</div>
)
})}
</Layout>
)
}
Navigate now to your posts page http://localhost:8000/posts
, and click on a post title. You should be able to see the title Post template
.
Ok! That's cool! But what if we want to display data from a single post ? Let's explore how to do that!
Open your post.js
file in src/templates
folder, and import graqhql
from gatsby at the top of the file:
import { graphql } from 'gatsby'
Then, at the bottom of the page, export the following graphQL query:
export const query = graphql`
query {
wordpressPost {
title
content
featured_media {
id
source_url
alt_text
}
}
}
`
Because we want to display data from one post, we are using the Query Type wordpressPost
. Now, title, content and the featured image are available for the front-end. Let's display them!
Replace the export function with the following code:
export default (props) => {
const singlePost = props.data.wordpressPost;
return (
<Layout>
<h1>{singlePost.title}</h1>
<img src={singlePost.featured_media.source_url}
alt={singlePost.featured_media.alt_text}
/>
<div dangerouslySetInnerHTML={{ __html: singlePost.content }} />
</Layout>
)
}
If you now visite a single post page, you will be able to see the title, a featured image and the content. Amazing!
In order to apply Gutenberg block styles to your website, there is a few steps to follow.
See all steps
- First, stop the development server if it's still running:
control+c
orctrl + c
for windows. - Then retrieve the CSS file in
/wp-includes/css/dist/block-library
namedstyle.min.css
. - Then Create a folder named styles in
src/
and put thestyle.min.css
file from WordPress - Then, in
gatsby-browser.js
file, import this file with this line:
import "./src/styles/block-library.min.css";
- Finally, restart the development server:
gatsby develop
You will have to first, set the useACF
property to true
from gatsby-source-wordpress
settings in gatsby-config.js
file, and secondly, have the plugin acf-to-rest-api installed in WordPress.
Then, restart your server (control+c
or ctrl+c
for windows, to stop it, then gatsby develop
to start it).
Let's use the following example:
Each post has a link (htts://www.google.ca), this link is an Advanced Custom Field from WordPress.
In order to retrieve this field, from the all posts query, you just need to add a new field:
export const query = graphql`
query {
allWordpressPost {
edges {
node {
id
title
content
acf {
field_url
}
}
}
}
}
`
And now, update your render function to display this field:
<a target="_blank" rel="noopener noreferrer" href={post.node.acf.field_url}>
{post.node.acf.field_url}
</a>
So, your function should looks like the following:
export default (props) => {
return (
<Layout>
<h1>Posts page</h1>
{props.data.allWordpressPost.edges.map(post => {
return (
<div key={post.node.id}>
<h2 dangerouslySetInnerHTML={{ __html: post.node.title }} />
<div dangerouslySetInnerHTML={{ __html: post.node.content }} />
<a target="_blank" rel="noopener noreferrer" href="{post.node.acf.field_url}">
{post.node.acf.field_url}
</a>
</div>
)
})}
</Layout>
)
}
You will have to add the plugin [wp-api-menus] to WordPress (https://wordpress.org/plugins/wp-api-menus/) which gives you the menus and menu locations endpoint to the REST-API (we already added this plugin to our WordPress in order to be available for you).
Then add your pages, links, etc into WordPress Menus, restart your server (don't forget to do it, otherwise, you won't be able to pull your data with GraphQL)
To query menus from the REST-API, the ${Manufacturer}
is WpApiMenus
and the ${Endpoint}
is MenusItems
. This is the query:
allWordpressWpApiMenusMenusItems {
edges {
node {
items {
title
object_slug
}
}
}
}
Gatsby already has a Layout
component in src/components/
, so it's a good place to add your menu query. Open the layout.js
file, and inside useStaticQuery
, past our menu query:
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
allWordpressWpApiMenusMenusItems {
edges {
node {
items {
title
object_slug
}
}
}
}
}
`)
NOTE: By default, file inside src/components folder cannot accept graphQL query, but Gatsby v2.1.0 introduces a hooks version of StaticQuery called useStaticQuery, a new API that allows components to retrieve data via GraphQL query. See the full documentation here.
We can finally render the menus with React:
<nav>
<ul>
{nav.edges[0].node.items.map((node, index) => {
return (
<li key={index}>
<Link to={"/" + node.object_slug}>{node.title}</Link>
</li>
)
})}
</ul>
</nav>
To build a produciton version, Gatsby provide us a command who produce a directory of static HTML and JavaScript files (public folder) which you can deploy to a static site hosting service.
Simply do the following command gatsby build
at the root of the project folder.
A few secondes later, Gatsby should have create a public
folder. We will deploy this folder in the next step.
Surge is one of many "static site hosts" which make it possible to deploy Gatsby sites.
In order to be able to use it, follow the next steps:
- Install Surge with the following command:
npm install --global surge
- Then, deploy your site:
surge public/
. If it's the firsts time, you will have to create an account (don't worry, it's free!). Enter your email, password, and press enter to confirm that the path to your public/ folder is correct. - Bonus: To ensure future deploys are sent to the same location, you can remember a domain. For instance, if your website was deployed to http://amazing-website.surge.sh/, run the following command:
surge --domain amazing-website.surge.sh
. The next time yo will run thesurge
command, it will deploy to the same domain.
Logos: WordPress, Gutenberg, Gatsbyjs, Graphql, Reactjs, Surge.sh