In my first post, I talked about the basic steps to configure and deploy this Gatsby-Starter-WordPress-Blog. However, I wanted my first portfolio website to include more than just a blog index, so I decided to add a Home page to it. The process of creating a custom portfolio with a home page and a blog is quite simple, and you can easily follow the steps to develop your own version.
Step 1: Install Starter Template
Follow the steps in My First Blog Post to clone this GitHub repo: https://github.com/gatsbyjs/gatsby-starter-wordpress-blog
Step 2: Review the Template Structure
Let’s start by reviewing some of the key files includes in the starter template /src folder.
Within the src/components folder you should have three component files:
- Layout.js
- Seo.js
- Bio.js
In this project, the layout component will define the overall look and feel for both your home page, blog index, and individual blog posts. The Bio.js component is used at the end of every blog post to share information about the author. The seo.js file contains metadata and SEO attributes from your WordPress account. These reusable UI elements are used throughout your website, so modify them with care.
Next, within the src/pages subfolder, you will find a single file:
- 404.js
This is a static 404 page that is displayed when a user navigates to a URL that is not defined.
You will notice that there is not a component or a page specifically for the blog index page or individual blog posts. That’s because those pages are created dynamically during the site build process, utilizing the createPages API from Gatsby and the templates files within the src/templates folder. The settings that control how those pages are built are actually found within the gatsby-node.js file. For more information on how that works, check out the gatsby documentation here: https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/
Step 3: Create the Home Page
For this starter project, you can imagine the components subfolder to contain typical reusable UI elements and the pages subfolder to contain “static” pages. Any pages that need to read data from the WordPress API and dynamically display data will be handled by the createPages function and the gatsby-node.js file.
Our homepage is static, so let’s go ahead and create a new file called “index.js” within the pages folder.
*Note: you can name this “Home.js” or any other name you wish, but “Index” is a standard naming convention used by many tools to identify the base file the browser should initially launch. If you use a different file name, keep that in mind as a potential setting you might need to update when using various tools such as hosting or debugging sites and apps.
Open your Index.js and paste the following code:
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
const Index = ({ data, location }) => {
const siteTitle = data.site.siteMetadata.title
return (
<Layout location={location} title={siteTitle} isHomePage={true}>
// home page here
</Layout>
)
}
export default Index
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
}
So far all we have is a bare-bones react component ready to add code, but by importing the layout component you are ensuring a consistent look and feel across all pages of your website.
For a simple homepage, you can create your home page UI directly in this file within the Layout tags. But if you have a more complex home page, for example, different sections for a hero image, about me, experience etc I recommend creating these sections as components and then importing these into your index.js like so:
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import Hero from "../components/home-page/Hero"
const Index = ({ data, location }) => {
const siteTitle = data.site.siteMetadata.title
return (
<Layout location={location} title={siteTitle} isHomePage={true}>
<Hero />
</Layout>
)
}
export default Index
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
}
`
Step 4: Create a Nav Bar
OK, now we have a new index.js file representing our homepage and our createPages API will create the blog-post-archive and the individual blog-post pages. Next, we need to create a nav bar that will allow us to navigate between all these pages.
Navigate to the src/components subfolder and open the layout.js file. At the top of the return statement is a <header> tag with the following code:
<header className="global-header">
{isHomePage ? (
<h1 className="main-heading">
<Link to="/">{parse(title)}</Link>
</h1>
) : (
<Link className="header-link-home" to="/">
{title}
</Link>
)}
</header>
This is a pretty neat dynamic header that checks if the current page is the home page. If it is, it shows the title of the site in an <H1> tag, and if it is not, it shows a link to go back to the home page. But for my site, I wanted a persistent nav bar that always shows a route to go back home or to the blog index no matter what page the user is on.
To do this, inside the components folder, create a new file called navbar.js and create a basic react class with an empty div and a nav element:
import React, { Component } from "react";
import { Link } from "gatsby";
class NavBar extends Component {
render() {
return (
<div>
<nav>
</nav>
</div>
);
}
}
export default NavBar;
Within this <nav> tag you can create any nav bar you wish. Mine is very simple but you can copy the following code if you wish:
import React, { Component } from "react";
import { Link } from "gatsby";
import * as styles from "../styles/navbar.module.css"
class NavBar extends Component {
render() {
return (
<div>
<nav>
<div className={styles.navbar}>
<a className={styles.navbarBrand} href="/">
Saul Belisle
</a>
<ul className={styles.navbarList}>
<li className={styles.navItem}>
<Link className={styles.navLink} to="/blog">
Blog
</Link>
</li>
</ul>
</div>
</nav>
</div>
);
}
}
export default NavBar;
What I have done is defined two navbar sections.
- A <div> with an <a> tag = “/”, which is labeled with my name.
- An unordered list tag with a single <li> containing a <Link> to “/blog”
The reason I used both a <a> tag and a <Link> tag was to achieve a specific style and it will allow me to easily add more navigation items after “/blog” in the future. You can also see that I am importing styles from another folder and have applied classNames to the various components. More on that at the end.
We can now go back to the Layout.js file and remove the dynamic <header> and instead import our Navbar component. The Layout.js file should now look like this:
import React from "react"
import {useStaticQuery, graphql } from "gatsby"
import NavBar from './navbar';
const Layout = ({ isHomePage, children }) => {
const {
wp: {
generalSettings: { title },
},
} = useStaticQuery(graphql`
query LayoutQuery {
wp {
generalSettings {
title
description
}
}
}
`)
return (
<div className="global-wrapper">
<NavBar/>
<main>{children}</main>
//rest of component
Now we have a home page created at index.js and a navbar with links to “/” and “/blog.” The final step is to create a path to the blog-post-archive at “/blog.”
Step 5: Update getPagePath Function
Now, for the first time, let’s open up the gatsby-node.js file and take a look at the function createBlogPostArchive():
/**
* This function creates all the individual blog pages in this site
*/
async function createBlogPostArchive({ posts, gatsbyUtilities }) {
const graphqlResult = await gatsbyUtilities.graphql(/* GraphQL */ `
{
wp {
readingSettings {
postsPerPage
}
}
}
`)
const { postsPerPage } = graphqlResult.data.wp.readingSettings
const postsChunkedIntoArchivePages = chunk(posts, postsPerPage)
const totalPages = postsChunkedIntoArchivePages.length
return Promise.all(
postsChunkedIntoArchivePages.map(async (_posts, index) => {
const pageNumber = index + 1
const getPagePath = page => {
if (page > 0 && page <= totalPages) {
// Since our homepage is our blog page
// we want the first page to be "/" and any additional pages
// to be numbered.
// "/blog/2" for example
return page === 1 ? `/` : `/blog/${page}`
}
return null
}
// createPage is an action passed to createPages
// See https://www.gatsbyjs.com/docs/actions#createPage for more info
await gatsbyUtilities.actions.createPage({
path: getPagePath(pageNumber),
// use the blog post archive template as the page component
component: path.resolve(`./src/templates/blog-post-archive.js`),
// `context` is available in the template as a prop and
// as a variable in GraphQL.
context: {
// the index of our loop is the offset of which posts we want to display
// so for page 1, 0 * 10 = 0 offset, for page 2, 1 * 10 = 10 posts offset,
// etc
offset: index * postsPerPage,
// We need to tell the template how many posts to display too
postsPerPage,
nextPagePath: getPagePath(pageNumber + 1),
previousPagePath: getPagePath(pageNumber - 1),
},
})
})
)
}
This function is designed to scan all the available blog posts in your WordPress CMS and compile a list of all the posts in order to create an index. This index is then used to create the “home page” of your Gatsby starter project, which can be found at the path “/”.
As part of its operations, the function makes use of another function known as getPagePath(). The latter function examines the current page that is being generated. If it is the first page, then it assigns to it the URL path of “/”. However, if the page number is greater than 0 and less than the total number of pages, it creates a new URL path in the format of “/blog/${page}”, where ${page} represents the page number. For instance, if the page number is 2, the URL path would be “/blog/2”. Furthermore, the function increments the page number for each additional page generated.
const getPagePath = page => {
if (page > 0 && page <= totalPages) {
// Since our homepage is our blog page
// we want the first page to be "/" and any additional pages
// to be numbered.
// "/blog/2" for example
return page === 1 ? `/` : `/blog/${page}`
}
return null
}
But in the new version of our site, the index.js file should be found at the path “/.” So we will update this formula so that the blog index is found at “/blog” and every subsequent blog post is numbered “/blog/${page}”
// return page === 1 ? `/` : `/blog/${page}`
return page === 1 ? `/blog/` : `/blog/${page}`;
That’s it! Our homepage will be featured at the base URL path “/” and the createBlogPostArchive() function will use a path prefix “/blog” for all dynamically created pages.
Step 6: CSS and Styles
Finally, make it your own. This is outside the scope of this blog post, but you will want to personalize your site with your own branding, colors and css choices. This blog has an incredible summary of the different methods available to you: https://css-tricks.com/different-ways-to-write-css-in-react/. In Step 4, you may have noticed that I used a combination of global style sheets and CSS Modules in my navbar code snippet.
Conclusion
To modify the https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-wordpress-blog and add a static homepage, you can follow these simple steps:
- Add an index.js file within the pages folder, and create your desired homepage.
- Create a navbar component and import it into your layout.js component.
- Finally, update the getPagePath function to create new pages with a “/blog” path prefix.
By following these steps, you will successfully modify https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-wordpress-blog to include a static home page.