https://github.com/matheusmarnt/scoutify
⌘K global search modal for Laravel — multi-model Livewire UI powered by Scout.
https://github.com/matheusmarnt/scoutify
algolia global-search laravel laravel-package laravel-scout livewire meilisearch pest php search tailwindcss typesense
Last synced: about 2 months ago
JSON representation
⌘K global search modal for Laravel — multi-model Livewire UI powered by Scout.
- Host: GitHub
- URL: https://github.com/matheusmarnt/scoutify
- Owner: matheusmarnt
- License: mit
- Created: 2026-04-27T02:07:15.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-30T17:14:22.000Z (about 2 months ago)
- Last Synced: 2026-05-02T04:02:34.834Z (about 2 months ago)
- Topics: algolia, global-search, laravel, laravel-package, laravel-scout, livewire, meilisearch, pest, php, search, tailwindcss, typesense
- Language: PHP
- Homepage:
- Size: 1.67 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
Awesome Lists containing this project
README
# Scoutify
⌘K global search modal for Laravel — multi-model Livewire UI powered by Scout.
Drops a production-ready ⌘K search experience into any Laravel application. Register Eloquent models, choose a Scout driver, and ship a keyboard-triggered modal that queries multiple model types simultaneously, groups results by type, and persists recent search history to session.
## Features
- **Livewire modal** — keyboard-triggered (`⌘K` / `Ctrl+K`) global search dialog
- **Zero-config discovery** — models under `app/Models/` using `Searchable` are auto-detected at boot
- **Grouped results** — results organised by model type with section headers and color tokens
- **Multiple drivers** — Meilisearch, Algolia, Typesense, or Database
- **Query hook** — per-model `globalSearchBuilder()` for custom filters, scopes, or infix matching
- **Recent searches** — configurable history, persisted to session
- **i18n** — ships with `pt_BR`, `en`, and `es` translations
- **Dark mode** — full dark mode support out of the box
- **WCAG AA** — accessible markup with focus management and keyboard navigation
- **Tailwind v4** — utility classes inlined, override via config
## Quick Start
```bash
composer require matheusmarnt/scoutify
php artisan scoutify:install
```
This will:
1. Prompt for a Scout driver (`meilisearch`, `algolia`, or `typesense`)
2. Install the driver's Composer packages
3. Publish `config/scoutify.php`
4. Set `SCOUT_DRIVER` in `.env`
## Registering Models
Make your Eloquent models globally searchable:
```bash
php artisan scoutify:searchable
```
The command discovers Eloquent models under `app/Models/`, prompts you to pick which to register (or pass `--all`), and **automatically edits each chosen model file** to:
1. Import `Matheusmarnt\Scoutify\Concerns\Searchable` and `Matheusmarnt\Scoutify\Contracts\GloballySearchable`
2. Add `implements GloballySearchable` to the class declaration
3. Insert `use Searchable;` as the first statement in the class body
The command then rebuilds the type manifest so models appear in the UI immediately.
The `Searchable` trait provides sensible defaults for every interface method. Override as needed:
```php
public function globalSearchTitle(): string { return $this->title; }
public function globalSearchSubtitle(): ?string { return $this->author; }
public function globalSearchUrl(): string { return route('articles.show', $this); }
public static function globalSearchGroup(): string { return 'Articles'; }
public static function globalSearchLabel(): string { return 'Articles'; } // UI chip label
public static function globalSearchIcon(): string { return 'heroicon-o-document-text'; }
public static function globalSearchColor(): string { return 'blue'; }
```
Use `--dry-run` to preview edits without touching files:
```bash
php artisan scoutify:searchable --dry-run
```
Then import your models into the Scout index:
```bash
php artisan scoutify:import
```
Add to your layout:
```blade
```
## Customizing the Scout Query
Override `globalSearchBuilder()` on any model to apply custom filters, scopes, or driver-specific options:
```php
use Laravel\Scout\Builder;
public function globalSearchBuilder(Builder $builder, string $query): Builder
{
return $builder->where('published', true);
}
```
> **Meilisearch note:** Meilisearch uses word-boundary prefix search. Substrings that are not word-prefixes (e.g. `"ano"` inside `"Mariano"`) return no results. If you need substring (infix) matching, override `globalSearchBuilder()` to configure Meilisearch's `attributesToSearchOn` or switch to the `database` driver which uses `LIKE`-based search.
## Opening the Modal Programmatically
Any element can open Scoutify without the official trigger component.
**Alpine (recommended):**
```html
Search
```
**Plain JS / any context:**
```js
window.dispatchEvent(new CustomEvent('scoutify:open'))
```
**Inside a Livewire component:**
```html
Search
```
> **Do not use** `wire:click="$dispatch('scoutify:open')"` on plain Blade elements — outside a Livewire component tree, Livewire.js never initialises those directives.
## Commands
| Command | Description |
|---|---|
| `scoutify:install` | Install driver packages, publish config, configure backend |
| `scoutify:doctor` | Verify driver config and backend connectivity |
| `scoutify:searchable` | Register models as globally searchable and rebuild manifest |
| `scoutify:rebuild` | Rebuild the type manifest from `app/Models/` |
| `scoutify:import` | Import registered models into Scout index |
| `scoutify:flush` | Flush registered models from Scout index |
| `scoutify:sync` | Flush then re-import |
## Documentation
- [Installation guide](docs/installation.md) — step-by-step setup, model registration, Tailwind config, customization
- [Production deployment](docs/production.md) — per-driver production configuration (Meilisearch, Algolia, Typesense, Database)
## Testing
```bash
composer test
```
## Contributing
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
## License
MIT — see [LICENSE](LICENSE.md).