extending-shopper
This provides instructions for overriding core components, registering sidebar items, and hooking into events for stock, pricing, and media customizations.
Install
mkdir -p .claude/skills/extending-shopper && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3848" && unzip -o skill.zip -d .claude/skills/extending-shopper && rm skill.zipInstalls to .claude/skills/extending-shopper
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Patterns for customizing Shopper in your Laravel application. Sidebar navigation, component overrides, event listeners, and domain features like stock, pricing, and media. Use when extending Shopper behavior in a project.Key capabilities
- →Register custom sidebar items
- →Override core components
- →Hook into event listeners
- →Manage stock, pricing, and media domains
- →Inject UI via render hooks
- →Build reusable addons
How it works
Developers register custom sidebar classes or component overrides within the Laravel ServiceProvider to extend Shopper's core functionality without modifying vendor files.
Inputs & outputs
When to use extending-shopper
- →Add custom items to Shopper sidebar
- →Override Shopper components
- →Implement event listeners for stock updates
- →Customize pricing logic
About this skill
Extending Shopper
Sidebar Navigation
Add Item to Existing Group
// app/Sidebar/ShippingSidebar.php
namespace App\Sidebar;
use Shopper\Sidebar\AbstractAdminSidebar;
use Shopper\Sidebar\Contracts\Builder\Group;
use Shopper\Sidebar\Contracts\Builder\Item;
use Shopper\Sidebar\Contracts\Builder\Menu;
class ShippingSidebar extends AbstractAdminSidebar
{
public function extendWith(Menu $menu): Menu
{
$menu->group(__('shopper::layout.sidebar.catalog'), function (Group $group): void {
$group->weight(2); // Same weight as CatalogSidebar to merge
$group->item(__('Shipping'), function (Item $item): void {
$item->weight(5);
$item->useSpa();
$item->route('shopper.shipping.index');
$item->setIcon('untitledui-truck-01');
$item->setAuthorized($this->user->hasPermissionTo('browse_shipping'));
});
});
return $menu;
}
}
Register in AppServiceProvider:
use Shopper\Sidebar\SidebarBuilder;
public function boot(): void
{
$this->app['events']->listen(SidebarBuilder::class, ShippingSidebar::class);
}
Create New Sidebar Group
$menu->group(__('Logistics'), function (Group $group): void {
$group->weight(5); // After CustomerSidebar (weight 4)
$group->setAuthorized();
$group->item(__('Shipping'), function (Item $item): void {
$item->weight(1);
$item->useSpa();
$item->route('shopper.shipping.index');
$item->setIcon('untitledui-truck-01');
});
});
Default Sidebar Groups
| Group | Weight | Class |
|---|---|---|
| Dashboard | 1 | DashboardSidebar |
| Catalog | 2 | CatalogSidebar |
| Sales | 3 | SalesSidebar |
| Customers | 4 | CustomerSidebar |
Item Options
$item->weight(int)- Position (lower = higher)$item->useSpa()- Enablewire:navigate$item->route('name')- Set route$item->setIcon('untitledui-*')- Icon$item->setAuthorized(bool)- Visibility condition
Override Components
Config files in config/shopper/components/:
// config/shopper/components/product.php
return [
'pages' => [
'product-index' => App\Livewire\Shopper\Products\Index::class,
'product-edit' => \Shopper\Livewire\Pages\Product\Edit::class,
],
'components' => [
'products.form.edit' => App\Livewire\Shopper\Products\EditForm::class,
],
];
Extend the base component:
namespace App\Livewire\Shopper\Products;
use Shopper\Livewire\Pages\Product\Index as BaseIndex;
class Index extends BaseIndex
{
public function table(Table $table): Table
{
return parent::table($table)
->columns([
...parent::table($table)->getColumns(),
TextColumn::make('custom_field'),
]);
}
}
Events
Listen to Shopper events:
// EventServiceProvider
protected $listen = [
\Shopper\Core\Events\Products\ProductCreated::class => [YourListener::class],
\Shopper\Core\Events\Products\ProductUpdated::class => [],
\Shopper\Core\Events\Products\ProductDeleted::class => [],
\Shopper\Core\Events\Orders\OrderCreated::class => [SendOrderConfirmation::class],
\Shopper\Core\Events\Orders\OrderCompleted::class => [],
\Shopper\Core\Events\Orders\OrderPaid::class => [],
\Shopper\Core\Events\Orders\OrderCancelled::class => [],
];
Stock Management
use Shopper\Core\Models\Inventory;
$product = Product::query()->find($id);
$inventory = Inventory::query()->where('is_default', true)->first();
$product->setStock(100, $inventory->id);
$product->decreaseStock($inventory->id, 5);
$currentStock = $product->getStock();
Pricing
Amounts stored in cents, supports multi-currency:
use Shopper\Core\Models\Currency;
$product->prices()->create([
'currency_id' => Currency::where('code', 'USD')->first()->id,
'amount' => 2999, // $29.99
'compare_amount' => 3999, // $39.99 (crossed-out)
'cost_amount' => 1500, // $15.00 (cost)
]);
Media Management
// Add thumbnail
$product->addMedia($file)
->toMediaCollection(config('shopper.media.storage.thumbnail_collection'));
// Add gallery images
$product->addMedia($file)
->toMediaCollection(config('shopper.media.storage.collection_name'));
// Get URL
$thumbnail = $product->getFirstMediaUrl(config('shopper.media.storage.thumbnail_collection'));
Feature Flags
if (\Shopper\Feature::enabled('review')) {
// Show reviews
}
Configure in config/shopper/features.php.
Helper Functions
| Function | Purpose |
|---|---|
shopper_table('products') | Prefixed table name (sh_products) |
shopper_setting('shop_name') | Get shop setting |
shopper_fallback_url() | Fallback image URL |
generate_number() | Order number with prefix |
shopper()->auth()->user() | Authenticated admin |
Render Hooks
Shopper provides 30+ UI injection points to extend admin pages without modifying core views. Register hooks in your ServiceProvider:
use Shopper\Facades\Shopper;
use Shopper\View\ProductRenderHook;
public function boot(): void
{
Shopper::renderHook(ProductRenderHook::EDIT_CONTENT_AFTER, fn () => view('custom.product-extra'));
}
Available hook classes: LayoutRenderHook, ProductRenderHook, OrderRenderHook, CustomerRenderHook, CatalogRenderHook, CollectionRenderHook, SalesRenderHook. See documentation for all hook constants.
Addon System
Build reusable plugins with BaseAddon. Register routes, components, sidebar items, permissions, and assets:
use Shopper\Addon\BaseAddon;
use Shopper\ShopperPanel;
class LoyaltyAddon extends BaseAddon
{
public function getId(): string
{
return 'loyalty';
}
public function register(ShopperPanel $panel): void
{
$panel->addRoutes(fn () => $this->loadRoutesFrom(__DIR__ . '/../routes/web.php'));
$panel->addSidebar(LoyaltySidebar::class);
$panel->addPermissions(['browse_loyalty', 'manage_loyalty']);
}
}
See documentation at https://docs.laravelshopper.dev for the complete addon lifecycle and AddonManager API.
Custom Routes
// config/shopper/routes.php
return [
'custom_file' => base_path('routes/shopper.php'),
];
// routes/shopper.php
use App\Livewire\Shopper\Shipping;
Route::get('shipping', Shipping::class)->name('shopper.shipping.index');
When not to use it
- →Modifying core views directly
- →Ignoring existing event listener patterns
Prerequisites
Limitations
- →Requires adherence to Shopper's specific event and hook classes
How it compares
Unlike modifying core files, this approach uses documented hooks and registration patterns to ensure updates remain compatible with future Shopper releases.
Compared to similar skills
extending-shopper side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| extending-shopper (this skill) | 1 | 4mo | No flags | Intermediate |
| pennant-development | 2 | 4mo | No flags | Intermediate |
| controller | 1 | 6mo | No flags | Beginner |
| filament-5-resources | 0 | 3mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by shopperlabs
View all by shopperlabs →You might also like
pennant-development
laravel
Manages feature flags with Laravel Pennant. Activates when creating, checking, or toggling feature flags; showing or hiding features conditionally; implementing A/B testing; working with @feature directive; or when the user mentions feature flags, feature toggles, Pennant, conditional features, rollouts, or gradually enabling features.
controller
JaguarJack
Generate CRUD controller for CatchAdmin module.
filament-5-resources
kooda-ai
Use when: working with Filament 5 Resources, Resource classes, make:filament-resource, simple resources, form(), infolist(), table(), getPages(), resource pages, ViewRecord pages, page routes, ListRecords, CreateRecord, EditRecord, ViewRecord, relation managers, relation pages, getRelations(), getRe
laravel-pdf
spatie
Generate PDFs from Blade views or HTML using spatie/laravel-pdf. Covers creating, formatting, saving, downloading, and testing PDFs with the Browsershot, Cloudflare, or DOMPDF driver.
laravel-specialist
Jeffallan
Use when building Laravel 10+ applications requiring Eloquent ORM, API resources, or queue systems. Invoke for Laravel models, Livewire components, Sanctum authentication, Horizon queues.
developing-shopper
shopperlabs
Provides coding standards and patterns for Laravel Shopper development. Use when creating or modifying Models, Actions, Enums, Livewire components, migrations, or tests in any Shopper package.