DEV Community

J.C. Hiatt
J.C. Hiatt

Posted on

Headless WordPress with React

An intro to building decoupled WordPress-powered websites using the WordPress REST API and Create React App

In recent months, I've taken a big interest in the WordPress REST API (hereto referred to as the WP-API) and React. I've been writing an introductory series to the WP-API, but decided to break for a more full-length, detailed post.

This post will outline how to get started building decoupled (or “headless”) WordPress web applications with Create React App and the WP-API. While this post is going to focus on React for the frontend, some of the general concepts still apply if you want to build your frontend with something else such as Angular, Rx, Ember, or Vue.

And you don't have to stop with web applications. You can use the WP-API to power not only web applications, but also mobile apps, gaming console apps, and more, simultaneously.

Before getting started, feel free to clone the repository for this demo.

Why?

Why WordPress?

Your first question may be “why should I care that WordPress has an API?” I've already written about this a bit in another post, but if you aren't up for opening another tab, here are a few highlights:

  1. As of November, WordPress now powers over 27% of the web. And as of version 4.7, released just a couple of months ago, all the content endpoints for the WP-API are now included in WordPress core, so millions of new APIs just went online.

  2. WordPress is super user-friendly. This may be the single biggest reason why WordPress has seen such widespread adoption. It allows anyone, even non-technical people, to create and edit a website. There is no other tool with the same amount of features and support in existence that's as empowering as WordPress.

  3. WordPress is a powerful content management platform. It's a common misconception among some developers who have never used WordPress (or who haven't used it in a long time) that WordPress is merely for blogging. While it's great for blogging, it's actually great for effectively managing custom content via Custom Post Types.

Why Create React App?

Unless you've been living under a rock in the web development world, you've undoubtedly heard of React by now. Going into the background of React is beyond the scope of this article, but I do want to introduce you to Create React App, the easiest way to get started with React.

Getting started with React itself is pretty easy. You can drop React and ReactDOM into your application today:

<script src="https://unpkg.com/react@15/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>

But if you're looking at using React on more than one small part of your application, the depth of the rabbit hole can quickly become overwhelming. Wanting to deeply learn React usually leads to a plethora of over things to learn: ES6, JSX, Babel, Webpack, and much more – each of these requiring a significant time investment to really understand.

Then, even after acquiring a deep knowledge of these subjects, you'll still spend a significant amount of time in configuration on most non-trivial projects.
But what if you just want to try React itself? Or what if you want to start with a set of configuration defaults and then modify those defaults as you go along?

Well, there's hope: Create React App.

Last summer, Facebook released Create React App, a boilerplate tool with a sensible set of configuration standards so you can quickly get started with React itself and then go down the rabbit hole at your own pace.

Create React App comes bundled with Webpack, ESLint, Babel, Autoprefixer, Jest, and other great tools from the community.

Why Headless WordPress?

Okay, so WordPress is great. React is great. So why should we combine the two?

  1. JavaScript is the future of WordPress. In late 2015, Automattic, the company behind WordPress, re-wrote their entire admin application (codenamed “Calypso”) in JavaScript. And a few weeks later, Matt Mullenweg, CEO of Automattic, gave a massive homework assignment to all WordPress developers: “learn JavaScript, deeply.”

  2. Because a frontend/backend split is good for the world – both users and developers. Better user experiences are possible. Maintaining large codebases is more efficient. Better performance.

  3. Your company can hire more specialized talent. Frontend engineers don't have to know WordPress and vice-versa. Instead of hiring a generalist WordPress theme/plugin developer, you can hire separate roles who each have a deep knowledge of frontend engineering and Wordpress, respectively.

Onward!

Okay, so now that we've established why this matters, let's dive in!

What We'll Be Building

For this tutorial, we'll be building a simple app that displays data about each of the Star Wars movies. The data will be supplied by a WordPress REST API we'll build, and we'll consume it with a React frontend built with Create React App.

Step One: Create New WordPress Installation

I won't go into much depth on this, as there are thousands of resources on the web for setting up a WordPress installation.

If this is your first time delving into WordPress, then I'll assume you don't have a local environment set up. There are some out-of-the-box solutions, such as MAMP and DesktopServer, which are great for getting going quickly. Currently, I'm using Vagrant with Varying Vagrant Vagrants and Variable VVV.

vv + VVV = Awesome Local Environment for WordPress

Once you have your new WordPress install set up, go ahead and visit your admin dashboard: http://your-site.dev/wp-admin

Look at that fancy new install! ✨

Step Two: Install the WordPress REST API Plugin (may not be required)

This step is only required if you are running a WordPress version older than 4.7. You can check what version of WordPress you are running by going to Dashboard>Updates:

~WordPress Dashboard - Updates Section

As of WordPress 4.7, the WP-API is integrated into WordPress core. So if you're running 4.7 or greater, you're good to go.

Otherwise, navigate to Plugins>Add New and search for “WordPress REST API (Version 2)”. Go ahead and Install it and then Activate it.

Step Three: Sanity Check

Fire up your favorite API request tool (I like to use Postman) or a Terminal window if you prefer.

Fire off a GET request to http://your-site.dev/wp-json/. You should get back some JSON that contains all your WordPress site's resources and their respective endpoints.

For a quick demo, send a GET request to http://your-site.dev/wp-json/wp/v2/posts/1 – you should get back JSON with information about the “Hello World!” test post that comes with all new WordPress installs by default. If you already deleted the test post, you won't get anything back.

Step Four: Install Plugins for this Project

The next thing to do is install the plugins we'll need for this demo project. Go ahead and install these and then come back for the explanation of each (unless otherwise noted, each can be searched and installed from Plugins>Add New).

CPT UI

Custom Post Types (CPTs) is one of the most powerful features of WordPress. It allow you to create custom content types to go beyond the default Posts and Pages that WordPress ships with.

While it's certainly possible (and pretty trivial) to create CPTs via PHP, I really like how easy CPT UI is to use. Plus, if you're reading this with no prior WordPress experience, I'd rather you be able to focus on the WP-API itself instead of WordPress and PHP.

For our demo, we'll be creating a CPT called Movies.

I'm going to cover how to manually add the Movies CPT, but if you'd like to skip that and just import the data, go to CPT UI>Tools and paste in the following:

{
"movies": {
"name": "movies",
"label": "Movies",
"singular_label": "Movie",
"description": "",
"public": "true",
"publicly_queryable": "true",
"show_ui": "true",
"show_in_nav_menus": "true",
"show_in_rest": "true",
"rest_base": "movies",
"has_archive": "false",
"has_archive_string": "",
"exclude_from_search": "false",
"capability_type": "post",
"hierarchical": "false",
"rewrite": "true",
"rewrite_slug": "",
"rewrite_withfront": "true",
"query_var": "true",
"query_var_slug": "",
"menu_position": "",
"show_in_menu": "true",
"show_in_menu_string": "",
"menu_icon": "",
"supports": [
"title",
"editor",
"thumbnail"
],
"taxonomies": [],
"labels": {
"menu_name": "",
"all_items": "",
"add_new": "",
"add_new_item": "",
"edit_item": "",
"new_item": "",
"view_item": "",
"search_items": "",
"not_found": "",
"not_found_in_trash": "",
"parent_item_colon": "",
"featured_image": "",
"set_featured_image": "",
"remove_featured_image": "",
"use_featured_image": "",
"archives": "",
"insert_into_item": "",
"uploaded_to_this_item": "",
"filter_items_list": "",
"items_list_navigation": "",
"items_list": ""
},
"custom_supports": ""
}
}

Now for the manual process:

  1. Go to CPT UI>Add/Edit Post Types

  2. For the Post Type Slug, enter movies – this is the URL slug WordPress will use.

  3. For the Plural Label, enter Movies

  4. For the Singular Label, enter Movie

  5. IMPORTANT: Scroll down to the Settings area and find the “Show in REST API” option. By default, this is set to False. If you don't change it to True, you will not be able to query this CPT using the WP-API. Right underneath that option, you should see the “REST API base slug” option – you can enter movies here.

  6. Scroll all the way down and click Add Post Type.

You should see a new Movies option appear in the sidebar:

Movies appeared in the WordPress Dashboard side bar

Advanced Custom Fields

Speaking in database terms, if CPTs are the tables, Custom Fields are the columns. This isn't actually how WordPress stores CPTs and Custom Fields in its database, but I find this illustration helpful to those who have limited to no WordPress experience. CPTs are the resource (i.e. “Movies”) and Custom Fields are the metadata about that resource (i.e. “Release Year, Rating, Description”).

