Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Iiif Bundle Laravel Package

survos/iiif-bundle

A Symfony bundle for working with IIIF (International Image Interoperability Framework) resources, helping PHP applications expose and consume image API endpoints, manifests, and related metadata.

View on GitHub
Deep Wiki
Context7

Getting Started

survos/iiif-bundle is a Symfony bundle for building and serving IIIF Image and Presentation API URLs. Its day-to-day value is narrow but real: it turns "we have identifiers for a few million archival scans on an IIPImage/Cantaloupe server" into "our Laravel app can render deep-zoom viewers and thumbnails without ever touching the bytes."

Minimal steps:

  1. Read src/ before anything else. Release 1.0.0 ships with the note "not yet in survos mono", which means it has not been folded into the Survos monorepo — so there is no cross-package documentation, no worked example in the monorepo test suite, and no guarantee the surrounding ecosystem packages are version-aligned. Treat the source and DependencyInjection/Configuration.php as the reference docs.
  2. Confirm what you actually need. The bundle is thin over IIIF URL construction. If all you need is {scheme}://{host}/iiif/{id}/{region}/{size}/{rotation}/{quality}.{format}, you may not need the package at all. The package earns its place when you also want the Twig helper, the configured size presets, and the Stimulus/viewer glue.
  3. Bridge it into Laravel manually. There is no ServiceProvider, no config/ publish tag, and no auto-discovery. Register the underlying service class (or your own thin wrapper) as a singleton and map the bundle's configuration tree to a Laravel config file. See the Gotchas section — this is the main integration cost.
  4. First use case: thumbnails. Take an existing identifier column (e.g. mss/0421), build a !400,400 size request, and put it in a Blade partial. This is a five-line win and validates your base URL, prefix, and server version assumptions before you commit to the viewer work.

Check the server's info.json first (curl $BASE/iiif/$ID/info.json) — it tells you the API version, maxWidth/maxHeight, tile sizes, and supported formats. Everything downstream depends on those values.

Implementation Patterns

Bind once, inject everywhere. Wrap the bundle's URL builder in a small IiifService of your own. The bundle's Twig function is not available under Blade, and wrapping it means you can swap Symfony services for a plain implementation if the bundle's lifecycle becomes a problem.

// config/iiif.php
return [
    'base_url' => env('IIIF_BASE_URL'),
    'prefix'   => env('IIIF_PREFIX', 'iiif'),
    'version'  => env('IIIF_VERSION', 3),
    'sizes'    => ['thumb' => '!200,200', 'card' => '!600,600', 'full' => 'max'],
];

Keep identifiers out of the URL logic. Store the image identifier (and, for multi-tenant setups, the server host) as columns on the model. The service should accept an identifier and a size preset and return a string — nothing more. This makes it trivially testable with assertSame and no HTTP.

$model->thumbUrl = app(IiifService::class)->image($model->identifier, 'thumb');

Blade component for the viewer. Wrap OpenSeadragon or Mirador in an anonymous component that takes a manifest URL. The bundle's Stimulus controllers are Symfony UX-flavoured; either compile them through Vite as-is or re-implement the twenty lines of OpenSeadragon.init yourself. The latter is usually faster.

Manifests from Eloquent. Use the Presentation API builder (if present in src/, and check the API version it emits — 2.1 vs 3.0 manifests are not interchangeable) to compose a manifest from a collection + its ordered items. Cache the manifest JSON per collection with a version key; regenerating it on every viewer load is the most common performance mistake with IIIF-backed exhibit pages.

Warm and validate in a job. A queued job that fetches info.json for newly ingested identifiers gives you an early warning when a file is corrupt or missing on the image server, rather than a broken tile in production. Http::fake() the info.json in feature tests so the suite stays offline.

Don't proxy pixels. Your app emits URLs; the image server serves tiles. Anything that streams image bytes through PHP defeats the entire architecture.

Gotchas and Tips

  • It is a Symfony bundle, not a Laravel package. No service provider, no facade, no publishable config. You are hand-wiring Extension/Configuration semantics into a Laravel config file and instantiating services yourself. Budget an afternoon for the first integration.
  • Twig may be a hard dependency. If the bundle's service definitions require the Twig extension, you will pull twig/twig into a Blade app. Harmless, but check composer.json — and prefer instantiating the URL builder directly to sidestep the extension entirely.
  • API version drift is the #1 source of 400s. IIIF 2.1 uses quality=color/gray/bitonal and a different size grammar than 3.0 (max is not universal). The bundle's version setting must match what Cantaloupe/IIPImage actually advertises in info.json — not what the docs say.
  • Escape identifiers, especially hierarchical ones. A slash in mss/0421 is legal in IIIF 3.0 but must be %2F-encoded for 2.x servers. The error is a silent 404, not an exception.
  • Respect maxWidth/maxHeight/maxArea. Requesting full/max on a server capped at 4000px returns a 400, and it will look like an auth bug when it is not. Read the caps at ingest and clamp your presets.
  • Browser-side failures are usually CORS or hotlink protection on the image server, not your code. Test the URL in curl and in the browser before debugging PHP.
  • No monorepo presence means no compatibility net. The "not yet in survos mono" note implies sibling packages (survos/iiif, the UX controllers, the fixtures) were not tested against this tag. Pin 1.0.0 exactly and avoid mixing with dev-main of adjacent Survos packages until the monorepo absorbs it.
  • Extension points are Symfony-shaped. If you genuinely need to customise behaviour, extend the bundle's service class in your own namespace rather than subclassing into Symfony's container conventions — you keep the upgrade path clean and stay entirely inside Laravel's container.
  • Pre-1.x churn is over, but the docs are not. 1.0.0 signals a stabilised API; the missing piece is examples. Read DependencyInjection/Configuration.php for the true config surface — the README likely lags.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
cgv/localized-resource