Moe Loubani Software Developer / Development Consultant

Building My New Site – Getting Started

Having used WordPress since 2007 (and developed for it since 2010) I have seen a lot of trends come and go. I remember before custom post types were around and everyone had to use posts categorized in a certain way instead. And then came custom post types and WordPress started turning more and more into the full fledged CMS that it is today.

Still, the most interesting of all of the trends has to me been the latest push towards decoupling the front and back end of a website and that was my aim when I built the website you’re on. And hey – when it comes to making a fast site it seems to have worked!

So the first step was to find a theme: I went to Themeforest and looked for an HTML theme (not a WordPress one) that I liked the look of. Once I found one I liked it was time to get started creating a NextJS project..but I had never done it before. Luckily I was able to find this great React course that helped me along and once I finished that (over a looong time) it was time to start writing some code.

My first step was to set up a WordPress site to use as the backend. I headed over to DigitalOcean and created a droplet there and mapped it to a subdomain. Then I installed some plugins: Advanced Custom Fields to add a little extra data and WPGraphQL to be able to query that data in an efficient way (and also learn GraphQL at the same time).

Once those were set up it was time to set up the NextJS project. I started with the setup that you get when you run

npx create-next-app@latest

Then you follow the steps there and give your project a name, I chose not to go with Typescript (that is next on my queue of things to learn).

I’m using Visual Studio Code here and this is what you should see now when you open your new project and navigate to index.js in the pages folder:

Now we are going to start building the pages for the new site (I’ll come back to the nav bar and sidebar/header in my next post). Make sure you’re on index.js in the pages folder as this will be your home page. From here I’m going to go through the long process of clearing clutter from the template and adjusting it for what I wanted. Here is what my home page page/component looked like at this point:

import Head from "next/head";

function HomeNew(props) {
  return (
    <Fragment>
      <Head>
        <title>
          Moe Loubani - Software Developer and Development Consultant
          Specializing in WordPress
        </title>
        <meta
          name="description"
          content="I'm a software developer located in Waterloo, Ontario. My main area of focus is high traffic WordPress sites and WordPress plugin development and I also provide a consulting service for people looking to plan things out before undertaking a large project."
        />
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <section data-id="about-me">
        <AboutMe
          rightColumnPoints={props.rightColumnPoints}
          aboutMeText={props.aboutMeText}
        />
      </section>
    </Fragment>
  );
}

export default HomeNew;

Let’s break down what is going on here. First thing I’m doing is setting up the title and some meta tags and then I create a section that I’m going to put the contents of what was once the about me page (on the template). Instead of putting the all of that HTML right into the page I factored it out into an AboutMe component (to start) and to that I pass some data that I saved to my page with ACF.

import { Fragment } from "react";

function AboutMe({ aboutMeText, rightColumnPoints }) {
  return (
    <Fragment>
      <div className="page-title">
        <h2>
          About <span>Me</span>
        </h2>
      </div>
      <div className="row">
        <div className="col-xs-12 col-sm-7">
          <p>{aboutMeText}</p>
        </div>

        <div className="col-xs-12 col-sm-5">
          <div className="info-list">
            <ul>
              {rightColumnPoints.map((point) => {
                return (
                  <li key={point.label}>
                    <span className="title">{point.label}:  </span>
                    {point.label === "Phone" && (
                      <span className="value">
                        <a href={`tel:${point.text}`}>{point.text}</a>
                      </span>
                    )}
                    {point.label === "Email" && (
                      <span className="value">
                        <a href={`mailto:${point.text}`}>{point.text}</a>
                      </span>
                    )}
                    {point.label !== "Phone" && point.label !== "Email" && (
                      <span className="value">{point.text}</span>
                    )}
                  </li>
                );
              })}
            </ul>
          </div>
        </div>
      </div>
    </Fragment>
  );
}

export default AboutMe;

To get that data I use WPGraphQL on my WP back end so let’s connect to that. I know that I’m going to be doing this with a whole bunch of stuff so I created a new folder in my project directory called helpers where I’m going to put the functions that call the API so I create a file in there called api.js where I add the following:

export async function fetchAPI(query, { variables } = {}, wordPressURL = false) {
  const headers = { "Content-Type": "application/json" };

  if (process.env.WORDPRESS_AUTH_REFRESH_TOKEN) {
    headers[
      "Authorization"
    ] = `Bearer ${process.env.WORDPRESS_AUTH_REFRESH_TOKEN}`;
  }

  const body = JSON.stringify({
    query,
    variables,
  });

  if(!wordPressURL) {
    wordPressURL = process.env.WORDPRESS_API_URL;
  }

  const res = await fetch(wordPressURL, {
    method: "POST",
    headers,
    body,
  });

  const json = await res.json();

  if (json.errors) {
    throw new Error(JSON.stringify(json.errors));
  }

  return json.data;
}

And now it’s time to write the first GraphQL query to get the data for the about page. After setting up the two custom fields in ACF and assigning them to my homepage (and filling them out) I head over to the WPGraphQL plugin and I try out my query:

query getHomePage {
  page(id: "home", idType: URI) {
    title
    slug
    id
    homePage {
      aboutMeText
      whatIDoArea {
        iconClass
        title
        text
      }
      rightColumnPoints {
        label
        text
      }
      testimonials {
        testimonial
        company
        name
      }
    }
  }
  posts(first: 6) {
    edges {
      node {
        id
        title
        excerpt
        slug
        date
      }
    }
  }
}

This one query gets me a few things: the homepage title, the content, six posts to use in my latest posts section on the homepage and the contents of four different ACF fields. Three of those fields are repeater fields so I go a little further to get some specific data from those fields (whatIDoArea, rightColumnPoints, testimonials). I put this into a query to fetch that data:

export async function getHomePage() {
  const data = await fetchAPI(
    `
      query getHomePage {
        page(id: "home", idType: URI) {
          title
          slug
          id
          homePage {
            aboutMeText
            whatIDoArea {
              iconClass
              title
              text
            }
            rightColumnPoints {
              label
              text
            }
            testimonials {
              testimonial
              company
              name
            }
          }
        }
        posts(first: 6) {
          edges {
            node {
              id
              title
              excerpt
              slug
              date
            }
          }
        }
      }
      `,
    {
      variables: {},
    }
  );

  return data;
}

And now I make sure that that data is available to me in my homepage by making use of the getStaticProps function from NextJS (I add this to the bottom of my home page component).

export async function getStaticProps({ params }) {
  const homePageContent = await getHomePage();

  return {
    props: {
      ...homePageContent.page.homePage,
      posts: homePageContent.posts.edges,
    },
  };
}

In the above the posts are obviously the posts and the homePageContent.page.homePage comes from my ACF fields where I called the field group Home Page (notice that in NextJS the home-page slug becomes homePage and gets camelcased).

Now I keep going and add a few more components to round out the home page and now that component looks like this (I’ll be releasing the full code when this series is over):

import { Fragment } from "react";
import Head from "next/head";
import { getHomePage } from "../helpers/api";
import AboutMe from "../components/Content/AboutMe";
import WhatIDo from "../components/Content/WhatIDo";
import Testimonials from "../components/Content/Testimonials";
import HomeBlogPosts from "../components/Content/HomeBlogPosts";

function HomeNew(props) {
  return (
    <Fragment>
      <Head>
        <title>
          Moe Loubani - Software Developer and Development Consultant
          Specializing in WordPress
        </title>
        <meta
          name="description"
          content="I'm a software developer located in Waterloo, Ontario. My main area of focus is high traffic WordPress sites and WordPress plugin development and I also provide a consulting service for people looking to plan things out before undertaking a large project."
        />
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <section data-id="about-me" className="animated-section">
        <AboutMe
          rightColumnPoints={props.rightColumnPoints}
          aboutMeText={props.aboutMeText}
        />
        <div className="white-space-50"></div>
        <WhatIDo whatIDoArea={props.whatIDoArea} />
        <div className="white-space-50"></div>
        <Testimonials testimonials={props.testimonials} />
        <div className="white-space-50"></div>
        <HomeBlogPosts blogPosts={props.posts} />
      </section>
    </Fragment>
  );
}

export async function getStaticProps({ params }) {
  const homePageContent = await getHomePage();

  return {
    props: {
      ...homePageContent.page.homePage,
      posts: homePageContent.posts.edges,
    },
  };
}

export default HomeNew;

Nothing really too hard here – I just use the data that was passed into the props to build out the different sections of the page.

In my next post we will get into the header/nav bar and start on a single blog post – the comments were definitely an interesting adventure so make sure to check that out.