Advanced Custom Fields (ACF) is the plugin for WordPress Custom Fields. Of course, you can create Custom Fields with PHP (just like CPTs), but ACF is such a time-saver (and it's a delight to use).

You can get this one from Plugins>Add New, but if you want to use the import function to import my sample data, you'll need the Pro version, which you can find here).

If you have the Pro version, go to Custom Fields>Tools after Activating the plugin. You can then paste in this JSON to import the fields you'll need:

[
{
"key": "group_582cf1d1ea6ee",
"title": "Movie Data",
"fields": [
{
"key": "field_582cf1d9956d7",
"label": "Release Year",
"name": "release_year",
"type": "number",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"prepend": "",
"append": "",
"min": "",
"max": "",
"step": ""
},
{
"key": "field_582cf1fc956d8",
"label": "Rating",
"name": "rating",
"type": "number",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"prepend": "",
"append": "",
"min": "",
"max": "",
"step": ""
},
{
"key": "field_5834d24ad82ad",
"label": "Description",
"name": "description",
"type": "textarea",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"maxlength": "",
"rows": "",
"new_lines": "wpautop"
}
],
"location": [
[
{
"param": "post_type",
"operator": "==",
"value": "movies"
}
]
],
"menu_order": 0,
"position": "normal",
"style": "default",
"label_placement": "top",
"instruction_placement": "label",
"hide_on_screen": "",
"active": 1,
"description": ""
}
]

If you don't have the Pro version, here's how to setup your Custom Fields:

Create the Field Group

ACF organizes collections of Custom Fields in Field Groups. This is domain-specific to ACF. That's all you really need to know about Field Groups for now.

1.Go to Custom Fields>Field Groups

  1. Click “Add New”

  2. For the Field Group title, enter “Movie Data”

  3. Scroll down until you see the Location metabox. Set this Field Group to only show if Post Type is equal to Movie:

ACF Display Settings for Field Group

You can then scroll down to the Settings metabox. You should be able to leave all these options set to their defaults, but you can still give it a once over compared against this screenshot:

ACF Movies field group settings

After that, click Update to save your Field Group settings.

Create the Custom Fields

First, create a Release Year field:

Field Label: Release Year
Field Name: release_year
Field Type: Number
Required? No

Next is the Rating field:

Field Label: Rating
Field Name: rating
Field Type: Number
Required? No

And lastly, the Description field:

Field Label: Description
Field Name: description
Field Type: Text Area
Required? No

Don't forget to click Update to save your new Custom Fields.

Now, if you to to Movies>Add New, and then scroll down a bit, you should see a metabox called Movie Data (the name of your field group) along with each of the Custom Fields you created inside it:

The Movies field group now appears if on the New Movie page

ACF to REST API

Now that we have our Custom Fields, we need to expose them to the WP-API. ACF doesn't currently ship with WP-API support, but there's a great plugin solution from the community called ACF to REST API. All you have to do is install (you can find it by searching for it at Plugins>Add New) and activate it, and it will immediately expose your ACF custom fields to the API.

If we had created our Custom Fields directly via PHP (without the use of a plugin), there's also a couple of nifty functions for exposing the field to the API. More on that here.

Step Five: Post Data Import

This is the last step to get our WordPress installation ready to serve our Star Wars data.

First, we need to import all the Movies. Lucky for you, I already did all the manual work and all you have to do is import a nifty file. :-)

Go to Tools>Import. At the bottom of the page you should see an option to import from WordPress with an Install Now link underneath:

Screenshot of WordPress Import screen

After the WordPress Import installs, you should see a link to run the importer. Click that and import this file at the next screen.

The next screen will ask you to assign the imported posts to an author. You can just assign them to your default admin account and click Submit:

Post-import screen for new author assignment

Lastly, go to Movies>All Movies. You should see a listing of Star Wars movies (Episodes 1–7). Because I developed in my local environment, the import file couldn't import the featured images for the Movies (it couldn't fetch them from the origin server), so you'll have to add those manually (it only takes about 30 seconds).

My preferred way (and the fastest way) is to hover over each of the posts on the All Movies page and hold Command (Control on Windows) and click Edit for each one. This will open one tab for each Movie.

