This post was originally published in Spanish at goiblas.com.

In this tutorial, I am going to show you how to create a personal blog using:

WordPress as database and a tool for creating content.

as database and a tool for creating content. React to display the content and manage the UI components.

to display the content and manage the UI components. NodeJS to render on the server, and thus improve loading times and facilitate search engines crawl.

Luckily for us, other developers have already faced this challenge and created a framework called Frontity which will make this work far easier. You can check out the official documentation at docs.frontity.org.

Index of this tutorial

Prerequisites

NodeJS installed in your computer.

Local install of WordPress, we’ll use Local by Flywheel for this tutorial.

A remote WordPress site.

A Zeit.co account to deploy a NodeJS server.

Set up Frontity

First, open the terminal, go to the directory where you will create your project, and run this command:

npx frontity create blog-name

Replace blog-name with the name of your project. Now access the folder and run the command:

npm run dev

This will open your blog at http://localhost:3000, where you should see it working. You will also see that its content is the one that comes by default with Frontity. The next step would be to show your own content.

This should be the initial appearance of your blog

To do so, you have to create a new site in your local by Flywheel with the default configuration.

Once it is working, copy the site’s url and return to your Frontity project. Open the file frontity.settings.js and look for the line where it states api . Then replace the address that comes by default (https://test.frontity.io/wp-json) with your site’s url plus /wp-json (the address of the WP REST API). It should look like this: http://blog-name.local/wp-json.

If you refresh your blog, you should now be able to see your site’s content. Everything should be working fine except the menu, which points to some pages that are not created in your site.

Configure your menu

Frontity pulls data from your WordPress site, so the first thing you have to do is to create those pagesthatyou’d like to show on your Frontity theme. We’ll create a page called “Quiénes somos” (About us) for this example. We just have to add the link text and path in our frontity.settings.js configuration file:

const settings = {

//…

"packages": [

{

"name": "@frontity/mars-theme",

"state": {

"theme": {

"menu": [

[

"Portada",

"/"

],

[

"Quiénes somos",

"/quienes-somos/"

]

]

}

}

},

//…

};

In this example, we only added “Portada” (Homepage) and the “Quiénes Somos” (About Us) page, but there’s no limit on the number of pages. You can even add links to categories or tags, like in your traditional WordPress site.

As you can see, paths are the same as those that your WordPress uses. So let’s say that you would like to change the url of your posts so that the dates are not shown, for example. You would have to do it from WordPress as usual, and not from Frontity.

Customize your theme

Frontity comes with a default theme called mars-theme, which you can use as a basis for creating your theme. The theme is located within the packages/mars-theme folder.

There you will find another folder called /src which contains: (1) an index.js file, where you can define and configure your theme; (2) a /components folder, where all the pieces that are part of your theme are.

If you are familiar with React and JSX, you’ll find it easy to add and modify components. One thing you should know is that Frontity comes with Emotion among its libraries (already integrated and configured), which allows you to write css styles with JavaScript.

You can find more information on how to style your Frontity theme here.

Emotion

Implement dark mode

As you customize your theme, you may want to add other functionalities. To do this, you will have to return to the index.js file of your theme’s /src folder.

There you’ll find: (1) state , where the global variables of our blog are defined; (2) actions , where the functions that will modify those variables are defined.

Let’s implement dark mode in our blog. The first step would be to define the state and the functions that will modify it.

packages/mars-theme/src/index.js

const marsTheme = { name: "@frontity/mars-theme", roots: { theme: Theme }, state: { theme: { mode: 'light', } }, actions: { theme: { setLightMode: ({state}) => { state.theme.mode = 'light'; }, setDarkMode: ({state}) => { state.theme.mode = 'dark'; } } } };

Now that we have all the ingredients, it’s time to implement this functionality. First, go back to the /components folder of your theme and open the index.js file. Then, get the mode from your state . To simplify, you can add some styles to the body, similar to how the global styles are added.

packages/mars-theme/src/components/index.js

const Theme = ({ state }) => { const data = state.source.get(state.router.link); const { mode } = state.theme; return ( <> <Head> <title>{state.frontity.title}</title> <meta name="description" content={state.frontity.description} /> <html lang="en" /> </Head> <Global styles={ globalStyles} /> <Global styles={ css` body { background-color: ${mode === 'light' ? '#fff': '#222'}; color: ${mode === 'light' ? '#222': '#fff'} }` } /> <HeadContainer> <Header /> </HeadContainer> <Body> {data.isFetching && <Loading />} {data.isArchive && <List />} {data.isPostType && <Post />} {data.is404 && <Page404 />} </Body> </> ); };

As you can see in this example, we tell it: if mode is "light" , use one color; if not, use another. It’s not a spectacular design but it will help you to see its behavior.

Now, let’s create a component which will allow you to change from one mode to another.

packages/mars-theme/src/components/toggle.js

//... const Toggle = ({ actions }) => { const { setLightMode, setDarkMode } = actions.theme; return ( <div> <button onClick={ setLightMode }>Light</button> <button onClick={ setDarkMode }>Dark</button> </div> ) } //...

This should work fine but you still need to indicate which one is selected. To do so, you have to collect the information from the state . Then, with the help of emotion , you can add style to your component as well as modify the buttons so that they accept an attribute which will change its appearance when selected.

packages/mars-theme/src/components/toggle.js

import React from "react"; import { connect, styled } from "frontity"; const Toggle = ({ actions, state }) => { const { setLightMode, setDarkMode } = actions.theme; const { mode } = state.theme; return ( <Container> <ButtonsStyled isSelected={ mode === 'light' } onClick={ setLightMode }>Light</ButtonsStyled> <ButtonsStyled isSelected={ mode === 'dark' } onClick={ setDarkMode }>Dark</ButtonsStyled> </Container> ) } export default connect(Toggle); const Container = styled.div` display: flex; `; const ButtonsStyled = styled.button` padding: 10px; border: 0; background-color: ${({ isSelected }) => (isSelected ? '#ccc': '#fff')}; `;

This component can be included in any part of your blog, in this example we included it in the header.

packages/mars-theme/src/components/header.js

//... import Toggle from "./toggle"; const Header = ({ state }) => ( <> <Container> <StyledLink link="/"> <Title>{state.frontity.title}</Title> </StyledLink> <Description>{state.frontity.description}</Description> <Toggle /> </Container> <Nav /> </> ); //...

Add Disqus as comment system

Although you can use the native WordPress comments, Disqus can bring you some benefits, such as spam control or user identification.

Before starting, you will have to create an account on Disqus (if you don’t have one already) and register a new site.

The good thing about using React for your theme is that you can take advantage of its rich ecosystem and use components from other developers that work great. In this example we will use disqus-react to integrate Disqus. To install it, you can use this command:

npm install disqus-react

Now that you can use it on your blog, you will just need to import it and pass it an object with the url, an identifier and a title, so that Disqus knows which comment it has to show in each post. All the documentation of this React component can be found at github.com/disqus/disqus-react.

To get the information you need, you can help yourself from the state you receive thanks to Frontity. First, get the information from the current url:

const data = state.source.get(state.router.link);

Now, get your post using the type and id you have received from data:

const post = state.source[data.type][data.id];

This is everything you need to build the object and create your comments component.

import React from "react"; import { connect } from "frontity"; import Disqus from 'disqus-react'; const Comments = ({ state }) => { const data = state.source.get(state.router.link); const post = state.source[data.type][data.id]; const disqusShortname = “blog-name”; const threadConfig = { url: `https://${disqusShortname}.com${state.router.link}`, identifier: post.id, title: post.title.rendered, }; return ( <Disqus.DiscussionEmbed shortname={disqusShortname} config={threadConfig} /> ) } export default connect(Comments);

The next step would be to import it within your post component. Remember to render it only on the browser since Frontity provides you with server side rendering (which makes your code run first on the server, where you don’t have a window object and Disqus will give an error).

Through state.frontity.platform you can know where your code is running. In this case, you may want it to run when it is "client" . And to show it only within your posts, you can use data.isPost .

{state.frontity.platform === "client" && data.isPost && ( <Comments /> ) }

The last step would be to implement it through namespaces. Frontity uses state , actions and libraries , and all packages are used from there through a specific name. This means that if you create a package that exports:

libraries: { comments: { Comments } }

You can use libraries in your post to do something similar to this:

const Post = ({ state, actions, libraries }) => { return ( <libraries.comments.Comments /> )

What do you achieve with this? That if you replace your comment library in the future, your theme won’t be affected. You have more information on the use of namespaces in the official Frontity documentation: docs.frontity.org/learning-frontity/namespaces. If you want me to write a post about this topic, let me know.

Publish your blog

Now that you have added style and some features to your blog, it’s time to show it to the world. To do this, you need to have a remote WordPress with the content – remember that we were working locally with Local by Flywheel. You have two options here, install and configure a WordPress blog manually in any web hosting, or use wordpress.com. Either option is perfectly valid.

Once you have your remote WordPress ready, you will have to update the frontity.settings.js configuration file by replacing the local url with the new location, like this:

//... "name": "@frontity/wp-source", "state": { "source": { "api": "https://public-api.wordpress.com/wp/v2/sites/goiblas.wordpress.com" } } //...

If you restart your blog with npm run dev , you should see the content of the new WordPress site. If so, now you have to deploy your project in a NodeJS server.

To do so, you can use Now and follow these steps: docs.frontity.org/installation-and-deploy/deploy-on-now.

You will need to create a now.json file in the root folder of your project with the following content:

{ "alias": "blog-name", "version": 2, "builds": [ { "src": "package.json", "use": "@frontity/now" } ] }

Then, create an account on Now at zeit.co/signup and log in the terminal using:

npx now login

Finally, publish your blog by running the following command:

npx now

And that’s it! ?

Your blog is published and ready to be shown to the world!

💭 Comments? Suggestions? Join the conversationhere!