Installation:
composer require matheusmarnt/scoutify
php artisan scoutify:install
Follow prompts to select Scout driver (Meilisearch, Algolia, Typesense, or Database).
Register Models:
php artisan scoutify:searchable
Select models to make searchable (or use --all). The command auto-edits model files.
Import Models:
php artisan scoutify:import
Add UI Components to your layout:
<!-- Desktop trigger -->
<x-scoutify::gs.trigger class="hidden lg:inline-flex" />
<!-- Mobile trigger -->
<x-scoutify::gs.trigger-mobile />
<!-- Modal (must be at root level) -->
{{ $slot }}
<livewire:scoutify::modal />
Trigger the modal with ⌘K (Mac) / Ctrl+K (Windows). Start typing to search across all registered models. Results appear grouped by model type with icons, titles, and subtitles.
app/Models/ for Eloquent models. Use --dry-run to preview changes:
php artisan scoutify:searchable --dry-run
public function globalSearchTitle(): string { return $this->custom_title; }
public static function globalSearchIcon(): string { return 'ri-file-pdf-fill'; }
--all to register all models at once:
php artisan scoutify:searchable --all
config/scout.php. Scoutify auto-detects the driver.LIKE queries).<x-scoutify::gs.trigger /> for desktop (lg+) and <x-scoutify::gs.trigger-mobile /> for mobile.<button x-data @click="$dispatch('scoutify:open')">Search</button>
<button wire:click="$dispatchTo('scoutify::modal', 'scoutify:open')">Search</button>
window.dispatchEvent(new CustomEvent('scoutify:open'));
HasGlobalSearchVisibility:
public function globalSearchVisibility(): VisibilityRule
{
return VisibilityRule::make()
->visibleToGuests()
->orWhenAuthenticated()
->policy('view')
->orPermission('edit-articles');
}
config/scoutify.php:
'authorization' => [
'default' => 'permissive', // 'secure', 'permissive', or 'gate-only'
],
HasGlobalSearchPreview:
public function globalSearchPreview(): ?PreviewDto
{
return PreviewDto::fromDisk('documents', $this->file_path);
}
scoutify:download event:
window.addEventListener('scoutify:download', (e) => {
const a = document.createElement('a');
a.href = e.detail.url;
a.download = e.detail.filename;
a.click();
});
Override globalSearchBuilder() for model-specific filters:
public function globalSearchBuilder(Builder $builder, string $query): Builder
{
return $builder->where('status', 'published')->where('category', 'tech');
}
Modal Placement:
<livewire:scoutify::modal /> is at the root layout level, outside dynamic containers.Icon Pack Conflicts:
user) default to heroicon-o- prefix. If using multiple packs, fully qualify icons (e.g., ri-user-fill).Scoutify::types()->iconPrefix('ri-');
Meilisearch Substring Search:
"ano" in "Mariano" return no results.globalSearchBuilder() to configure attributesToSearchOn or switch to the database driver.Livewire Event Dispatch:
$dispatch('scoutify:open') fails outside Livewire components.$dispatchTo('scoutify::modal', 'scoutify:open') in Livewire or Alpine/JS for non-Livewire contexts.Authorization Gaps:
gate-only mode in config/scoutify.php to enforce policies strictly.File Preview Permissions:
HasGlobalSearchVisibility and the PreviewDto record passes authorization checks.Check Scout Index:
php artisan scout:index
Livewire Logs:
config/livewire.php:
'log' => env('LIVEWIRE_LOG', true),
storage/logs/livewire.log for modal initialization errors.Query Inspection:
globalSearchBuilder() temporarily to log queries:
public function globalSearchBuilder(Builder $builder, string $query): Builder
{
\Log::info('Scoutify query:', ['query' => $query, 'toSearchableArray' => $builder->toSearchableArray()]);
return $builder;
}
Event Listener Debugging:
scoutify:download event listener is registered:
console.log('Listener registered:', window.addEventListener);
Dark Mode:
darkMode: 'class',
Translation Overrides:
resources/lang/en/scoutify.php:
return [
'search_placeholder' => 'Search across all models...',
];
Recent Searches:
session()->forget('scoutify.recent_searches');
Tailwind Overrides:
Scoutify::theme()
->modalBackground('bg-gray-800')
->resultItemHover('hover:bg-gray-700');
Custom Result Components:
php artisan vendor:publish --tag=scoutify-views
resources/views/vendor/scoutify/result-item.blade.php.Scout Driver Extensions:
Matheusmarnt\Scoutify\Contracts\ScoutDriver.Authorization Logic:
VisibilityRule for custom conditions:
VisibilityRule::make()->using(fn($record, $user) => $user->isAdmin());
Preview Pane Customization:
php artisan vendor:publish --tag=scoutify-views
resources/views/vendor/scoutify/preview-pane.blade.php.How can I help you explore Laravel packages today?