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
Feature | Traditional WordPress | Headless WordPress |
---|---|---|
Front-end Rendering | PHP-based themes | React, Vue, Next.js, etc. |
Content Delivery | Server-rendered pages | API-driven (REST/GraphQL) |
Performance Tuning | Plugin-dependent | Optimized via front-end tools |
Developer Experience | Limited flexibility | Modern 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:
- Go to your WordPress Admin Panel
- Install & activate WPGraphQL
- 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
- Vercel (ideal for Next.js)
- Netlify (great for static builds)
- GitHub Pages (for simple React apps)
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
Pros | Cons |
---|---|
Fast & modern front-end | Extra setup complexity |
Flexible UI/UX | SEO needs manual configuration |
Works across platforms | Requires 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.