PHPackages                             shammaa/laravel-smart-glide - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. shammaa/laravel-smart-glide

ActiveLibrary[Caching](/categories/caching)

shammaa/laravel-smart-glide
===========================

Advanced image processing toolkit for Laravel with unified /img routing, responsive components, and intelligent caching.

v2.3.0(1mo ago)357MITPHPPHP ^8.3

Since Dec 12Pushed 1mo agoCompare

[ Source](https://github.com/shammaa/laravel-smart-glide)[ Packagist](https://packagist.org/packages/shammaa/laravel-smart-glide)[ Docs](https://github.com/shammaa/laravel-smart-glide)[ RSS](/packages/shammaa-laravel-smart-glide/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (22)Versions (5)Used By (0)

Laravel Smart Glide
===================

[](#laravel-smart-glide)

Advanced image processing toolkit for Laravel with unified `/img` routing, responsive components, intelligent caching, and a headless JSON API for React/Next.js/Vue frontends.

---

Features
--------

[](#features)

- 🔐 **Signed URLs &amp; Validation** — Protect image transformations with HMAC signatures, strict parameter validation, and extension whitelisting.
- 🖼️ **Responsive Components** — Blade components generate `srcset`, `sizes`, and background media queries automatically.
- ⚙️ **Smart Profiles** — Define reusable WebP/AVIF compression presets and override them from an external PHP profile file.
- 📦 **Unified Delivery Path** — All image responses flow through `/img/...`, simplifying CDNs, caching rules, and observability.
- 🧠 **Intelligent Caching** — LRU-inspired cache manifest with size budgets, warmup metadata, and background eviction.
- 🧾 **SEO-Ready** — Configurable attributes (`loading`, `fetchpriority`, `aria`, `title`, etc.) plus optional JSON-LD `ImageObject` snippets.
- 🛡️ **Security Rules** — Block remote sources (optional), enforce max width/height/quality ranges, and stricter MIME filters.
- 🧰 **DX Friendly** — Publishable config, auto-discovered components, and clean service provider wiring.
- 🌐 **Headless JSON API** — `/img-data` endpoint returns `src`, `srcset`, `sizes`, and `blurDataUrl` as JSON for React/Vue/Mobile consumers.
- 🛠️ **Admin Management API** — HTTP endpoints to warm, forget, and inspect cached images directly from your dashboard.
- 📊 **Cache Introspection** — Check image existence, read dimensions, and view cache statistics through the Facade or HTTP.

---

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 11.x or 12.x
- GD or Imagick PHP extension
- League Glide 3.x (installed automatically)

---

Installation
------------

[](#installation)

```
composer require shammaa/laravel-smart-glide
```

The service provider and components are auto-discovered. If discovery is disabled, register the provider manually in `bootstrap/app.php` (Laravel 11+):

```
return Application::configure(basePath: dirname(__DIR__))
    ->withProviders([
        Shammaa\SmartGlide\SmartGlideServiceProvider::class,
    ])
    ->create();
```

Publish the configuration file when you want to customize paths, caching, or SEO defaults:

```
php artisan vendor:publish --tag=smart-glide-config
```

This creates `config/smart-glide.php` in your application.

---

Environment Setup
-----------------

[](#environment-setup)

1. **Signing keys**```
    APP_KEY=base64:...
    # Optional dedicated key
    SMART_GLIDE_SIGNATURE_KEY=base64:...
    ```

    After modifying the `.env` file, always clear cached configuration: ```
    php artisan config:clear
    php artisan cache:clear
    ```
2. **Filesystem**
    - Originals default to `storage/app/public`.
    - Processed images live in `storage/app/smart-glide-cache`.
    - Run `php artisan storage:link` once if your front-end needs to serve the originals.
3. **Permissions**Make sure the cache directory is writable by your web server user.

---

Quick Start
-----------

[](#quick-start)

1. **Prepare assets**
    Place an image inside `storage/app/public` (default source path). If you need public access to the originals, create the symlink once via `php artisan storage:link`.
2. **Drop the component**```

    ```
3. **Load the page**
    The rendered `` tag now contains a fully signed `src`, responsive `srcset`, `sizes`, and fixed width/height for layout stability. All requests resolve to `/img/team/photo.jpg?...`.
4. **Need a different source path?**
    Edit `config/smart-glide.php` (`'source' => ...`) and clear configuration cache: ```
    php artisan config:clear
    php artisan cache:clear
    ```

### Verify in Tinker

[](#verify-in-tinker)

```
php artisan tinker
>>> app(Shammaa\SmartGlide\Support\SmartGlideManager::class)->deliveryUrl('team/photo.jpg', ['w' => 640])
```

Opening the returned URL in a browser should yield the processed image (HTTP 200). A `403` usually indicates an invalid or missing signature—double‑check your `APP_KEY`/`SMART_GLIDE_SIGNATURE_KEY` and clear cached config.

---

### Facade Usage

[](#facade-usage)

Resolve URLs anywhere in your Laravel app through the `SmartGlide` facade. This is convenient for tables, JSON APIs, or Livewire components where you need pre-signed image URLs without rendering Blade components.

```
use Shammaa\SmartGlide\Facades\SmartGlide;

$url = SmartGlide::croppedUrl(
    path: 'team/photo.jpg',
    width: 160,
    height: 160,
    parameters: [
        'profile' => 'thumbnail', // merges preset params (quality, format, etc.)
        'focus' => 'faces',       // any additional Glide parameters
    ],
);
```

In a DataTable JSON feed:

```
return TeamMember::query()
    ->select(['id', 'name', 'photo_path'])
    ->get()
    ->map(fn ($member) => [
        'id' => $member->id,
        'name' => $member->name,
        'photo' => SmartGlide::croppedUrl($member->photo_path, 96, 96, [
            'profile' => 'thumbnail',
        ]),
    ]);
```

Then render it in JavaScript:

```
$('#team-table').DataTable({
    columns: [
        { data: 'name' },
        {
            data: 'photo',
            render: (data, type, row) => type === 'display'
                ? ``
                : data,
            orderable: false,
            searchable: false,
        },
    ],
});
```

---

Headless &amp; API Usage (React / Vue / Mobile)
-----------------------------------------------

[](#headless--api-usage-react--vue--mobile)

### JSON Data API

[](#json-data-api)

Smart Glide provides a dedicated JSON endpoint at `/img-data/{path}` for headless frontends. This returns all responsive data as a structured JSON payload — ideal for React, Vue, Next.js, or mobile apps.

```
GET /img-data/products/phone.jpg?profile=hero&responsive=retina&blur_placeholder=1&schema=1

```

**Response:**

```
{
  "src": "/img/products/phone.jpg?profile=hero&s=...",
  "srcset": "/img/products/phone.jpg?w=640&... 640w, /img/products/phone.jpg?w=960&... 960w, ...",
  "sizes": "(max-width: 640px) 100vw, (max-width: 960px) 100vw, ...",
  "widths": [640, 960, 1280, 1920, 2560],
  "blurDataUrl": "data:image/webp;base64,UklGR...",
  "schema": {
    "@context": "https://schema.org",
    "@type": "ImageObject",
    "contentUrl": "https://example.com/img/products/phone.jpg?..."
  }
}
```

**Query Parameters:**

ParameterTypeDescription`profile`stringNamed compression profile (hero, thumbnail, etc.)`responsive`stringNamed responsive set, comma-separated widths, or `0` to disable`blur_placeholder`booleanInclude base64 LQIP data URI`schema`booleanInclude JSON-LD `ImageObject` data`alt`stringAlt text used in the schema caption`w`, `h`, `fit`, `focus`, `q`, `fm`mixedAny additional Glide transformation parameters### Facade: `responsiveData()`

[](#facade-responsivedata)

Extract responsive data as a plain array from PHP:

```
use Shammaa\SmartGlide\Facades\SmartGlide;

// In a Laravel Controller or Resource
$imageData = SmartGlide::responsiveData(
    path: 'products/phone.jpg',
    profile: 'thumbnail',
    responsive: 'retina' // or [320, 640, 960]
);

return response()->json([
    'product_title' => 'Awesome Phone',
    'image' => $imageData
]);
```

### Facade: `apiPayload()`

[](#facade-apipayload)

Build the complete JSON-ready payload (including blur placeholder and dimensions) from the Facade — perfect for Inertia.js props and Laravel API Resources:

```
use Shammaa\SmartGlide\Facades\SmartGlide;

// In a Laravel Resource or Inertia page
return SmartGlide::apiPayload('products/phone.jpg', [
    'profile'          => 'hero',
    'responsive'       => 'retina',
    'blur_placeholder' => true,
    'dimensions'       => true,
]);

// Returns: { src, srcset, sizes, widths, blurDataUrl, dimensions: { width, height } }
```

### Consumption in React/Vue

[](#consumption-in-reactvue)

Simply bind the returned attributes to your `` tag:

```
// React / Vue Example

```

> **For a full-featured React/Next.js SDK**, install the companion package `smart-glide-react` (`npm install smart-glide-react`) which provides ``, hooks, and Next.js loader integration.

---

Image Introspection
-------------------

[](#image-introspection)

### Check Image Existence

[](#check-image-existence)

```
if (SmartGlide::imageExists('avatars/user-42.jpg')) {
    // Image found in source directory
}
```

### Get Original Dimensions

[](#get-original-dimensions)

```
$dims = SmartGlide::dimensions('hero.jpg');
// ['width' => 3840, 'height' => 2160]
```

### Generate Multiple URLs

[](#generate-multiple-urls)

```
$urls = SmartGlide::multipleUrls('hero.jpg', [640, 960, 1280], ['profile' => 'hero']);
// [640 => '/img/hero.jpg?w=640&...', 960 => '/img/hero.jpg?w=960&...', ...]
```

---

Admin Management API
--------------------

[](#admin-management-api)

Enable HTTP endpoints for managing the image cache directly from your website or admin dashboard.

### Setup

[](#setup)

```
SMART_GLIDE_ADMIN_ENABLED=true
SMART_GLIDE_ADMIN_PATH=/img-admin
```

> **Security**: Admin routes are protected by `auth` middleware by default. Configure this in `config/smart-glide.php` under `admin.middleware`.

### Endpoints

[](#endpoints)

#### Cache Statistics

[](#cache-statistics)

```
GET /img-admin/stats

```

```
{
  "count": 152,
  "size_mb": 48.3,
  "cache_path": "/var/www/storage/app/smart-glide-cache",
  "source_path": "/var/www/storage/app/public",
  "max_size_mb": 1024
}
```

#### Full Manifest

[](#full-manifest)

```
GET /img-admin/stats/manifest

```

Returns every cached rendition with path, width, profile, format, and timestamps.

#### Warm a Single Image

[](#warm-a-single-image)

```
POST /img-admin/warm
Content-Type: application/json

{
  "path": "products/phone.jpg",
  "profile": "hero",
  "widths": [640, 960, 1280]
}

```

```
{ "warmed": true, "path": "products/phone.jpg", "widths": [640, 960, 1280] }
```

#### Warm All Source Images

[](#warm-all-source-images)

```
POST /img-admin/warm-all
Content-Type: application/json

{
  "profile": "thumbnail",
  "widths": [320, 640],
  "extensions": ["jpg", "png"]
}

```

```
{ "warmed_count": 48, "skipped_count": 3, "size_mb": 52.1, "total_entries": 192 }
```

#### Evict Cache for an Image

[](#evict-cache-for-an-image)

Call this after replacing or updating the original file:

```
POST /img-admin/forget
Content-Type: application/json

{ "path": "products/phone.jpg" }

```

```
{ "forgotten": true, "path": "products/phone.jpg", "deleted_count": 5 }
```

#### Check Image Existence

[](#check-image-existence-1)

```
GET /img-admin/exists?path=products/phone.jpg

```

```
{ "exists": true, "path": "products/phone.jpg" }
```

#### Get Image Dimensions

[](#get-image-dimensions)

```
GET /img-admin/dimensions?path=products/phone.jpg

```

```
{ "path": "products/phone.jpg", "width": 3840, "height": 2160 }
```

---

Cache Management (PHP)
----------------------

[](#cache-management-php)

### Warm Paths Programmatically

[](#warm-paths-programmatically)

Pre-process and cache image renditions (ideal for queued jobs):

```
// Warm specific widths
SmartGlide::warmPath('products/phone.jpg', [320, 640, 960, 1280], ['profile' => 'hero']);

// Warm using config breakpoints
SmartGlide::warmPath('hero.jpg');
```

### Forget (Purge) a Path

[](#forget-purge-a-path)

Delete all cached renditions after replacing the original file:

```
$deleted = SmartGlide::forgetPath('products/phone.jpg');
// Returns count of deleted entries (e.g. 5)
```

### Cache Statistics

[](#cache-statistics-1)

```
$stats = SmartGlide::cacheStats();
// ['count' => 152, 'size_mb' => 48.3, 'manifest' => [...]]
```

---

Configuration Overview
----------------------

[](#configuration-overview)

The config file (`config/smart-glide.php`) exposes several groups:

KeyDescription`source`, `cache`, `delivery_path`Control filesystem paths and the unified `/img` endpoint.`security`Toggle URL signing, allowed formats, max dimensions, quality ranges, and remote sources.`profiles` &amp; `profile_file`Define reusable transformation presets; merge an external PHP file at runtime.`breakpoints`Global widths for automatic `srcset` generation.`responsive_sets`Named breakpoint aliases usable from the components.`cache_strategy`Enforce cache size (MB) and LRU time window.`cache_headers`Configure browser cache days and enable ETag responses.`logging`Enable processing logs and choose the log channel.`seo`Default attributes for `` / background components and structured data behaviour.`api`Enable/disable the headless JSON API endpoint and its middleware.`admin`Enable/disable admin management endpoints, set path and auth middleware.> Tip: set `SMART_GLIDE_SCHEMA_ENABLED=true` to emit JSON-LD `ImageObject` snippets for every component by default.

---

### Default Profiles &amp; Responsive Sets

[](#default-profiles--responsive-sets)

**Profiles (`config('smart-glide.profiles')`)**

NameDescription`default`Outputs WebP at quality 82.`thumbnail`320×320 crop for avatars or cards.`hero`1600×900 centered crop for hero banners.`portrait`800×1200 crop prioritising faces.`square`600×600 crop for grids.`profile_photo`400×400 crop focused on faces (avatars).`cover`2048×1152 crop suitable for cover art.`background`2560×1440 max-fit background-friendly rendition.Use them via `profile="hero"` or override/add more in your config file.

**Responsive sets (`config('smart-glide.responsive_sets')`)**

NameWidths`hero`640, 960, 1280, 1600, 1920`thumbnails`240, 320, 480`square`320, 480, 640`portrait`480, 768, 1024`hd`960, 1280, 1600`fhd`1280, 1600, 1920, 2560`retina`640, 960, 1280, 1920, 2560Reference them with `responsive="retina"` or specify an inline array.

---

Blade Components
----------------

[](#blade-components)

### ``

[](#x-smart-glide-img)

Render responsive `` tags with minimal boilerplate.

```

```

**Common properties**

PropTypeDescription`src`stringRelative path (inside `smart-glide.source`).`profile`stringApply a config profile (`profiles.hero`).`params`arrayAdditional Glide parameters (width, height, etc.).`style`stringInline styles applied to ``.`aspect-ratio`stringAspect ratio hint (e.g. `16:9`, `1.5`).`width` / `height`intNative dimension attributes for layout stability.`seo`arrayExtra HTML attributes (`fetchpriority`, `title`, `itemprop`, …).`schema`boolForce JSON-LD emission for this image only.Structured data respects component-level overrides and merges extra fields from `config('smart-glide.seo.structured_data.fields')`.

#### View Overrides &amp; Fallback Rendering

[](#view-overrides--fallback-rendering)

When you publish the package views, make sure `resources/views/vendor/smart-glide/components/img.blade.php` is kept in sync with the version shipped by the package. If it is removed or left empty, the component now falls back to rendering the `` tag inline, so URLs remain signed even with an incomplete override. You can safely delete the override to restore the default template.

#### How `srcset` Is Generated

[](#how-srcset-is-generated)

- Smart Glide reads breakpoint widths from `config('smart-glide.breakpoints')` by default.
- For each width, the component clones your parameters, overrides `w`, and calls the delivery URL to produce entries like `/img/photo.jpg?w=640&... 640w`.
- The generated HTML will look similar to: ```

    ```
- Update the breakpoints globally by editing `config('smart-glide.breakpoints')`, or define named presets in `responsive_sets` for reuse (`responsive="hero"`).
- Override widths without touching the config: ```

    ```
- Use a named preset from `config('smart-glide.responsive_sets')`: ```

    ```
- Disable `srcset` entirely when you want a single rendition: ```

    ```
- If you need full control, set the attributes manually via `:seo="['sizes' => '...']"` or `['srcset' => '...']`.

### ``

[](#x-smart-glide-bg)

Responsive background helper with media queries and placeholders.

```

```

The component outputs a wrapper `` with inline styles plus an optional `` block for breakpoint-specific backgrounds. A blurred placeholder overlay is included when `lazy` is `true`.

### ``

[](#x-smart-glide-picture)

Responsive `` helper that lets you define multiple `` breakpoints and a Smart Glide powered fallback.

```

```

Each source entry accepts:

KeyDescription`media`Optional media query for the `` tag.`src`Override image path for this source (defaults to component `src`).`params`Glide parameters merged with the base parameters.`profile`Profile name to merge with parameters.`widths` / `responsive`Array or preset used to generate the `srcset`.`sizes`Custom `sizes` attribute.`type`MIME type hint for the source.`srcset`Custom array of descriptors if you need full control.`img-class` / `img-style`Styling for the fallback ``.`img-width` / `img-height`Native width/height attributes on fallback ``.`width` / `height`Set attributes on the wrapping ``.`aspect-ratio`Sets CSS `aspect-ratio` on fallback ``.The internal `` fallback inherits Smart Glide features (SEO attributes, structured data, signed URLs) and can be styled separately via `img-class`.

#### Picture Presets

[](#picture-presets)

Skip repeating `:sources="[]"` arrays in every template by defining presets in `config('smart-glide.picture_presets')`:

```
'picture_presets' => [
    'feature' => [
        ['media' => '(min-width: 1200px)', 'widths' => [1200], 'params' => ['fit' => 'crop', 'w' => 1200, 'h' => 675]],
        ['media' => '(min-width: 768px)', 'widths' => [900], 'params' => ['fit' => 'crop', 'w' => 900, 'h' => 506]],
    ],
],
```

Use the preset in Blade:

```

```

You can still pass `:sources="[]"` along with a preset; they will be appended for page-specific overrides.

---

Signing &amp; Security
----------------------

[](#signing--security)

- URLs are signed with HMAC using `SMART_GLIDE_SIGNATURE_KEY` or `APP_KEY` when `security.secure_urls` is enabled.
- Parameters are sanitized and validated against maximum width/height and quality limits.
- Remote image sources are rejected by default; enable them per environment with `SMART_GLIDE_ALLOW_REMOTE=true`.
- Allowed output formats (`fm`) and file extensions are configurable to avoid unsafe file types.

Requests with invalid signatures or disallowed parameters return `403/400` responses automatically.

---

Smart Cache
-----------

[](#smart-cache)

Smart Glide stores processed images in the configured cache path and tracks metadata in a manifest stored in your cache store.

- `max_size_mb` limits total cache footprint.
- `lru_window` determines how far back "least recently used" entries remain before eviction.
- Metadata includes `cached_at`, `last_accessed`, and `cache_file` references to support background cleanup.

Responses include browser cache headers (`Cache-Control`, `Expires`) and optional `ETag`. HTTP clients respecting `If-None-Match` will receive `304 Not Modified` when appropriate.

---

External Profiles
-----------------

[](#external-profiles)

To allow non-developers to tweak compression parameters, create a PHP file that returns an array:

```
