How to make Headless WordPress with React: A Beginner’s Guide to Building Decoupled Websites

In the fast paced web world, developers and content creators are always looking for flexible high performance solutions. Headless WordPress has become a powerful option for modern websites especially when paired with front end frameworks like React.

If you ever wished WordPress had a more dynamic user experience or wanted to use modern JavaScript tools without leaving your favorite CMS you’re in the right place.

In this tutorial we’ll go through how to build a headless website using Headless WordPress and React — from setup to deployment — in a way that’s easy to follow even for beginners with basic web development skills.

What is Headless WordPress?

A headless CMS separates the back-end (content management) from the front-end (website display). This means you can manage content in WordPress but display it using any technology you like — such as React, Vue, or even a mobile app.

Headless WordPress works by exposing your site’s content through APIs — typically the WordPress REST API or GraphQL (via the WPGraphQL plugin). You no longer use WordPress themes to render pages. Instead, WordPress becomes a content database.

Traditional vs. Headless WordPress

FeatureTraditional WordPressHeadless WordPress
Front-end RenderingPHP-based themesReact, Vue, Next.js, etc.
Content DeliveryServer-rendered pagesAPI-driven (REST/GraphQL)
Performance TuningPlugin-dependentOptimized via front-end tools
Developer ExperienceLimited flexibilityModern JavaScript tooling

Why Use React with Headless WordPress?

React is a JavaScript library created by Facebook for building interactive user interfaces. It’s fast, modular, and a perfect match for dynamic front ends.

Benefits of Using React Front-End with Headless WordPress

  • Improved Performance: Faster load times and smooth navigation thanks to React’s Virtual DOM and SPA (Single Page Application) capabilities.
  • Developer Experience: Use modern tools like ES6, JSX, and component-based architecture.
  • Scalability: Easily expand with micro front-ends, mobile apps, or PWAs.
  • SEO Support: Tools like Next.js enable server-side rendering (SSR) and static site generation (SSG), helping improve SEO.

Popular Use Cases

  • Tech blogs using custom UIs.
  • E-commerce platforms with real-time interactions.
  • News and magazine sites that need speed and scalability.

Companies using headless WordPress include: TechCrunch, The New York Times, and Spotify’s news blogs.


Setting Up a Headless WordPress Environment

Step 1: Install WordPress

You can set up a WordPress site using:

  • A local environment like LocalWP
  • A shared hosting plan
  • WordPress.com (business plan required for REST API support)

Step 2: Enable API Access

WordPress has a built-in REST API by default. To access posts:

https://yoursite.com/wp-json/wp/v2/posts

Step 3: Install WPGraphQL (Optional)

To use GraphQL instead of REST:

  1. Go to your WordPress Admin Panel
  2. Install & activate WPGraphQL
  3. You can now access the GraphQL endpoint at:
https://yoursite.com/graphql

This plugin offers powerful query flexibility, similar to how React components fetch specific data.


Creating a React Frontend

Let’s build the front end using Create React App (CRA). You can also use Next.js for SSR and better SEO.

Step 1: Initialize React App

npx create-react-app headless-wp-site
cd headless-wp-site
npm start

Step 2: Fetch Data from WordPress

Using the REST API

useEffect(() => {
  fetch("https://yoursite.com/wp-json/wp/v2/posts")
    .then(res => res.json())
    .then(data => setPosts(data));
}, []);

Using GraphQL

Install Apollo Client:

npm install @apollo/client graphql

Create a query:

Routing and Displaying Content

Using React Router

Install it:

npm install react-router-dom

Basic setup:

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/post/:id" element={<Post />} />
</Routes>

In Next.js

Pages are auto-routed via file names:

  • pages/index.js/
  • pages/post/[slug].js/post/some-title

Displaying WordPress Content

Use dangerouslySetInnerHTML to render HTML from WordPress:

<div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />

Make sure to sanitize or trust the source.

Authentication and Protected Content

For more advanced apps, you may need to authenticate users.

Options:

  • JWT (JSON Web Tokens): Use JWT Auth plugin
  • Application Passwords: Built-in for WordPress 5.6+

Example JWT request:

fetch('https://yoursite.com/wp-json/jwt-auth/v1/token', {
  method: 'POST',
  body: JSON.stringify({ username, password })
})

This returns a token to use in subsequent API requests.

Deployment Tips

WordPress Deployment

  • Shared Hosting (e.g., Bluehost, SiteGround)
  • Managed WordPress Hosts (e.g., Kinsta, WP Engine)

React Front-End Deployment

Performance Best Practices

  • Use image optimization (e.g., Next.js’ Image component)
  • Add caching for API responses
  • Use CDNs for assets and static content

Pros and Cons of Headless WordPress

Pros

  • Modern front-end with React
  • Flexibility to build across platforms
  • Improved performance
  • Full control over design

Cons

  • Increased complexity
  • SEO setup requires effort
  • Requires basic understanding of APIs
ProsCons
Fast & modern front-endExtra setup complexity
Flexible UI/UXSEO needs manual configuration
Works across platformsRequires JS knowledge

Conclusion

Headless WordPress with React is an exciting approach to building high-performance, flexible websites. It offers the best of both worlds: WordPress’s content management power and React’s dynamic UI capabilities.

Whether you’re building a blog, portfolio, or business site, this decoupled setup empowers you to build smarter, faster, and more scalable web experiences.

Ready to build your own headless site? Start by experimenting with WordPress REST API or WPGraphQL and spin up a React front-end — the web is yours to shape!


You might also like:


If you’d like this in a downloadable format or as a live tutorial with code examples, just let me know! Would you like a PDF version or a GitHub repo to go with this?

4o

Humanize 295 words

You said:

Examples for above

ChatGPT said:

Great! Below are some real code examples for the major sections in the blog post to help readers implement Headless WordPress with React using both the REST API and WPGraphQL.


1. Fetching WordPress Posts Using REST API (React Example)


// App.js
import React, { useEffect, useState } from 'react';

function App() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    fetch('https://yourwordpresssite.com/wp-json/wp/v2/posts')
      .then(res => res.json())
      .then(data => setPosts(data))
      .catch(err => console.error(err));
  }, []);

  return (
    <div>
      <h1>Latest Posts</h1>
      {posts.map(post => (
        <div key={post.id}>
          <h2 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
          <div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} />
        </div>
      ))}
    </div>
  );
}

export default App;

Fetching Posts Using WPGraphQL + Apollo Client

// App.js
import React from 'react';
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://yourwordpresssite.com/graphql',
  cache: new InMemoryCache()
});

const GET_POSTS = gql`
  query GetPosts {
    posts {
      nodes {
        id
        title
        excerpt
      }
    }
  }
`;

function Posts() {
  const { loading, error, data } = useQuery(GET_POSTS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error loading posts</p>;

  return (
    <div>
      <h1>GraphQL Posts</h1>
      {data.posts.nodes.map(post => (
        <div key={post.id}>
          <h2 dangerouslySetInnerHTML={{ __html: post.title }} />
          <div dangerouslySetInnerHTML={{ __html: post.excerpt }} />
        </div>
      ))}
    </div>
  );
}

function App() {
  return (
    <ApolloProvider client={client}>
      <Posts />
    </ApolloProvider>
  );
}

export default App;

React Router Example for Post Detail View (Using REST API)

// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import PostList from './PostList';
import PostDetail from './PostDetail';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<PostList />} />
        <Route path="/post/:id" element={<PostDetail />} />
      </Routes>
    </Router>
  );
}

export default App;
// PostDetail.js
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';

function PostDetail() {
  const { id } = useParams();
  const [post, setPost] = useState(null);

  useEffect(() => {
    fetch(`https://yourwordpresssite.com/wp-json/wp/v2/posts/${id}`)
      .then(res => res.json())
      .then(data => setPost(data));
  }, [id]);

  if (!post) return <p>Loading...</p>;

  return (
    <div>
      <h1 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
      <div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />
    </div>
  );
}

export default PostDetail;

WordPress JWT Auth Example (Token Fetch Request)

// AuthService.js
export async function login(username, password) {
  const res = await fetch('https://yourwordpresssite.com/wp-json/jwt-auth/v1/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password })
  });

  const data = await res.json();
  if (data.token) {
    localStorage.setItem('token', data.token);
  }

  return data;
}

Then use token in future fetch requests:

fetch(‘https://yourwordpresssite.com/wp-json/wp/v2/posts’, {
headers: {
Authorization: Bearer ${localStorage.getItem('token')}
}
});

Now you are ready to deploy you site.

Leave a Comment

Your email address will not be published. Required fields are marked *