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

Imagekit Laravel Package

aerni/imagekit

Laravel integration for ImageKit.io that makes it easy to generate optimized image URLs, apply transformations, and manage uploads through a simple, fluent API.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire up the endpoint first.

composer require aerni/imagekit
php artisan vendor:publish --tag=imagekit-config   # verify the tag name against the repo

The package is a thin URL builder, so the only real prerequisite is knowing your ImageKit URL endpoint (the https://ik.imagekit.io/<your_id> value from the ImageKit dashboard). Drop it into .env and map that env var in config/imagekit.php:

IMAGEKIT_ENDPOINT=https://ik.imagekit.io/your_id

Look here first (in this order):

  1. config/imagekit.php — the only config surface, tells you exactly which keys the tag/modifier reads, and since v2.2.0 it also holds the new bypass flag.
  2. src/ — likely a single ServiceProvider plus a Tag or Modifier class. Read the class, not the README; at this repo size the source is the documentation.
  3. The package's test fixtures — they usually contain the canonical path/parameter shapes, including the bypass branches added in v2.2.0.

Turn on the dev bypass immediately. v2.2.0 adds an option to skip ImageKit entirely and emit the regular/origin path, which is exactly what you want locally. Find the key in config/imagekit.php (grep for bypass) and wire it to an env var so you never edit the config file per-machine:

IMAGEKIT_BYPASS=true   # local only
// config/imagekit.php — confirm the actual key name against the published file
'bypass' => env('IMAGEKIT_BYPASS', false),

Then php artisan config:clear and verify a rendered <img> points at your local asset path rather than ik.imagekit.io.

First use case. The 90% job is "given a Statamic asset, give me an ImageKit URL with transformation params." That means:

{{ imagekit src="/assets/hero.jpg" width="1200" quality="80" }}

or, if it ships as a modifier:

{{ hero_image | imagekit:width=1200 }}

Confirm which form the package actually registers (tag vs. modifier) before building templates around it — see Gotchas.

Checkpoint before going further: with the bypass off, hit the generated URL in a browser with a single transformation (w=400). If ImageKit responds, your endpoint and signing are correct and everything downstream is template plumbing. Then flip the bypass on and confirm the same template renders a working local image.

Implementation Patterns

Build a single "image partial" as your seam. Because the package only produces strings, wrap it so the rest of the app never touches it directly. One partial, one place to swap the addon out:

{{# partials/image.antlr #}}
<img
  src="{{ imagekit :src="src" width="{ width ?? 1200 }" quality="80" }}"
  alt="{{ alt }}"
  loading="{{ loading ?? 'lazy' }}"
  width="{{ width ?? 1200 }}">

Call it everywhere: {{ partial:image src="{ hero.url }" width="1600" alt="{ hero.alt }" }}. This is the single highest-leverage thing you can do with a small dependency — it caps your blast radius to one file.

Use the v2.2.0 bypass instead of branching on environment. Pre-v2.2.0 the standard workaround was an {{ if environment == 'local' }} fork between glide and imagekit inside the partial. That branch is now dead weight: the bypass flag gives you the same behaviour with the template unchanged and one config value flipped per environment. Delete the Glide branch if you added one — keeping both means two code paths to debug when local and production images diverge.

Responsive srcset. Generate the candidates in Antlers and let ImageKit do the resizing per-breakpoint rather than pre-baking derivatives:

<img
  srcset="
    {{ imagekit src="{ url }" width="640"  }} 640w,
    {{ imagekit src="{ url }" width="1280" }} 1280w,
    {{ imagekit src="{ url }" width="1920" }} 1920w"
  sizes="(max-width: 768px) 100vw, 1280px"
  src="{{ imagekit src="{ url }" width="1280" }}"
  alt="{{ alt }}">

With the bypass on, all three candidates collapse to the same source file — correct, if wasteful locally. Don't "fix" that; local fidelity is the point, and it's a dev-only cost.

Pass ImageKit transformations through verbatim. ImageKit's whole value proposition is URL chaining (tr=w-400,h-300,q-80,f-auto). Rather than mapping every option, expose an escape hatch in your partial — e.g. a transforms string param concatenated onto the tag — so you aren't blocked when a designer wants bl-5 or f-auto and the package has no named arg for it. Note the bypass path silently drops these; that's expected.

Pair with a Statamic fieldset for editorial control. Add image fields (focus, alt, crop intent) and translate them into transformation params in the partial, rather than teaching editors ImageKit syntax.

Caching strategy. ImageKit URLs are deterministic; cache the rendered string at the tag/partial level if you have high-traffic pages, but don't cache the image bytes yourself — that's ImageKit's job. Set a long Cache-Control on pages and let the CDN handle invalidation via path purge when an asset is replaced.

Gotchas and Tips

Pin the bypass to local, and assert it in CI. The bypass is the best thing in this release and the easiest way to ship a silently unoptimised production site: every image resolves, nothing errors, and you've lost every transformation plus the CDN. Guard it two ways — env-var default false in the config, and a test or deploy check asserting the rendered URL contains your ImageKit host when APP_ENV=production.

Config caching. The bypass flag is read from config, so a runtime config(['imagekit.bypass' => true]) in a service provider won't survive php artisan config:cache and will behave inconsistently between php artisan serve and your container. Always go through .env + config/imagekit.php, and php artisan config:clear after any .env change — this bites everyone once, and with the bypass it now produces "why is my local site hitting the CDN" rather than a blank image.

Silent empty output is the #1 failure mode. A misnamed parameter or unregistered tag in Antlers produces a blank string, not an error. When an <img> has an empty src, debug in this order: (1) {{ dump }} the asset URL — is it a plain path or a Statamic asset object? (2) confirm the tag/modifier name from src/*.php; (3) confirm IMAGEKIT_ENDPOINT is actually set and the bypass flag isn't in a half-configured state (config cached?). If the bypass is on you should see your local path — an empty src with the bypass on points at the asset resolution, not the package.

Verify the package supports your Statamic version — but it's no longer frozen. The 2020-era-relic assumption is outdated: it's shipping releases again, and v2.2.0 is a feature drop rather than a patch. Still read the composer.json require block for the statamic/cms constraint before adopting, and run php artisan about to confirm the provider appears in the loaded providers list. If it doesn't, the auto-discovery entry is stale — but treat that as a version-mismatch to fix, not a dead package to replace.

Signing / private files. If your ImageKit account requires signed URLs, the package may still predate that feature — the bypass flag changes nothing here. Don't assume it handles the ik-t/signature query param; if you need signed URLs, generate the HMAC yourself and append it, or wrap the package call in your own helper. Verify by requesting a private-path image from an incognito window.

Local paths vs. absolute URLs. ImageKit needs to map an origin path. If Statamic hands the tag a full https://yoursite.com/... URL, the transformation may apply to the wrong origin or fail to resolve. This is also what the bypass will emit locally, so a bypass render that looks right can mask a path problem that only shows up in production. Prefer passing the asset's relative path/url as Statamic stores it, and check what the package does with the leading slash.

f-auto before you optimize. Always add f-auto (and q-auto if available) — ImageKit will serve WebP/AVIF to supporting browsers. This is the single biggest perf win and it's a one-word addition, so it belongs in your image partial's defaults, not scattered across templates. The bypass removes it locally, which is precisely why you need the production assertion above.

Escape hatch for missing features. Plan to extend rather than fork: write a small App\ImageKit\Url helper that builds the URL string and have your partial call that if the addon's API doesn't cover a need. Migration off the package then becomes a one-line change in one partial.

Test the string, not the image. In Pest/PHPUnit, assert on the generated URL containing tr=w-1200 and your endpoint host, and add one test that flips the bypass config and asserts the origin path comes through instead. You can't assert the rendered image, and you don't need to — the transformation string is the contract, and now the bypass is a contract too.

Have an exit plan documented. Note in your README: "ImageKit URLs are produced by partials/image; the underlying implementation is aerni/imagekit and can be replaced with a ~20-line URL builder." The v2.2.0 release makes that sentence less urgent than it was, but it costs nothing to keep.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core