Does Laravel Work With Payload CMS?
Laravel and Payload CMS can work together as a headless backend + frontend framework combination, but they operate independently rather than natively integrating.
Quick Facts
How Laravel Works With Payload CMS
Laravel and Payload CMS serve different architectural purposes and don't have native integration. Payload is a Node.js/TypeScript headless CMS that provides its own REST and GraphQL APIs, while Laravel is a PHP backend framework. The practical approach is using Payload CMS as your content backend and Laravel for custom business logic, API orchestration, or legacy system integration. Your frontend (React, Vue, Next.js) consumes Payload's API, while Laravel can sit alongside it to handle authentication, custom workflows, payment processing, or data transformation between systems. This requires managing two separate deployments and authentication layers, which adds complexity but provides flexibility. The developer experience involves setting up Payload independently, exposing its API, then building Laravel middleware and controllers to interact with Payload's REST endpoints using HTTP clients. You'll need to coordinate user authentication between systems—typically using JWT tokens from Payload or maintaining separate auth schemas.
Best Use Cases
Laravel consuming Payload CMS API
composer require guzzlehttp/guzzle<?php
namespace App\Services;
use GuzzleHttp\Client;
class PayloadCMSService
{
protected $client;
protected $payloadUrl = 'http://localhost:3000/api';
protected $apiKey;
public function __construct()
{
$this->client = new Client();
$this->apiKey = config('services.payload.api_key');
}
public function getCollectionData($collection, $query = [])
{
$response = $this->client->get(
"{$this->payloadUrl}/{$collection}",
[
'headers' => ['Authorization' => "Bearer {$this->apiKey}"],
'query' => $query,
]
);
return json_decode($response->getBody(), true);
}
public function getDocumentById($collection, $id)
{
return $this->getCollectionData("{$collection}/{$id}");
}
}
// Usage in controller:
$payloadService = new PayloadCMSService();
$products = $payloadService->getCollectionData('products', ['limit' => 10]);Known Issues & Gotchas
Authentication mismatch between Payload (JWT-based) and Laravel (session/token-based)
Fix: Implement a unified auth layer using Payload's JWT tokens across both systems, or use OAuth2 with a shared identity provider like Auth0
Managing two separate deployment pipelines and databases increases operational overhead
Fix: Use Docker Compose for local development, containerize both services, and coordinate CI/CD pipelines with tools like GitHub Actions
Payload's TypeScript ecosystem differs significantly from Laravel's PHP conventions
Fix: Treat them as separate microservices; establish clear API contracts and use API documentation tools like Postman or OpenAPI specs
Real-time data consistency requires polling or webhook implementation between systems
Fix: Use Payload's webhooks to trigger Laravel events, or implement message queues (Redis, RabbitMQ) for eventual consistency
Alternatives
- •Next.js + Payload CMS: More native integration with Payload's TypeScript ecosystem, both JavaScript-based
- •Laravel + Strapi: Both ecosystems have more community documentation for Laravel-Strapi partnerships
- •Laravel Livewire + Filament: Stay fully in the Laravel ecosystem with Laravel's own admin panel and ORM
Resources
Related Compatibility Guides
Explore more compatibility guides