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

Wn Tinypng Plugin Laravel Package

winter/wn-tinypng-plugin

Winter CMS plugin that integrates TinyPNG to automatically compress and optimize PNG and JPEG images, reducing file sizes while preserving quality. Easy to configure and works with the CMS media manager and uploads.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install into a Winter CMS project:
    composer require winter/wn-tinypng-plugin
    php artisan winter:up
    
  2. Get an API key from the TinyPNG developer dashboard (free tier is ~500 compressions/month), then store it in .env rather than committing it:
    TINYPNG_API_KEY=xxxxxxxxxxxxxxxx
    
  3. Open the backend and look for the plugin's settings under Settings → (TinyPNG / Image Compression). If no settings page is registered, check config/config.php or the plugin's Plugin.php for the expected config key.
  4. Where to look first: plugins/winter/tinypng/Plugin.php (event listeners and Twig registrations), models/ (settings model and any stored-file relation), classes/ (the compressor/client wrapper), and the README for the exact namespace.
  5. First use case: compress one image on upload. Wire the compressor to System\Models\File creation, upload a test JPEG in the Media manager, and confirm the stored file size drops and the image still renders.

Names in the examples below are illustrative — verify the actual namespace and method signatures in Plugin.php before copying.

Implementation Patterns

Compress on upload via model events. The most common day-to-day pattern is listening to the attachment lifecycle rather than asking editors to compress manually:

// Plugin.php boot()
Event::listen('eloquent.created: System\Models\File', function ($file) {
    if (in_array($file->getExtension(), ['jpg', 'jpeg', 'png', 'webp'])) {
        \Winter\TinyPNG\Classes\Compressor::compress($file->getLocalPath());
    }
});

For custom models with attached files, prefer a trait or a File relation observer so the behaviour is explicit and testable.

Wrap it in a service/queue job. Never call the API inline for multi-image uploads. Dispatch a job per file so a slow or rate-limited response doesn't block the admin request:

Queue::push(\App\Jobs\CompressImage::class, ['path' => $file->getLocalPath()]);

Backend integration points. Useful places to expose it:

  • A bulk action on the Media list widget ("Compress selected").
  • A "Re-compress" button on the file form.
  • A scheduled command (php artisan tinypng:compress-existing) for a one-off backfill of the media library.

Twig/frontend helpers. If the plugin registers a Twig filter or function, use it for on-demand resizing:

<img src="{{ image.path|tinypng_resize(800) }}" alt="{{ image.title }}">

If no Twig helper exists, expose your own via Plugin::registerMarkupTags() that delegates to the plugin's compressor class.

Configuration over code. Keep the API key and default options (preserve metadata, resize presets, overwrite vs. sibling file) in config so staging and production can use different TinyPNG accounts and quotas:

// config/config.php
return [
    'api_key' => env('TINYPNG_API_KEY'),
    'overwrite' => true,
    'preserve_metadata' => false,
];

Resize/convert as part of the pipeline. TinyPNG also does resizing and format conversion; if the plugin exposes those, chain them in one job (compress + resize to a max width) rather than making two API round-trips.

Gotchas and Tips

  • Quota is the real constraint. The free tier is small (hundreds of compressions/month). Log the Compression-Count response header and fail gracefully on 429. A single large upload loop can exhaust the monthly quota in minutes.
  • TinyPNG payload limits. The API rejects files over ~5 MB (and has stricter limits on some formats). Check size before calling and skip with a warning instead of throwing.
  • Format support is narrower than you think. JPEG, PNG, WebP, and AVIF are supported; animated images and SVG are not. Guard the extension check — a failed API call on a GIF shouldn't break the upload.
  • Overwriting is destructive. If the plugin replaces the original in place, you lose the source of truth and any future re-compression options. Confirm whether it writes a sibling file or backs up the original, and make CDN/cache invalidation part of the workflow.
  • Idempotency. Add a tinypng_compressed_at flag or hash so re-saving a model doesn't burn a compression credit on an unchanged file. TinyPNG will re-compress happily and bill you for it.
  • Strip metadata deliberately. EXIF removal is usually desirable (privacy, size) but will strip copyright and orientation data — verify orientation is baked in or the image will rotate.
  • Synchronous calls time out. The default PHP execution limit will bite on multi-megabyte uploads. Queue jobs, set a timeout, and retry with backoff on 5xx/429.
  • Debugging a failing key. Test outside the CMS first: curl -u api:YOUR_KEY https://api.tinypng.com/shrink -d @test.jpg. A 401 means key/encoding, not plugin code.
  • Config caching. After changing .env, run php artisan config:clear — Winter caches config and the old key will persist.
  • Compatibility check. Confirm the plugin supports your Winter version (v1.1 vs v1.2+ namespacing differs) and that it's still maintained. The low star count and zero dependents mean you should read the source rather than assume behaviour.
  • Verify the package/repo mapping before adopting. The registry entry points at a repo described as a Winter CMS test playground, not an image-compression plugin. Check the actual package contents in vendor/ (or the Packagist source link) to confirm you're installing what you think you are.
  • Extension points to prefer: events fired before/after compression and a container binding for the client class. If the plugin hardcodes file_get_contents-style HTTP calls, wrap it in your own adapter so you can swap in a mocked client for tests and a different CDN-backed compressor later.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle