A React-based demonstration comparing Drupal JSON API and WordPress REST API integration patterns in decoupled (headless) architectures.
This project showcases how to build modern frontend applications that consume content from different CMS platforms via their respective APIs. It demonstrates the differences in data structures, API patterns, and integration approaches between Drupal's JSON API and WordPress REST API.
- Dual CMS Integration: Side-by-side comparison of Drupal and WordPress APIs
- Modern React Architecture: Built with TypeScript, React Router, and Tailwind CSS
- Content Management: Articles and events from both platforms
- Responsive Design: Mobile-first design with beautiful UI components
- Individual Content Pages: Detailed views for each piece of content
- Error Handling: Graceful fallbacks and loading states
- Type Safety: Full TypeScript integration with proper API types
The Drupal integration uses the JSON API specification, which provides a standardized format for API responses.
https://drupalize.me/jsonapi
Endpoint | Method | Description | Response Format |
---|---|---|---|
/node/article?page[limit]={limit}&include=field_image |
GET | Fetch articles with images | JSON API format with data array |
Example Response Structure:
{
"data": [
{
"id": "123",
"type": "node--article",
"attributes": {
"title": "Article Title",
"body": {
"value": "Article content...",
"processed": "<p>Article content...</p>"
},
"created": "2024-01-15T10:00:00Z",
"changed": "2024-01-15T10:00:00Z"
}
}
]
}
Since we're using Drupalize.me's API as an example, the following content types use mock data when the live API is unavailable:
- Articles: Demonstrates JSON API format with attributes and relationships
- Events: Shows event-specific fields like
field_event_date
andfield_location
The WordPress integration uses the standard REST API that comes built-in with WordPress.
https://wptavern.com/wp-json/wp/v2
Endpoint | Method | Description | Response Format |
---|---|---|---|
/posts?per_page={limit}&_embed |
GET | Fetch blog posts with embedded media | Array of post objects |
Example Response Structure:
[
{
"id": 123,
"title": {
"rendered": "Post Title"
},
"content": {
"rendered": "<p>Post content...</p>"
},
"excerpt": {
"rendered": "<p>Post excerpt...</p>"
},
"date": "2024-01-16T11:00:00",
"modified": "2024-01-16T11:00:00",
"featured_media": 456,
"categories": [1, 2],
"tags": [3, 4],
"_embedded": {
"wp:featuredmedia": [
{
"source_url": "https://example.com/image.jpg",
"alt_text": "Image description"
}
]
}
}
]
The following content types use mock data for demonstration:
- Posts: Shows WordPress REST API format with rendered HTML content
- Events: Demonstrates custom fields using ACF (Advanced Custom Fields) format
- Standardized Format: Follows JSON API specification (jsonapi.org)
- Consistent Structure: All responses use
data
,attributes
, andrelationships
- Type Information: Each resource includes explicit type information
- Relationship Handling: Built-in support for including related resources
- Sparse Fieldsets: Ability to request specific fields only
- RESTful Design: Traditional REST endpoints with HTTP verbs
- Flexible Structure: Direct property access on response objects
- Embedded Resources: Use
_embed
parameter to include related data - Custom Fields: Support for custom fields via plugins like ACF
- Extensible: Easy to add custom endpoints and modify responses
src/
├── components/ # Reusable UI components
│ ├── ContentCard.tsx # Card component for articles/events
│ ├── DrupalSection.tsx # Drupal content display
│ ├── ErrorMessage.tsx # Error handling component
│ ├── Header.tsx # Page header (deprecated)
│ ├── LoadingSpinner.tsx # Loading state component
│ ├── Navigation.tsx # Main navigation menu
│ └── WordPressSection.tsx # WordPress content display
├── hooks/ # Custom React hooks
│ ├── useDrupalContent.ts # Drupal API integration
│ └── useWordPressContent.ts # WordPress API integration
├── pages/ # Route components
│ ├── ContentDetailPage.tsx # Individual content pages
│ ├── DrupalPage.tsx # Drupal platform page
│ ├── HomePage.tsx # Landing page
│ └── WordPressPage.tsx # WordPress platform page
├── services/ # API service layers
│ ├── drupalApi.ts # Drupal API client
│ └── wordpressApi.ts # WordPress API client
├── types/ # TypeScript type definitions
│ └── index.ts # API response types
├── App.tsx # Main application component
├── index.css # Global styles (Tailwind)
└── main.tsx # Application entry point
- Node.js 18+
- npm or yarn
-
Clone the repository
-
Install dependencies:
npm install
-
Start the development server:
npm run dev
-
Open your browser to
http://localhost:5173
npm run dev
- Start development servernpm run build
- Build for productionnpm run preview
- Preview production buildnpm run lint
- Run ESLint
- Frontend Framework: React 18 with TypeScript
- Routing: React Router DOM v7
- Styling: Tailwind CSS
- Icons: Lucide React
- Build Tool: Vite
- Code Quality: ESLint with TypeScript rules
Both API integrations include comprehensive error handling:
- Network Errors: Graceful fallback to mock data
- Loading States: Spinner components during data fetching
- Error Messages: User-friendly error display
- Retry Logic: Automatic fallback to demonstration data
When live APIs are unavailable, the application falls back to realistic mock data that demonstrates:
- Content Structure: How each platform organizes content
- Field Types: Different field types and their formats
- Relationships: How related content is handled
- Metadata: Publishing dates, categories, and custom fields
This project can be deployed to any static hosting service:
- Netlify: Drag and drop the
dist
folder - Vercel: Connect your Git repository
- GitHub Pages: Use the build output
- AWS S3: Upload static files
Build the project first:
npm run build
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is for educational and demonstration purposes.