inoyyth / statamic-cloudinary
Statamic Cloudinary integration: Flysystem adapter for Asset Containers, direct upload services, Antlers tags, and image resolution helpers.
Package info
github.com/inoyyth/statamic-cloudinary-addon
Type:statamic-addon
pkg:composer/inoyyth/statamic-cloudinary
Requires
- php: ^8.2 || ^8.3 || ^8.4 || ^8.5
- cloudinary/cloudinary_php: ^2.0
- illuminate/filesystem: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0 || ^13.0
- league/flysystem: ^3.0
- statamic/cms: ^5.0 || ^6.0
- symfony/mime: ^6.0 || ^7.0
Requires (Dev)
- mockery/mockery: ^1.6
- phpunit/phpunit: ^10.0 || ^11.0 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Seamless Cloudinary integration for Statamic CMS, featuring a complete Flysystem v3 storage adapter for Statamic Asset Containers, direct upload services, Antlers tags, Blade directives, and smart image resolution utilities.
Features
- Statamic Asset Container Integration: Use Cloudinary as your Statamic Asset Container disk driver with full CP file listing, cursor-paginated folder browsing, uploading, renaming, and deleting.
- Path & Metadata Integrity: Preserves exact extensions (
.jpeg,.pdf,.mp4, etc.) and root.meta/<filename>.yamlmetadata files across cache clears (php artisan cache:clear). - CDN Invalidation: Automatically sends cache-invalidation tags on upload, edit, rename, and destroy operations so recent edits never come back stale from the CDN.
- Secure File Delivery: Strict TLS certificate peer verification on all internal file reads and streams.
- Multi-Site Account Isolation: Optional folder/prefix scoping allows multiple websites or environments to share a single Cloudinary account seamlessly.
- Flysystem v3 Adapter: High-performance, cached
CloudinaryFlysystemAdapteradhering to League Flysystem standards. - Smart Image Resolver: Resolves URLs from Statamic
Valueobjects,Assetinstances, collections, nested arrays, and Cloudinary paths with intelligent fallback handling. - Antlers Tags & Modifiers: Effortlessly render responsive
<img>tags and on-the-fly transformations inside Antlers templates. - Blade Directives & Helpers: Use
@statamicImage(),@cloudinary(),@cloudinaryTransform(),@cloudinaryImage(), or global helpers (statamic_image_url(),cloudinary_transformed_url(),cloudinary_image_tag()). - Direct Cloudinary Operations: Direct upload, deletion, public ID extraction, and transformed URL generation via
Cloudinaryfacade andCloudinaryService.
Requirements
- PHP
^8.2,^8.3,^8.4, or^8.5 - Statamic CMS
^5.0or^6.0 - Laravel
^10.0,^11.0,^12.0, or^13.0 - Cloudinary Account
Installation
Install the package via Composer:
composer require inoyyth/statamic-cloudinary
The package will automatically register its ServiceProvider through Laravel/Statamic package discovery.
Publish Configuration (Optional)
php artisan vendor:publish --tag=statamic-cloudinary-config
This publishes config/statamic-cloudinary.php.
Configuration
1. Environment Variables
Add your Cloudinary credentials to your .env file:
CLOUDINARY_CLOUD_NAME=your_cloud_name CLOUDINARY_API_KEY=your_api_key CLOUDINARY_API_SECRET=your_api_secret # Or use the single Cloudinary connection URL: CLOUDINARY_URL=cloudinary://your_api_key:your_api_secret@your_cloud_name # Optional: isolate container assets to a subfolder CLOUDINARY_PREFIX=site-production # Optional: fallback image path when an image field is empty (defaults to null) STATAMIC_CLOUDINARY_FALLBACK=
2. Configure Filesystem Disk
In config/filesystems.php, add the cloudinary disk:
'disks' => [ // ... 'cloudinary' => [ 'driver' => 'cloudinary', 'cloud_name' => env('CLOUDINARY_CLOUD_NAME'), 'api_key' => env('CLOUDINARY_API_KEY'), 'api_secret' => env('CLOUDINARY_API_SECRET'), 'url' => env('CLOUDINARY_URL'), 'secure' => env('CLOUDINARY_SECURE', true), // Optional: scope this disk to a specific folder in Cloudinary 'prefix' => env('CLOUDINARY_PREFIX', ''), ], ],
Multi-Site Tip: If several sites share one Cloudinary account, setting
'prefix' => 'site-a'or'prefix' => 'site-b'ensures each site's asset container only lists and manages its own folder.
3. Statamic Asset Container
Configure a Statamic Asset Container to use the cloudinary disk:
- In the Statamic Control Panel, navigate to Assets -> Configure Containers.
- Select or create your Container (e.g.
cloudinary). - Set Disk to
cloudinary.
All assets uploaded through Statamic CP or blueprint fields configured with container: cloudinary will now be stored in and served from Cloudinary!
Usage
In Antlers Templates
1. Resolving URLs
{{-- Resolving asset URL via tag --}}
<img src="{{ cloudinary:url src=banner_image }}" alt="Banner" />
{{-- Using modifiers --}}
<img src="{{ banner_image | cloudinary }}" alt="Banner" />
<img src="{{ banner_image | statamic_image }}" alt="Banner" />
2. On-the-fly Image Transformations
{{-- Transforming with dimensions, crop, quality & format --}}
<img src="{{ cloudinary:transform src=banner_image width=800 height=400 crop='fill' quality='auto' format='webp' }}" alt="Transformed Banner" />
{{-- Using modifier pipeline --}}
<img src="{{ banner_image | cloudinary:transform(800, 400, 'fill', 'auto', 'webp') }}" alt="Transformed Banner" />
3. Generating Responsive HTML <img> Tags
{{-- Renders a complete <img ... /> with transformations and HTML attributes --}}
{{ cloudinary:image src=hero_image width=1200 height=600 crop='fill' alt="Hero Banner" class="w-full rounded-2xl shadow-xl" loading="lazy" }}
In Blade Templates
{{-- Direct URL Resolution --}} <img src="@statamicImage($page->banner_image)" alt="Banner" /> <img src="@cloudinary($page->hero_image, 'images/default-fallback.jpg')" alt="Hero" /> {{-- Transformed URL --}} <img src="@cloudinaryTransform($page->avatar, ['width' => 200, 'height' => 200, 'crop' => 'fill', 'gravity' => 'face'])" alt="Avatar" /> {{-- Complete HTML Image Tag --}} {!! \Inoyyth\StatamicCloudinary\Facades\Cloudinary::imageTag($page->banner_image, ['width' => 800, 'height' => 400], ['alt' => 'Banner', 'class' => 'w-full']) !!}
Global Helper Functions
// Resolve any Statamic asset, string, or collection $url = statamic_image_url($entry->banner_image); // Generate transformed URL $transformed = cloudinary_transformed_url($entry->avatar, 400, 400); $custom = cloudinary_transformed_url($entry->avatar, ['width' => 800, 'crop' => 'fit', 'format' => 'webp']); // Generate HTML <img> tag $tag = cloudinary_image_tag($entry->avatar, ['width' => 120, 'height' => 120], ['class' => 'rounded-full']); // Direct upload $result = cloudinary_upload($file->getRealPath(), 'uploads/resumes');
In PHP / Livewire / Controllers
use Inoyyth\StatamicCloudinary\Facades\StatamicImage; use Inoyyth\StatamicCloudinary\Facades\Cloudinary; // Resolve any Statamic asset, string, or collection $imageUrl = StatamicImage::resolve($entry->image); // Direct Cloudinary Upload $result = Cloudinary::upload($request->file('avatar')->getRealPath(), 'avatars'); $publicId = $result['public_id']; // Get transformed URL $transformedUrl = Cloudinary::getTransformedUrl($publicId, ['width' => 600, 'height' => 600, 'crop' => 'fill']); // Delete an asset Cloudinary::delete($publicId);
Running Tests
The test suite covers Flysystem adapter operations, path consistency, metadata preservation across cache clears, Antlers tags & modifiers, Blade directives, service providers, and helper functions:
composer test # or ./vendor/bin/phpunit
Changelog
Please see CHANGELOG.md for details on recent changes and release notes.
Support & Feedback
If you encounter any issues or have questions, please open an issue on our GitHub Issues page or reach out via email.
License
The MIT License (MIT). Please see License File for more information.