coroowicaksono/nova-carousel
Coroowicaksono Nova Carousel is a Laravel Nova field for adding image carousels to your admin panel. Upload and display multiple images in a responsive slider directly within Nova resources, with simple configuration and integration.
Install the package like any Nova card and confirm the version constraint against your Nova major:
composer require coroowicaksono/nova-carousel
Then publish the card's compiled assets so Nova can find them:
php artisan vendor:publish --provider="Coroowicaksono\NovaCarousel\CardServiceProvider" --tag=assets
# or, depending on how tags are defined:
php artisan nova:publish
Where to look first, in this order:
composer.json — check the laravel/nova constraint. A 9-star package is almost certainly pinned to a single Nova major (Nova 3 or Nova 4). If your app is on Nova 5 (Vue 3), stop here and vendor the Vue component manually.src/*.php — the Card class. Read the constructor and any fluent setters; that's your entire public API. There is likely no config file and no service provider beyond asset registration.resources/js/components/Card.vue — this is where vue-carousel is wired up. Everything the card can render is visible in ~50 lines of template, and this file is your extension point for links, captions, overlays, etc.First use case — a hero banner row at the top of your dashboard. Register the card in app/Providers/NovaServiceProvider.php:
public function cards(Request $request)
{
return [
(new \Coroowicaksono\NovaCarousel\NovaCarousel())
->images([
asset('img/banner-1.jpg'),
asset('img/banner-2.jpg'),
asset('img/banner-3.jpg'),
]),
];
}
Reload /nova, and you should see the slider occupying a single card slot. If the card renders as an empty white box, the assets weren't published or are stale — see the Gotchas section.
Dedicated dashboards instead of the main dashboard. The package's own description hints at this: don't clog NovaServiceProvider::cards(), generate a dashboard and register the carousel there.
php artisan nova:dashboard Marketing
// app/Nova/Dashboards/Marketing.php
public function cards()
{
return [
(new NovaCarousel())->images($this->heroSlides()),
new \App\Nova\Metrics\ActiveUsers,
];
}
This keeps slide lists separate from your metrics and lets different teams see different carousels via canSee().
Drive slides from the database. Hardcoded asset() calls rot fast. The natural pattern is a Banners model with image, url, sort_order, active columns, mapped at card-construction time:
(new NovaCarousel())->images(
Banner::where('active', true)
->orderBy('sort_order')
->pluck('image')
->map(fn ($path) => Storage::disk('public')->url($path))
->all()
);
Note that this executes on every dashboard render, so wrap it in Cache::remember('dash-banners', 600, ...) if the query starts showing up in your logs.
Multiple instances with different behaviour. Because each card is just a PHP object, you can register two carousels side-by-side with different settings — a fast-autoplay promo strip and a slow-manual "featured case studies" strip. Whatever fluent setters the card exposes (autoplay interval, loop, per-page count) map directly onto vue-carousel props, so you'll recognise the names from the vue-carousel docs.
Layering around other cards. In Nova's grid, cards flow into columns, so a carousel typically wants a wide slot. If your Nova version supports per-card widths, give the carousel a full-width slot and keep metrics in the row below — otherwise the slider gets squeezed into a 1/3 column and looks broken.
Making slides clickable. If the card doesn't already accept per-slide links (check the Vue template before assuming), the cleanest path is to copy Card.vue into resources/js/components/Carousel/Card.vue, add an <a :href="slide.url"> wrapper, and register your own card class that points at it. Nova builds your app's JS bundle alongside the card assets, so as long as you run npm run dev / npm run prod in your Nova project, vendor:publish is no longer needed for your fork.
public/vendor/<package>. After composer require, after composer update, and after any php artisan nova:publish, verify that directory exists and isn't empty. A card that "renders but shows nothing" is almost always this, not a PHP error.config/nova-carousel.php. All behaviour lives in the Card class and the Vue component — don't waste time hunting for a publishable config.vue-carousel doesn't always recover gracefully on refocus; if slides desync, disable autoplay or re-init on visibilitychange.vue-carousel will stretch slides to the tallest child unless you constrain height in CSS. Normalise your banner assets to a fixed aspect ratio (e.g. 1600×500) or add a style="height: 260px; object-fit: cover" to the slide wrapper.var(--colors-white), var(--colors-gray-100)) rather than hex codes.composer.json ("coroowicaksono/nova-carousel": "1.0.3") rather than ^1.0, so a composer update can't break your dashboard. MIT licensing means forking to an in-house namespace is a legitimate long-term option if the card becomes load-bearing.canSee() gate to hide it per-user, (3) copying Card.vue and pointing a local card class at it, (4) a full fork. Only reach for (4) if you need behaviour beyond image-array slides.How can I help you explore Laravel packages today?