Does Laravel Work With Sanity?
Laravel and Sanity work excellently together—Sanity acts as your headless CMS while Laravel handles your API and business logic.
Quick Facts
How Laravel Works With Sanity
Laravel integrates seamlessly with Sanity through HTTP requests to Sanity's REST and GraphQL APIs. You fetch structured content from Sanity in your Laravel controllers or services, then return it as JSON responses for frontend consumption, or render it server-side with Blade templates. Most developers use Laravel as a backend API layer that sits between Sanity and a decoupled frontend, but you can also use Laravel with server-side rendering for a traditional MPA setup with dynamic Sanity content.
The typical architecture has Laravel handling authentication, custom business logic, data validation, and serving Sanity content through your own API endpoints. You'll use the Sanity PHP SDK or simple HTTP clients like Guzzle to query content. Real-time collaboration on content in Sanity doesn't require changes to your Laravel setup—you just re-fetch data when needed. Caching strategies become important at scale; Laravel's cache facade pairs perfectly with Sanity's webhook system to invalidate content caches when editors publish changes.
Developer experience is smooth: configure your Sanity project credentials in your .env file, use Laravel's service providers to register a Sanity client, and start querying content. No authentication headaches since Sanity provides a simple API token system. The separation of concerns is clean—your content model lives in Sanity, your application logic lives in Laravel.
Best Use Cases
Fetching Content from Sanity in Laravel
composer require guzzlehttp/guzzle<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
use GuzzleHttp\Client;
class SanityService
{
protected $client;
protected $projectId;
protected $dataset;
protected $token;
public function __construct()
{
$this->projectId = config('sanity.project_id');
$this->dataset = config('sanity.dataset');
$this->token = config('sanity.token');
$this->client = new Client();
}
public function query($query)
{
return Cache::remember("sanity:{$query}", 3600, function () use ($query) {
$response = $this->client->post(
"https://{$this->projectId}.api.sanity.io/v2021-06-07/data/query/{$this->dataset}",
[
'query' => ['query' => $query],
'headers' => ['Authorization' => "Bearer {$this->token}"]
]
);
return json_decode($response->getBody(), true)['result'];
});
}
}
// Usage in controller
$posts = $this->sanity->query('*[_type == "post"] | order(_createdAt desc)[0..9]');Known Issues & Gotchas
API rate limits on Sanity's free tier can be hit during heavy traffic spikes
Fix: Implement aggressive caching in Laravel using Redis or Memcached, and set up Sanity webhooks to invalidate cache on publish events
Image optimization and CDN serving isn't automatic—Sanity provides URLs but you need to configure image transformations
Fix: Use Sanity's image URL builder library or configure your own image service in Laravel with query parameters for resizing and quality
Drafts and preview mode require careful handling—published vs draft content isn't automatically filtered
Fix: Check preview tokens in your Sanity queries and maintain separate API tokens for preview (includes drafts) vs production (published only)
Alternatives
- •Next.js with Sanity—more tightly integrated, better for JAMstack workflows with built-in image optimization
- •Strapi with Laravel—self-hosted CMS option if you need more control, but adds deployment complexity
- •Contentful with Laravel—similar to Sanity but larger enterprise focus, more opinionated structured content model
Resources
Related Compatibility Guides
Explore more compatibility guides