Using Docker For Local Development Of Headless WordPress Sites With NextJS
Tags: wordpress, nextjs, docker
Published: 2021-01-13 23:38:13

Back in 2016, I was [talking about adding how the WordPress REST API]  (https://sandiego.wordcamp.org/2016/session/do-wordpress-better-with-the-wordpress-rest-api/) was the first step in [evolving WordPress to more of an application platform](https://pittsburgh.wordcamp.org/2016/session/the-wordpress-rest-api-and-the-evolution-of-wordpress/). Since then the WordPress post editor has been re-written in React. In addition to the WordPress REST API, there is now a GraphQL plugin for WordPress being developed with the goal of making it a part of WordPress core one day.

Back then, we were not sure how to integrate React or Vue with WordPress sites. Today, NextJS and Gatsby exist and come with WordPress presets. I am a huge fan of NextJS, which includes static site generation, making it perfect for static content sites. I also love the zero config routing for front-end pages and API routes.

NextJs's WordPress preset is everything you need to start a content site, with [WPGraphQL](https://www.wpgraphql.com/). That's cool, but it could also be the start point for a WordPress-powered application. 

Like most WordPress projects, the first step is choosing a local development environment for the WordPress site. There are a ton of options out there. I like to use Docker beacuse there is very little setup for WordPress, thanks to the [@wordpress/wp-env](https://developer.wordpress.org/block-editor/packages/packages-env/) package.

With a little configuration, we can automate all of the setup that is needed. This makes onboarding new developers and QA easier. In this article I am going to show you how to set that up. I will assume you are familiar with WordPress and NextJS.

## Create The Application

First thing, we need a Next app. The WordPress preset is a great start point. It even includes Tailwind. Get started by generating the app using create-next-app:

```sh
yarn create next-app --example cms-wordpress cms-wordpress-app
```

That will create the application. Now we need a WordPress.

## Adding A Local WordPress Site

The configuration for this site is going to very minimal. We need a site with a few plugins and we need to set one constant in wp-config.php of that site. [@wordpress/wp-env](https://developer.wordpress.org/block-editor/packages/packages-env/) can do all of that. 

The WordPress site will need to have WPGraphQL installed. I like to add the [Headless Mode](https://wordpress.org/plugins/headless-mode) plugin I made with some friends awhile ago. This will redirect all unauthenticated requests to the front-end of the WordPress site will be redirected to the client. 

First install the package:

```sh
yarn add @wordpress/env
```

Then we will need to create a `.wp-env.json` config file for the local Docker site:

```json
{
	"core": null,
	"plugins": [
		"https://downloads.wordpress.org/plugin/wp-graphql.zip",
		"https://downloads.wordpress.org/plugin/headless-mode.zip"
	],
	"port": 4113,
	"config": {
		"HEADLESS_MODE_CLIENT_URL": "http://localhost:3000"
	}
}
```

The  "plugins" section is being used to download the latest version of both of those plugins from WordPress.org. The "config" section sets one PHP constant. This is the URL for the redirect. You will need to set one constant in production to match your deployed URL for the client, as [documented here](https://wordpress.org/plugins/headless-mode/#%0Ahow%20do%20i%20set%20it%20up%3F%0A).

To make my life easier, I added a "wordpress" command to the scripts section of package.json


```json

{
        "scripts": {
		"dev": "next",
		"build": "next build",
		"start": "next start",
		"wordpress": "wp-env start"
	}
}
```

## Making Them Work Toghether

Now, lets make sure the WordPress site is working. Try starting it:

```sh
yarn wordpress
```

If everything goes as expected that will download the plugins we need and start the site. When it says its done, if you go to [the front-end of the WordPress site](http://localhost:4113/) it should redirect you to port 3000, which isn't' running and that is fine. We are not there yet.

If you go to [the WordPress login page](http://localhost:4113/wp-login.php) you should see that like normal. If you can login with username "admin" and password "password", then everything is good.

### Configuring NextJS To Work With WordPress

Before starting the next app, we need to tell it what URL to source content from. 

Create a `.env` and add this:

```sh
WORDPRESS_API_URL=http://localhost:4113/graphql`
```

Now start the front-end

```sh
yarn && yarn dev
```

Now you should see the front-end at [http://localhost:3000/](http://localhost:3000/).


### Adding A Plugin

If you're going to add custom post types, or [register new mutations](https://www.wpgraphql.com/functions/register_graphql_mutation/) or do anything else that requires custom PHP code, you will need to add a plugin or mu-plugin.

I like having a plugin for my custom code, so I can turn it on and off. I added a directory called "wordpress-plugin" and put a file in there called "wordpress-plugin". Then I updated the "plugins" section of .wp-config.json to map that directory as a plugin:

```json
{
	"core": null,
	"plugins": [
		"./wordpress-plugin",
		"https://downloads.wordpress.org/plugin/wp-graphql.zip",
		"https://downloads.wordpress.org/plugin/headless-mode.zip"
	],
	"port": 4113,
	"config": {
		"HEADLESS_MODE_CLIENT_URL": "http://localhost:3000"
	}
}
```

Check out [this part of the documentation](https://developer.wordpress.org/block-editor/packages/packages-env/#add-mu-plugins-and-other-mapped-directories) for more information on other ways to load plugins and mu-plugins.

## Make Web Application Now

That's all you need to set up a NextJS app using a local WordPress site running in Docker containers. You can start developing the PHP and JavaScript for your project. What you do next is up to you. Figuring our deployment and [authentication](https://github.com/wp-graphql/wp-graphql-jwt-authentication) as well as coding the app will come next.

If you push the repo to Github, you can deploy the front-end with Vercel with their (super simpler importer](https://vercel.com/new). Make sure to set the `WORDPRESS_API_URL` [environment variable](https://vercel.com/docs/environment-variables) to match the URL of the live WordPress site. 

Feel free to fork the source for [the example application](https://github.com/Shelob9/next-wordpress-docker) to build your own thing. I hope you enjoy.

<em>Featured image by <a href="https://unsplash.com/@rohitsunjaynavin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Suresh Ramamoorthy</a> on <a href="https://unsplash.com/s/photos/blue-skies?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></em>