On each of the edit pages, in the right sidebar, find the Featured Image metabox and click Set Featured Image. Here's a ZIP file with each of the images you'll need. Or you can use any other images you'd like.

For the first one, it's easiest to upload all the images to the Image modal that you see when you click Set Featured Image and then only select the one you need for that first Movie (this will save you the time of uploading each image individually across all your Movies):

If that seems unclear, here's a GIF that will hopefully make more sense than my poor attempt at explanation.

For each Movie, be sure to click Update after selecting featured image.

Now you're good to go! Now leave your WordPress server running and let's move on.

Step Six: Install Create React App

Assuming you already have Node and npm installed on your machine, simply run this command:

npm install -g create-react-app

That's it! You're ready to use Create React App.

Step Seven: Create the App

cd into the directory you'd like to create the frontend (this doesn't have to be (and shouldn't be) the same directory as your WordPress installation). Then run:

create-react-app headless-wp

The process will take a few minutes, but once it's complete you should be able to cd into the newly created headless-wp directory. From there, run:

npm start

This command fires off a number of things, but all you need to know at the moment is that it'll boot up a Webpack dev server. Your browser should automatically open to http://localhost:3000:

The default page when you first boot up your new React app.

You can leave the server running in your shell. Hot reloading will automatically refresh your webpage every time you save a file.

Step Eight: Create Your Component

Since this demo app is very simple, we'll only be using one component. We could easily create another component (it's as easy as creating another ComponentName.js file and importing it into its parent component), but we're instead going to edit our App.js component.

Open up App.js. You can go ahead and delete all the existing code from this file except for the first and last lines.

At this point, App.js should look like this:

import React, { Component } from 'react';
export default App;

Next, create the render() function for this component. This function gets called every time the state changes. If you aren't sure what this means, have some patience. It'll make sense soon.

App.js should now look like this:

import React, { Component } from 'react';
class App extends Component {
  render() {
    return (
      <div>
        <h2>Star Wars Movies</h2>
      </div>
    )
  }
}
export default App;

Whatever render() returns is what gets painted on the DOM. If you save this file and go back to your browser, it should automatically reload and you should see this h2 we created:

A shiny new h2!

This is great and all, but what about all that great data we stored in WordPress about the Star Wars movies? Time to get that data!

Update App.js like so:

import React, { Component } from 'react';
class App extends Component {
  constructor() {
    super();
    this.state = {
      movies: []
    }
  }
componentDidMount() {
    let dataURL = "http://headless-wp.dev/wp-json/wp/v2/movies?_embed";
    fetch(dataURL)
      .then(res => res.json())
      .then(res => {
        this.setState({
          movies: res
        })
      })
  }
render() {
return (
      <div>
        <h2>Star Wars Movies</h2>
      </div>
    )
  }
}
export default App;

We just added two new functions to our render() function: constructor() and componentDidMount().

The constructor() function is where we initialize state. Since we're only dealing with some JSON about our movies, our state is going to be pretty simple. Our initial state will just be an empty movies array since we're expecting to get back that JSON.

The componentDidMount() function fires after the component mounts. This is the best place to make external API calls, so this is where we've added our code to use the fetch API to grab all the movies from our WordPress API (be sure to update the URL to reflect your own URL!). Then, we're taking the response, parsing it as JSON, and then pushing it into our state object.

Once the response gets pushed into our state, the component will re-render by firing the render() function because the state has changed. But this doesn't really matter right now, because currently our render() function is still only returning a div with a h2 inside.

Let's fix that.

We're now going to add a bit of extra code to our render() function that will take the JSON in the our state (currently stored in this.state.movies) and map each movie and its data into a div.

App.js should now look like this:

import React, { Component } from 'react';
class App extends Component {
  constructor() {
    super();
    this.state = {
      movies: []
    }
  }
componentDidMount() {
    let dataURL = "http://headless-wp.dev/wp-json/wp/v2/movies?_embed";
    fetch(dataURL)
      .then(res => res.json())
      .then(res => {
        this.setState({
          movies: res
        })
      })
  }
render() {
    let movies = this.state.movies.map((movie, index) => {
      return <div key={index}>
      <img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} />
      <p><strong>Title:</strong> {movie.title.rendered}</p>
      <p><strong>Release Year:</strong> {movie.acf.release_year}</p>
      <p><strong>Rating:</strong> {movie.acf.rating}</p>
      <div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
      </div>
    });
return (
      <div>
        <h2>Star Wars Movies</h2>
      </div>
    )
  }
}
export default App;

If you save your file, the page will reload, but you still won't see the Star Wars movie data load on the page. That's because there's one last thing to add. We're mapping each of our movies to their own respective divs, and then storing all those movies inside the movies variable in our render() function. Now we just need to tell our render() function to return our movies variable by adding {movies} underneath our h2.

Finished App.js:

import React, { Component } from 'react';
class App extends Component {
  constructor() {
    super();
    this.state = {
      movies: []
    }
  }
componentDidMount() {
    let dataURL = "http://headless-wp.dev/wp-json/wp/v2/movies?_embed";
    fetch(dataURL)
      .then(res => res.json())
      .then(res => {
        this.setState({
          movies: res
        })
      })
  }
render() {
    let movies = this.state.movies.map((movie, index) => {
      return <div key={index}>
      <img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} />
      <p><strong>Title:</strong> {movie.title.rendered}</p>
      <p><strong>Release Year:</strong> {movie.acf.release_year}</p>
      <p><strong>Rating:</strong> {movie.acf.rating}</p>
      <div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
      </div>
    });
return (
      <div>
        <h2>Star Wars Movies</h2>
        {movies}
      </div>
    )
  }
}
export default App;

Switch back over to your browser window and you should see the Star Wars data after the page reloads:

May the Force be with you.

Going Further

This is only the beginning of what you can do with the WP-API and React. Both have many other features and both have huge communities.

You can take the WP-API further by learning about authentication and POST requests, custom endpoints, and more complex queries.

And as I said earlier, Create React App is made for you to just get your feet wet. When you're ready to learn more, you can learn more about things like Redux, ES6, Webpack, React Native, and more.

I'll be covering many of these topics and more in future posts, so be sure to check back. Or if you'd prefer to have these posts sent directly to your inbox, shoot me an email and I'll add you to my mailing list.

Questions?

I'm happy to help! Leaving a comment below is the fastest way to get a response (plus, it helps others who have the same problem!). Otherwise, drop me a line on Twitter or shoot me an email and I'll do what I can to help!

Top comments (59)

Collapse
 
jchiatt profile image
J.C. Hiatt

Hey Mauro!

As for plugins, it shouldn't matter most of the time because you should only be sending data back via the API (as opposed to any HTML/CSS). I suppose there could be plugins that also send over HTML/CSS, and in that case I think you could hook into the plugin via a filter and remove that markup before the data is sent over the API. But any plugin that's compatible with the API shouldn't be sending styles to the frontend, so this shouldn't be an issue. If you have a specific plugin in mind, let me know!

For routing, I think it mostly depends on what benefits you were getting via WP's routing that you can't get with React Router. I think you can configure your React Router structure to be pretty much identical to WordPress in terms of navigating to pages, posts, etc. Is there a specific benefit you're worried about losing?

If you're looking to do a pet project to use React, then a blog is a great application to get some experience! You can even build your own separate frontend for creating your posts if you wanted.

Would a tutorial on creating a React blog application be helpful?

—J

Collapse
 
arasheedphoto profile image
Adam Rasheed

Seconded for a React blog tutorial!

Collapse
 
timothymehlhorn profile image
Tim Mehlhorn

On the SEO note, Google's crawler will process the site just fine but Facebook and Twitter don't run any javascript. A common approach is to reroute (.htaccess rewrite) the non-javascript running crawlers straight to the posts within WordPress. This lets the crawlers see the meta-tags and users to see the react-app.

Collapse
 
olivia101 profile image
Cristian

If the front-end is not a WordPress theme then won't you end up with two separate domains in production (one domain name for the front-end and another domain for the WordPress installation)?
Wouldn't make more sense to create a React WP theme like FoxHound (github.com/ryelle/Foxhound) instead?

Collapse
 
jchiatt profile image
J.C. Hiatt

You wouldn't necessarily have to end up with two separate domains —you probably would have the API living on a subdomain of your site (api.yoursite.com).

This is pretty standard practice for decoupled applications.

Themes are just fine, but IMO your code is more portable if you are fully broken out of WordPress (just in case you change your API from WP to something else later).

Collapse
 
olivia101 profile image
Cristian

By moving to a fully decoupled approach you are losing the benefits of integrating with future third-party WordPress plugins that work with a React-based front end as well as not being able to avoid additional network requests on app initial load.

Thread Thread
 
jchiatt profile image
J.C. Hiatt

I suppose it depends on the goals of the project. Some folks would rather only use WordPress at the data source and not require any functionality from plugins (unless those plugins manipulate the data, but in that case you still wouldn't care that it's fully decoupled, because those plugins could still interact with the data within WP and never care about the frontend).

 
jchiatt profile image
J.C. Hiatt • Edited

Hey Mauro! To make your plugin compatible, you'd create a custom endpoint for you plugin: developer.wordpress.org/rest-api/e...

For your CSS rules, you could just separate them from the plugin, or you may be able to send them back via the API in a JS object, and then grab them out of the object and write them to <head> or do inline styles. You could go a step further and add an interface in the Dashboard to change the styles of your footnotes.

I haven't done this yet, so you may want to read up more and test it out!

I don't really know the full extent of functionality of your plugin, but you could also simply not use a plugin and instead use a custom field on each post object and let the custom field include footnotes for that respective post. You could then trivially retrieve the value of the custom field via the API.

Collapse
 
michaellsmith profile image
Michael Laurence Smith

Great tutorial. I didn't realise you could still use the admin of WP. How would you continue this app to be able to create movies from the React front end? I'm trying to convert one of personal projects from using localStorage to using a WP-API backend. I realised how complex WP-API data structure is. How do you create a custom post type structure on the front-end before making a POST request?

Collapse
 
jchiatt profile image
J.C. Hiatt

Hi Michael! To my knowledge, you'll have to have the custom post type registered before you can post to it from the frontend. I'd have to look into it deeper to figure out if there's a way to register a CPT from the frontend (although that may not be a good idea in terms of security).

I'll be creating new articles / videos soon, including more about POST requests! Be on the lookout on my Twitter: @jchiatt .

Cheers!
—J

Collapse
 
khaledallen profile image
khaledallen

Do you have any recommendations on how to get started with authenticating Wordpress using a react front-end?

Collapse
 
jchiatt profile image
J.C. Hiatt

There's a couple of different ways to do it, but if you're going to be deploying a production application you'll probably want to look into oAuth or JWT:

wp-oauth.com/kb/authenticating-wit...

auth0.com/docs/cms/wordpress/jwt-a...

I haven't personally tackled these myself — I've only used Basic Auth so far. Would a tutorial on either of these be helpful?

Collapse
 
khaledallen profile image
khaledallen

A tutorial would be awesome! I have tried this with ember.js, but ran into a wall. I was hoping react would have more supporting material but in general it seems like a blindspot. I will check out the resources you've provided though and muddle my way through.

Thread Thread
 
jchiatt profile image
J.C. Hiatt

What specifically was the wall you ran into?

Thread Thread
 
khaledallen profile image
khaledallen

I was able to set up an authentication call using ember-simple-auth, but couldn't figure out how to send all the needed information to the Wordpress server. nonce, token, etc. Basically, all we could send was the login and the password.

We get a response from the server though, with this message: Missing OAuth parameters oauth_nonce, oauth_signature.

Just wasn't sure how to generate all that information. My understanding was that ember-simple-auth was supposed to handle it automatically. I tried writing code to generate those bits on my own, but it turned out to be a little over my head and I was concerned about the security concerns.

I could send you the actual code for the authenticator if you want.

Thanks for looking into this. I appreciate your time.

Thread Thread
 
jchiatt profile image
J.C. Hiatt

I'm not very familiar with Ember, but you can link me to the repo and I'll definitely at least take a look!

—J

Thread Thread
 
khaledallen profile image
khaledallen

Thanks! Here's the link: github.com/khaledallen/mindfishapp...

Collapse
 
wunnle profile image
wunnle

A tutorial on how to authenticate for SPA's would be awesome indeed

Collapse
 
yayromina profile image
Romina Barrett

Wow - fantastic article! As a longtime Wordpress dev and new React dev I was hoping it wouldn't be difficult to use Wordpress as a backend for a React application, and you made it easy to understand how to set up. Thank you!

Collapse
 
jchiatt profile image
J.C. Hiatt

Hi Romina!

Glad you enjoyed the article! I'd love to see what you build with the API — link me on Twitter when you create something!

