Building a Notebook Web app with WordPress and React

Welcome to very first tutorial series on enforty.com!

In this tutorial, we will build an notebook web app to browse and search for snippet and note. I do this tutorial because I want to have a place to quickly access and search my notes, I also want to access them on any devices. There isn’t any “good enough” app out there which fit my needs, so I decided to build one.

Why do I use WordPress as backend of web app?

I use WordPress because it’s easy to use, the UI is very slick so anyone can get started with WordPress. WordPress is also what I work on everyday so I can build backend faster. Moreover, WordPress is full featured and very well tested, the REST API is predefined. And for last reason, it just works. We can build our backend of our app with very little code. I want you – my readers – can build your own app with ease.

By the end of this tutorial I hope you can:

  • Build backend of web application with WordPress.
  • Understand WordPress REST API and how to work with it.
  • Create an React application with create-react-app
  • Work with redux.
  • Use UI library to speed up your development.
  • How to deploy your React app.

I will try my best to not introduce many things. This isn’t an all-in-one tutorial. Instead of building a perfect application that seems never complete, we will build an imperfect application that works!

For easier follow up and update in future, I’ll divide this tutorial into small pieces:

Analyze and design our app

In this tutorial, we will build a simple programer’s notebook app that fetch notes from an WordPress instance and display notes in our app. We can view, filter and search for notes. To keep thing simple, we won’t implement Note management features such as create note book, tag, create – update – delete note from front end. Maybe we will talk about them in another post. Let’s build our app as a MVP first, we will add more cool features later.

Firstly, let’s take a look at the app we will build. You can also check the live version ( I’m actually using it ) here: https://notes.enforty.com/

We will make a full width web app with sidebar on the left which have Category and Tag filter. We will have a big search input in our header for easy note searching. The content section will be a list of notes besides a box to view detail of each note.

For note detail, we can have more than one snippet in a note. Each snippet can have different filename/title and language. The app will auto display each of them with correct highlighting base on the language specified by user when adding note. We can also copy the snippet by a single click.

Pretty simple, right? 🙂

To satisfy the requirement above, we will split out application into two sides: back-end and front-end. Back-end part will be a WordPress instance, and front-end part will be a React app. Front-end React app will communicate with WordPress by REST API.

Everything’s still good? Take a beer and let’s get our hand dirty with the next.

Setup WordPress as our app backend

Welcome to the part 2 of our tutorial. In this part we will setup a WordPress instance and get it ready for our app.

First step will be installing WordPress to our local host or remote host. It’s up to you, either is okay. For your convenient, I will use my live production notes app as example in this tutorial.

I setup a blank WordPress site at enfory.com/notes/. Using localhost is fine if you want. If you don’t know to to setup a WordPress site, use Google, it’s very easy, I promise!

Disable WordPress front-end

Congratt! At this point, we had a WordPress site. The next step, we will disable front-end side of WordPress because we just need the backend. Let’s do this by create a blank theme, which I called … Blank.

Our blank theme will have structure like this:

We just need 2 lines for style.css file:

Leave index.php and functions.php empty. Move or upload this theme to your WordPress installation and then activate it. And congratt! You have just disabled WordPress front end.

For me, when an user go to my backend site ( which currently is enforty.com/notes ) I will redirect him to my main blog which you’re reading. To do so, we need index.php file like this:

Stop here for minute. We will discuss how to use WordPress to store code snippets:

  • We use default category to categorize our snippets. Eg: WordPress, React, Phoenix…
  • We use default tag for things like woocommerce, wp-cli, redux…
  • Because we use this WordPress instance for store snippets only, we will use deault post type post for snippet.
  • In the real world, a snippet may have more than one piece of code ( which I called code cell ) with different programming languages. We will need a repeatable group of custom fields. For sure, we can use default editor of post but the UX when adding or updating snippet with multiple cells is not so smart.
  • A cell of code will have:
    • language field: to specify language of current cell.
    • code field: to store code.
    • title field: we can store a very short description of current cell or filename…

We continue this part by installing CMB2 plugins. You can get this plugin from WordPress.org plugin directory. After installing that. We will get .. nothing. It’s time to edit our empty functions.php file.

When you look at my app at notes.enforty.com, you will see some icon appeared next to category name. We will need a custom field to store icon class for category. To do that with CMB2, edit your empty functions.php file in blank theme like this:

After add that code, edit a category and you will see the Icon class field. We will use this field to store icon class name of icon font.

Continue adding code to the end of functions.php file to make your post post type ready for snippet:

Save functions.php file then we will got this in add/update post UI:

Our final funtions.php file:

OK. We’re done. Add some content to your WordPress site and head to the next part.

Test WordPress REST API with Postman

In this part, we will learn how to use WordPress API to fetch data.

From WordPress 4.8, REST API has been turned on by default. We won’t go deep in REST API in this tutorial, there are so many good posts about that in the internet. We just cover some basic terms, which is enough to understand and work with WordPress REST API.

WordPress REST API – A very crash cource

Formerly, when we want to read a blog from a WordPress site, we need a browser to go to address (domain) of the blog. From development side, when we want to display a blog post, we need a theme (which follows template system of WordPress), the theme must have a file called single.php to display single post.

With REST API, we will communicate with WordPress by an other way. API stands for Application Programming Interface. We will make a request to a specific URL which called endpoint, then WordPress will give us a response in JSON. We can this JSON response in our application. By this way we don’t need an WordPress theme to display a blog. This can be an Windows .NET app, a macOS app, an Android or iOS app, … and sure, a web app – which we’re building.

Test WordPress REST API with Postman

Postman is an awesome tool to work with API. It’s available as both browser extension and OS app. Choose which suits you best and start testing.

Because we installed the latest version of WordPress, REST API is enabled by default. We can test if API enabled or not by make a GET request to site URL of our app with a suffix /wp-json:

Here, I make a GET request to our backend site https://enforty.com/notes/ with wp-json as the suffix. We will receive an JSON Object as response. This object contains public information of our site.

You can find the list of all built-in endpoint of WordPress REST API here: https://developer.wordpress.org/rest-api/reference/.

For this tutorial, we will use these endpoints:

  • wp-json/wp/v2/posts: Get most recent posts.
  • wp-json/wp/v2/posts?categories=catId : Get most recent posts which have specific category ID catId.
  • wp-json/wp/v2/posts?tags=tagId : Get most recent posts which have specific  tag ID tagId.
  • wp-json/wp/v2/posts?search=term : Get most recent posts which match search string term.
  • wp-json/wp/v2/categories : Get all categories.
  • wp-json/wp/v2/tags : Get all tags.

Here is an example when we try to fetch categories:

Sweet! We have done building the backend of our app. Let’s continue with most fun part: Front-end React app.

Scaffold React app with create-react-app

So sweet that you reach here. Now we will dive into front-end world and craft our app with ReactJS.

There are many way to get started with React, but for me, the best way to learn is doing something. We will learn React by coding our app with React.

Before we can do anything, make sure your dev machine has nodeJS installed. If you don’t, just do some searching to install it then comeback here. I hope that I can write another blog about installing node in the future.

Now we has our dev machine with nodeJS installed. Let’s install create-react-app to start coding our app.

Why create-react-app?

I choose create-react-app because it’s simple and just work, like WordPress. create-react-app is extreme friendly for new comers. No configuration, no hassle!

Install create-react-app

Now we will install create-react-app. First, let’s verify our node installation again.

node -v
v8.1.2
npm -v
5.0.3

Then, we will install yarn which is a better package management. Go to official guide to grab it.

Look good!  Now we install create-react-app with this command:

npm install -g create-react-app

After running above command, we will create an empty react app with this command:

create-react-app notebook

Creating a new React app in /Users/admin/Projects/notebook.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts…

yarn add v0.24.6
info No lockfile found.
[1/4] 🔍 Resolving packages…
[2/4] 🚚 Fetching packages…
[3/4] 🔗 Linking dependencies…
[4/4] 📃 Building fresh packages…
success Saved lockfile.
warning Your current version of Yarn is out of date. The latest version is “0.27.5” while you’re on “0.24.6”.
success Saved 895 new dependencies.
├─ [email protected]

└─ [email protected]
✨ Done in 55.56s.

Success! Created notebook at /Users/admin/Projects/notebook
Inside that directory, you can run several commands:

yarn start
Starts the development server.

yarn build
Bundles the app into static files for production.

yarn test
Starts the test runner.

yarn eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

cd notebook
yarn start

Happy hacking!

We have just created a React app at /Users/admin/Projects/notebook. Note that I’m using a Mac to write this tutorial, your response may be slightly different, so don’t worry.

Next, go to /Users/admin/Projects/notebook and start our app for the first time.

cd notebook
yarn start
Compiled successfully!
You can now view notebook in the browser.
Local: http://localhost:3000/
On Your Network: http://192.168.1.14:3000/
Note that the development build is not optimized.
To create a production build, use yarn build.

A new browser tab will be opened pointing to http://localhost:3000. And your first React app is ready to develop:

Refactor folder structure

So we got a React app, it’s time to open code editor/IDE. Currently, our app folder looks like bellow:

▸ node_modules/
▾ public/
|-favicon.ico
|-index.html
|-manifest.json
▾ src/
|-App.css
|-App.js
|-App.test.js
|-index.css
|-index.js
|-logo.svg
|-registerServiceWorker.js
|-package.json
|-README.md
|-yarn.lock

We will refactor the folder structure to a better one.

First create a folder components inside src folder, then put App.css, App.js, App.test.js, logo.svg to a folder called App inside components folder:

▸ node_modules/
▾ public/
|-favicon.ico
|-index.html
|-manifest.json
▾ src/
|-▾ components/
|-|-▾ App/
|-|-|-App.css
|-|-|-App.js
|-|-|-App.test.js
|-|-|-logo.svg
|-index.css
|-index.js
|-registerServiceWorker.js
|-package.json
|-README.md
|-yarn.lock

To unify our component folder structure, we will rename some files in App component like this:

  • App.css -> style.css
  • App.js -> index.js
  • App.test.js -> index.test.js

Our current folder structure of src/components/App will look like this:

▾ src/
|-▾ components/
|-|-▾ App/
|-|-|-index.js
|-|-|-index.test.js
|-|-|-logo.svg
|-|-|-style.css

Now our app will be failed to build:

Failed to compile.
./src/App.js
Module build failed: Error: ENOENT: no such file or directory, open ‘/Users/tung/Projects/notebook/src/App.js’

We need some modifications in src/index.js to make our app work again.

We will got another fail in terminal:

Failed to compile.

./src/components/App/index.js
Module not found: Can’t resolve ‘./App.css’ in ‘/Users/tung/Projects/notebook/src/components/App’

It’s time to open src/components/App/index.js,  then correct the import for stylesheet:

Our app now compiles successfully again.

Wireframe app with ant.design

Now we have the foundation for our app. Let’s build sketch our app’s layout with ant.design. FYI, ant is a React UI Kit come with many prebuilt components. It’s very nice by the way. And it works with create-react-app. You can learn more about ant at https://ant.design/.

Change directory to root of our app, then install ant UI Kit with this command:

yarn add antd

Next, copy the node_modules/antd/dist/antd.min.css to public/css folder. We need to create css folder first.

mkdir public/css
cp node_modules/antd/dist/antd.min.css public/css

Then we load the css file in public/index.html:

It’s time to write some components. Let’s take a look at the final app:

According to the design, we need some components:

  • Sidebar component
    • A Logo component
    • A Menu component
  • Header component which holds search form
  • A Content component to wrap all content
    • A Snippet list component
    • A Detail Snippet component

Logo Component

Let change the logo by putting the logo file in public/images. Mine is public/images/logo.png.

Create src/components/Logo/index.js:

Stylesheet for Logo src/components/Logo/style.css:

Something to note here:

  • We use stateless component ( presentational ) for static component, or component doesn’t have state. Shorter and better syntax, easier to test.
  • File in public folder will be serve as root of our web app. Eg: we can access public/images/logo.png by URL: localhost:3000/images/logo.png

Sidebar Component

Create src/components/Sidebar/index.js:

Stylesheet for Sidebar src/components/Sidebar/style.css:

Here, we use ES6 class syntax for Sidebar component because in the design (notes.enforty.com), we will display tags and categories in Sidebar, we use React Component Lifecycle to fetch data on load, which can’t be archived with presentational compontent.

SearchForm Component

Create src/components/SearchForm/index.js:

Stylesheet for SearchForm src/components/SearchForm/style.css:

AppHeader Component

Create src/components/AppHeader/index.js:

Stylesheet for AppHeader src/components/AppHeader/style.css:

App Component

Finnaly, we update src/components/App/index.js:

Stylesheet for App src/components/App/style.css:

At this point, our app will look like bellow, and we’re ready for the next part: Implementing Redux.

Leave a Reply