This project demonstrates how to build a headless CMS using WordPress as the backend and React (with Vite) as the frontend. Content is managed entirely in WordPress and consumed via the WordPress REST API in a React-based landing page.
Follow the steps below to get your development environment set up.
git clone <repo-url>
cd <repo-folder>Download and install XAMPP to set up a local server environment.
- Download the latest version of WordPress.
- Extract the WordPress files into your
htdocsdirectory (inside XAMPP installation folder). - Create a new database:
- Open phpMyAdmin via XAMPP control panel
- Create a new database for your WordPress installation
- Run the WordPress installer by visiting in your browser:http://localhost/your-wp-folder
(Replace
your-wp-folderwith your actual WordPress directory name)
- Go to Settings > Permalinks in WordPress admin dashboard
- Select the "Post name" option for clean URLs
- Click Save Changes
Install these essential WordPress plugins via Plugins > Add New:
- Enables token-based authentication for secure POST requests
- Setup Required:
- Follow the plugin's instructions to modify:
wp-config.php.htaccess
- Add these lines to
wp-config.php:define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key'); define('JWT_AUTH_CORS_ENABLE', true);
- Follow the plugin's instructions to modify:
- Creates custom post types and taxonomies through a UI
- No additional configuration needed for basic usage
- Adds custom fields to posts/pages
- Important: After creating field groups:
- Edit each field group
- Under "Settings", enable:
- "Show in REST API"
- (Optional) Create custom REST API endpoints
GET http://localhost/your-wp-folder/wp-json/wp/v2/posts POST http://localhost/your-wp-folder/wp-json/jwt-auth/v1/token Content-Type: application/json
"username": "your_admin_username",
"password": "your_password"
GET http://localhost/your-wp-folder/
Authorization: Bearer YOUR_TOKEN_HERE Navigate to your project directory and set up Vite:
npm create vite@latest . -- --template reactnpm install
npm install axiosnpm run devimport { useEffect, useState } from 'react';
import axios from 'axios';
function PostList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
axios.get('http://localhost/your-wp-folder/wp-json/wp/v2/posts')
.then(response => {
setPosts(response.data);
setLoading(false);
})
.catch(error => {
setError(error.message);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h2>WordPress Posts</h2>
<ul>
{posts.map(post => (
<li key={post.id}>
<h3 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
<div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} />
</li>
))}
</ul>
</div>
);
}
export default PostList;-
Fully decoupled CMS using WordPress and React
-
Custom post types and fields via CPT UI & ACF
-
RESTful API communication using JWT Auth and Axios
-
Clean URL structures with customizable frontend rendering
Feel free to open an issue or contact me for suggestions, improvements, or questions!