I'll be converting this tutorial into a video series as well as sharing more WP API videos on my new YouTube channel. Check it out: youtube.com/channel/UCJpDAGpKtSKv5...

Collapse
 
dunnedev profile image
Gareth Dunne

This is a fantastic guide. I've been holding off doing this to my Wordpress blog but knowing that SEO can be maintained and plugins can persist through a decoupled WP is great to know. Thanks for putting this up.

Collapse
 
jchiatt profile image
J.C. Hiatt

Glad you enjoyed it! More coming soon.

—J

Collapse
 
abarron87 profile image
Alex Barron

Thanks so much for writing this article. It's going to be really helpful for my new app idea. Each article I'd read so far missed out something key for me that I wasn't able to decipher (hosting WP on a subdomain and accessing it through the api from the main domain for example), and the create-react-app looks great for React n00bs like me. It'll give me the project structure to work from!

Like you say, when you just want to start on something new and you get bogged down in all the other dependencies that you've gotta learn first, it's frustrating!

Loving reading the insightful comments too. Keep it up.

Collapse
 
jchiatt profile image
J.C. Hiatt

Thanks, Alex! I'm glad my article was helpful!

—J

Collapse
 
digitalhomeca profile image
Digital Home Canada

Fabulous post.

I am currently working on a React / WP Rest API project. I was having some success but this post really helped me with the WP custom fields and showed me a different way to get the data into React which was superior to what I was doing.

Thanks again!

Collapse
 
danielbonnells profile image
Daniel

Thank you, thank you!! This is going to help me a ton. I want just this, a react front-end with the usefulness of wordpress as a content management system. :)

Do you have any posts regarding SEO and react? Particularly regarding possible solutions where server-side rendering is not an option?

Thanks again :)

Collapse
 
jchiatt profile image
J.C. Hiatt

Hey Daniel! I don't have any posts on that yet, but if SSR isn't an option for you, I'd check out something like prerender.io/

J

Collapse
 
tinhochu profile image
Tin Ho Chu

Hello! Thanks for the awesome post!

How can we make a react app to live in the same domain and server of the wordpress installation ?
I've. I want the root domain.com go to the react app instead of the wordpress index?

Collapse
 
jchiatt profile image
J.C. Hiatt

Hi! If you're using Apache, by default Apache will serve an index.html file before a index.php file if one is present. So, you should be able to simply drop your React app in the root of your webserver.

stackoverflow.com/questions/100024...

If you've changed the DirectoryIndex hierarchy, you can simply modify the rule in your .htaccess like so:

DirectoryIndex index.html index.php /index.php

Let me know if that doesn't work!

Collapse
 
camiloruizi profile image
camiloruizi

I need to put multiple wordpress pages in my app.js. file

I managed to call them with let pagesURL like this:
http: // localhost / react-wordpress / headless-react / admin / wp-json / wp / v2 / pages? include [] = 25 & include [] = 2

but I want to call them individually
for example:

{page1} </ div>

{page2} </ div>
Collapse
 
timothymehlhorn profile image
Tim Mehlhorn

I am been doing something very similar with Polymer and Wordpress. Restricting the Wordpress CMS to just content has been having huge performance impacts for some of my projects.

Collapse
 
bennerge profile image
BennerGe

How did you do the authentication and how did you bring the nonces into your Polymer app?
I am working on also with Polymer and Wordpress but I have no idea how I can get the nonce into my app.

Collapse
 
jchiatt profile image
J.C. Hiatt

Hey! From the Codex:

For developers making manual Ajax requests, the nonce will need to be passed with each request. The API uses nonces with the action set to wp_rest. These can then be passed to the API via the _wpnonce data parameter (either POST data or in the query for GET requests), or via the X-WP-Nonce header.

More here: developer.wordpress.org/rest-api/u...

Thread Thread
 
bennerge profile image
BennerGe

Yes I read that already, had already tested it and it works. But I wonder how I can pass the generated nonce from WP to my app, if it is completely independent from my Wordpress installation, e.g. the app is in a different directory / subdomain as Wordpress.

Thread Thread
 
jchiatt profile image
J.C. Hiatt

That's a good question! I'll look into that and see if I can write a post on it.

—J

Collapse
 
Sloan, the sloth mascot
Comment deleted