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

Uploadcare Image Laravel Package

adnanchowdhury/uploadcare-image

A Laravel package for integrating Uploadcare image handling into your app, with helpers for building image URLs, applying on-the-fly transformations, and serving optimized, CDN-backed images through Blade views and facades.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a third-party Nova field that swaps Nova's built-in file/image field for the Uploadcare upload widget, so files land on Uploadcare's CDN instead of your app's disk. Before writing code, verify the field actually supports your Nova major version — the package is hosted on a private Bitbucket repo with zero public stars or dependents, so treat its composer.json (laravel/nova constraint) and README as the source of truth rather than assuming current-Nova compatibility.

Install (it is not on Packagist — you need the VCS repository entry):

{
  "repositories": [
    { "type": "vcs", "url": "https://bitbucket.org/adnanchowdhury/nova-uploadcare-imagefield.git" }
  ],
  "require": {
    "adnanchowdhury/uploadcare-image": "dev-master"
  }
}

Then:

composer update adnanchowdhury/uploadcare-image

Credentials. The widget runs in the browser and only needs your public key; the secret key is only for server-side calls (delete, file info, signed URLs). Put both in .env and publish any package config if a config/uploadcare.php ships with it:

UPLOADCARE_PUBLIC_KEY=demopublickey
UPLOADCARE_PRIVATE_KEY=demoprivatekey

First use case. Add the field to a resource and store the returned UUID (or CDN URL — see Gotchas) on the model:

use AdnanChowdhury\UploadcareImage\UploadcareImage;

public function fields(Request $request)
{
    return [
        ID::make()->sortable(),
        Text::make('Name'),
        UploadcareImage::make('Image', 'image_uuid'),
    ];
}

Run php artisan migrate as usual, open the resource, upload through the widget, and confirm what actually gets persisted in image_uuid before you build anything on top of it. That single check (UUID vs full URL vs JSON) determines every downstream pattern below.

Implementation Patterns

Decide the storage contract first. Uploadcare gives you a file UUID (3f0e...~1) and a CDN URL (https://ucarecdn.com/<uuid>/). Storing the UUID is the more flexible choice — you can rebuild URLs with any transformation, switch domains, or regenerate signed URLs for private files. Storing the full URL is simpler but bakes the CDN host and transformation string into your data.

// migration
$table->string('image_uuid')->nullable();

// model
public function getImageUrlAttribute(): ?string
{
    return $this->image_uuid
        ? "https://ucarecdn.com/{$this->image_uuid}/-/resize/800x/"
        : null;
}

Do transformations at render time, not upload time. Uploadcare operations are URL-based and free to change later:

<img src="https://ucarecdn.com/{{ $post->image_uuid }}/-/resize/400x/-/quality/smart/-/format/auto/"
     alt="{{ $post->title }}">

A common workflow: store the raw UUID, expose small helper accessors for thumb, hero, and og sizes, and let the CDN handle resizing. This keeps your upload path dumb and your display path expressive.

Responsive/multi-size in Laravel. If you need srcset, generate the variants in an accessor or a small presenter so views stay clean:

public function getSrcsetAttribute(): string
{
    return collect([400, 800, 1600])
        ->map(fn ($w) => "https://ucarecdn.com/{$this->image_uuid}/-/resize/{$w}x/ {$w}w")
        ->implode(', ');
}

Pair with a fallback. Because the field is a Nova-only UI component, keep a sensible fallback for when no file is set, and keep your model's existing accessor logic framework-agnostic (no Nova classes in the model):

public function getImageUrlAttribute(): string
{
    return $this->image_uuid
        ? "https://ucarecdn.com/{$this->image_uuid}/"
        : asset('images/placeholder.png');
}

Integrating with non-Nova entry points. If users can also upload outside Nova (a public form, an API), the Nova field is only the admin-side path. Use the official uploadcare/uploadcare-php SDK server-side for those, and standardize on the same UUID column so both paths produce identical data.

Large media / video. Uploadcare handles video too. If your field allows arbitrary file types, gate the display logic on a stored MIME type or a ->rules() check, otherwise an <img> tag will happily render a broken video element.

Gotchas and Tips

  • VCS install is fragile. No Packagist listing means every consumer needs the repositories block, and dev-master moves under you. Pin a specific commit/tag in composer.json (e.g. dev-master#abc1234) and commit composer.lock.
  • Maintenance risk is the headline. Zero stars, zero dependents, private host — assume no upstream fixes. Read the field's resolve() / fill() methods and vendor it into your app (app/Nova/Fields/UploadcareImage.php) if it works, so a deleted Bitbucket repo doesn't break composer install in CI.
  • Deletes don't cascade. Deleting a model or clearing the field almost certainly leaves the file on Uploadcare. Hook Model::deleted and call the Uploadcare delete API with the private key if storage hygiene matters, and audit orphaned files periodically.
  • Never ship the private key to the field. The widget only needs the public key; the secret belongs in server-side code or a signed-URL endpoint. Double-check the field's meta()/withMeta() payload doesn't leak it into the Nova JS bundle.
  • Configure allowed domains/CORS in the Uploadcare dashboard. The widget can refuse uploads if the requesting origin isn't on the allowed list — a silent failure that looks like a Nova JS bug.
  • Validation is not what it looks like. The field is a custom component, so ->rules('image') or ->maxSize() may not apply the way they do on File::make(). Verify with a deliberate oversized/invalid upload; if unsupported, validate the UUID in a FormRequest or via the field's own rule options.
  • Index previews are a separate concern. Confirm the field renders a preview on the resource index/detail views, or add a ->thumbnail()/->displayUsing() call (name varies) — often these packages only fully style the form view. If index rendering is broken, use an Image::make(...)->disk(null)-style field or a plain Text column with the CDN URL.
  • Tests need faking. Uploadcare's widget is JS; feature tests will never exercise it. Write your model tests against the stored UUID and assert URL generation directly. For Nova field unit tests, set image_uuid manually rather than simulating an upload.
  • Private files need signed URLs. If the Uploadcare project has "private storage" enabled, plain ucarecdn.com/<uuid>/ URLs 403. You'll need a server-side signing step using the secret key — this is where storing the UUID (not the URL) pays off.
  • Version-pin Nova. Nova is licensed/commercial and changes its field API between majors. Lock the Nova version alongside this field and smoke-test after every Nova upgrade; the two are coupled and this package won't publish a compatibility fix.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel