gabrielesbaiz/unsplash-toolkit
| Install | |
|---|---|
composer require gabrielesbaiz/unsplash-toolkit |
|
| Latest Version: | 2.0.4 |
| PHP: | ^8.2|^8.3|^8.4 |
| License: | MIT |
| Last Updated: | Sep 28, 2026 |
| Links: | GitHub · Packagist |
UnsplashToolkit
Curated Unsplash photos for Laravel — you approve the photos, Unsplash serves the bytes, and the photographer gets credited correctly every time.
📖 Read the documentation →
Every setting, every command, the whole API, eight recipes, and a page on each of the nine Unsplash API Guidelines this package enforces for you.
[!CAUTION] Upgrading from 1.x? Read UPGRADE.md first. The facade is now
Facades\Unsplash, the trait moved toConcerns\HasUnsplashables, andstore()is gone — the package hotlinks instead of downloading files. Your curated rows survive:unsplash:refresh --backfillrebuilds them.
[!IMPORTANT] A ⭐ costs you nothing and helps other developers find this package. Sponsoring keeps it compatible with every new Laravel release.
What it does
If you need one photo on one page, copy the URL out of Unsplash and put it in
your template. Add the credit by hand and you are done — no dependency, no
table, no API key. If you want raw API access and nothing else, the official
unsplash/unsplash client is
thinner than this and has no opinions.
This package is for when a person has to choose the photos and the application has to keep choosing between them:
- Curated pools. Approve photos into named sets, then select from your own database — zero API calls when a page renders.
- Hotlinked and responsive. Images are resized on Unsplash's CDN, so there is no storage bill, no egress bill, and any width you like.
- Attribution that cannot be got wrong. Escaped, UTM-tagged, rendered by default, and it throws rather than emit a credit that would not qualify.
- Nine guidelines enforced in code, each with a test named after it, and
unsplash:doctorto fail a build that breaks one. - Caching, retries, timeouts and a rate limiter, so the 50-per-hour demo budget is spent on curation rather than discovered in production.
- Readonly DTOs, enums and a fake driver — no more digging through nested response arrays.
The trade is real: you never hold the image files, because the API Guidelines
require hotlinking. If a photographer deletes a photo, your copy goes with it.
A scheduled unsplash:verify takes dead photos out of rotation and a colour
fallback keeps the page readable, but it cannot bring the photo back. If you need
bytes you control forever, buy a stock licence and use
spatie/laravel-medialibrary.
Requirements
- PHP 8.2, 8.3 or 8.4
- Laravel 11 or 12
- An Unsplash API access key
Installation
composer require gabrielesbaiz/unsplash-toolkit
php artisan vendor:publish --tag=unsplash-toolkit-migrations
php artisan migrate
php artisan vendor:publish --tag=unsplash-toolkit-config
php artisan unsplash:doctor
Two environment variables are required. UNSPLASH_APP_NAME is not optional: it
becomes the utm_source of every photographer credit, and the package throws
rather than emit one without it.
UNSPLASH_ACCESS_KEY=your-access-key
UNSPLASH_APP_NAME="Your Application"
Artisan commands
| Command | Purpose |
|---|---|
unsplash:search {query} |
Find photos from the console, with orientation and colour filters. |
unsplash:curate {id*} --pool= |
Approve photos into a pool, reporting the download event. |
unsplash:verify |
Re-check curated photos still exist, retiring those that do not. |
unsplash:doctor |
Audit the application against the API Guidelines. Exits non-zero on a violation. |
Nine commands in all, two of which belong in your scheduler. See the commands page.
Documentation
| Documentation site | Everything: install, configure, curate, operate. |
| Guide | Browsing, curating, pools, Blade components, building a picker. |
| Configuration | All 40 settings, with defaults and what each one changes. |
| API reference | Every method, DTO, enum, event and exception. |
| Compliance | The nine rules, how each is enforced, and the storage exception. |
| Recipes | Whole solutions: rotating backgrounds, admin pickers, queued curation. |
| Troubleshooting | The errors you are most likely to meet. |
| UPGRADE.md | Upgrading from 1.x. Read before you start. |
| CHANGELOG.md | What changed, and when. |
Testing
composer test # Pest
composer analyse # PHPStan, level 6
composer format # Pint
GitHub Actions runs all three across PHP 8.2–8.4 and Laravel 11–12 on every push.
tests/Compliance holds one file per guideline — it is what keeps the rules from
rotting, so a change that weakens it needs a test rather than a merge.
Contributing
Thank you for considering contributing. The project page covers how to run the suite and what gates a pull request.
Security vulnerabilities
Please review the security policy for reporting a vulnerability, and the security page for the threat model. Please do not open a public issue.
Credits
Written and maintained by Gabriele Sbaiz.
The 1.x line was forked from marksitko/laravel-unsplash by Mark Sitko. 2.0 is a rewrite, but the idea of a fluent Unsplash client for Laravel started there.
This package builds on Laravel and spatie/laravel-package-tools. The photographs come from the photographers on Unsplash, who make them available for free.
Support this package
If it is useful to you:
- ⭐ Star the repo. Free, thirty seconds, and it is the first signal other developers look at.
- ❤️ Become a sponsor. From $5 a month.
- 🐛 Open a good issue. A clear reproduction is worth more than you think.
- 🗣️ Tell another Laravel developer. Word of mouth is how packages survive.
Disclaimer
This package is provided as is, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, title and non-infringement. To the fullest extent permitted by applicable law, in no event shall the authors, copyright holders or contributors be liable for any claim, damages or other liability — whether in an action of contract, tort or otherwise — arising from, out of or in connection with this package or its use, including without limitation any direct, indirect, incidental, special, exemplary, consequential or punitive damages, loss of data, loss of profits, business interruption, or the suspension or termination of your Unsplash API access.
This package enforces the Unsplash API Guidelines as they were published when it was written. The compliance checks are a good-faith implementation, not legal advice and not an approval from Unsplash. The guidelines can change, and the terms that apply to your application are between you and Unsplash. Whoever deploys this package is responsible for reading them and keeping their usage within them — including, and not limited to, applying for production access, naming the application correctly, honouring the rules no package can check, and reviewing the code before putting it in front of traffic you cannot afford to lose. Images are loaded from a third-party CDN at render time, and neither their availability nor their continued licensing is within this package's control.
Use of this package is entirely at your own risk.
License
MIT. See LICENSE.md. The MIT licence's warranty disclaimer and limitation of liability apply in full, alongside the disclaimer above.
Related Packages
A lightweight helper package to handle Eloquent model duplication.