Skip to main content

Documentation

No results found.
Features Members

Advanced Search (Meilisearch)

WebProCMS's free-tier search (search.md) is plenty for most sites — but past a few thousand records, or for a polished editor experience that works the way users expect search to, the database falls short. The Advanced Search add-on swaps t...

WebProCMS's free-tier search (search.md) is plenty for most sites — but past a few thousand records, or for a polished editor experience that works the way users expect search to, the database falls short. The Advanced Search add-on swaps the engine for Meilisearch, an open-source search server purpose-built for instant typo-tolerant ranked search, and adds a cmd-K command palette in the dashboard plus public-site search on the front end.


What it adds over the free tier

Compared to Standard Search (LIKE) or even MySQL FULLTEXT, Meilisearch brings four real upgrades that you can't get from the database alone:

  • Inline, per-keystroke typo tolerance. Searching "restraunt" finds "restaurant" inside every ranked query, on every keystroke; "Joh Smtih" finds the form submission from "John Smith". The free tier now corrects public-site misspellings too (search.md "Typo correction"), but as a correction pass over site content — it can't tolerate typos mid-ranking, doesn't cover dashboard search (users, media, submissions), and doesn't work as-you-type. Meilisearch matches one or two typos automatically based on word length, everywhere.
  • Sub-50ms search. Meilisearch indexes data in memory and returns ranked results in single-digit milliseconds even on millions of records. The free tier's LIKE '%query%' always scans every row of the table, and even FULLTEXT slows down past 100k+ records.
  • Better ranking. Meilisearch ranks results by a configurable mix of typo proximity, word position, and proximity-of-words-to-each-other — closer to how Google surfaces matches than MySQL's MATCH AGAINST score.
  • Highlights and snippets. Search results return the matched fragments with the query terms wrapped, ready to display in result lists.

On top of the engine, the add-on ships two concrete features the free tier doesn't include:

  • Dashboard cmd-K command palette — a global Cmd+K (Mac) / Ctrl+K (Windows) keyboard shortcut opens a search modal with results from every searchable model on the site, grouped by type, with keyboard navigation. Pages from any language are included; clicking a result lands you in the editor with the matching locale pre-selected.
  • Public-site search — a /search route + a search box partial that searches Posts, Events, Locations, and Pages from the front-end. Same Meilisearch index, scoped to public-facing content.

Plus one Meilisearch-only relevance control (below). The federated result grouping, pinned-result curation, and search-analytics surfaces are engine-agnostic and documented in the free-tier search doc — they work under LIKE and FULLTEXT too, and simply get better ranking under Meilisearch.

Synonyms & stop words

Meilisearch exposes per-index relevance settings that the free engines can't; the add-on surfaces the two most useful ones at Settings → Search → Synonyms & Stop Words (the card only appears when the add-on is enabled):

  • Synonyms — one equivalence group per line, comma-separated (tv, television, telly). Every word in a group is treated as interchangeable with the others, so a search for any of them matches records using the others. Internally each group is expanded into the word → [others] map Meilisearch's updateSynonyms expects (a word appearing in multiple lines merges its groups).
  • Stop words — words ignored during ranking (the, a, of), comma- or newline-separated.

Both lists are stored as raw text in Settings (search.synonyms / search.stop_words) so they survive with or without a live Meilisearch connection, then pushed to every searchable index on save and re-applied automatically on a full index rebuild (Rebuild Meilisearch Index, or a mode switch to Meilisearch). Under the LIKE / FULLTEXT engines the settings are kept but inert. Implemented in SearchSynonyms.

Enabling

  1. Install Meilisearch. Local Herd Pro: toggle on the built-in service. Local with brew: brew install meilisearch && meilisearch. Production: Meilisearch Cloud (managed, free tier available), self-hosted single binary, or Docker. See the official docs for any of these — the WebProCMS side doesn't care which one.
  2. Enable the feature. Dashboard → Settings → Features → Advanced Search → toggle on.
  3. Configure the host. Dashboard → Settings → Search — pick "Meilisearch" as the search engine, fill in the host URL (e.g. http://localhost:7700) and master key, click Save.
  4. Index your data. Run php artisan scout:import "App\\Models\\Post" (and similar for Event, Location, ContentItem, MediaItem, FormSubmission, User, PageSearchEntry) to seed the index. Future writes are picked up automatically by Scout's model observers.

The toggle in step 2 sets Features::enabled('advanced_search') to true; without it the radio in step 3 is greyed out. Disabling the feature is non-destructive — your data stays in Meilisearch, but SearchService::activeMode() falls back to like until you re-enable.

How it integrates with the free tier

Every model that's searchable in the free tier is searchable here too — same toSearchableArray(), same models, same UI. Switching modes is instant:

  • The same Model::search($query) calls work everywhere — controllers, Livewire components, blade templates. No conditionals on which engine is active.
  • The page search index (page_search_entries) is reused; Meilisearch indexes the same table and rows the database driver does. So multilingual page search behaves identically — one result per (page, language).
  • Switching back from Meilisearch to a free mode is a one-click change in Settings → Search. Your indexed data in Meilisearch remains; the free engine just uses the database directly until you flip back.

Implementation notes

  • SearchService::scoutDriver() returns 'meilisearch' when the active mode is meilisearch; SearchServiceProvider::register() overrides config('scout.driver') accordingly so Scout sees the right driver before any model triggers a search.
  • Configuration is stored in Setting::get('search.meilisearch_host') / search.meilisearch_key, mirrored to runtime config on save so the change applies on the next request without a restart.
  • The cmd-K palette is a Livewire component mounted on every dashboard layout; the keyboard shortcut listener is in resources/js/app.js.
  • Front-end search is a public route + a <x-search-box> blade component that posts to a controller calling Model::search($query) across the public-facing models.
  • Synonyms & stop words are pushed to every index returned by SearchService::searchableModels() via a fresh Meilisearch\Client; the push is a no-op unless Meilisearch is the active engine and the PHP client is installed, and each index is handled independently so one failure doesn't abort the rest.
  • Documentation articles join SearchService::searchableModels() (and therefore the Meilisearch rebuild) only when the Documentation add-on is enabled, so a disabled feature's un-migrated table never surfaces as a rebuild error.

Trade-offs vs. self-hosted free-tier MySQL FULLTEXT

If you're on MySQL with FULLTEXT installed and your site has under ~10k records per model, the user-visible difference is mostly instant as-you-type search + ranking quality + the cmd-K palette (the free tier corrects public-site typos on its own now — Meilisearch's tolerance is broader and per-keystroke). The fundamental "find me the post about pricing" search works fine in either mode.

What pushes a site over the line:

  • Records past 100k — Meilisearch stays sub-50ms; FULLTEXT starts to slow down.
  • Multilingual site with non-Western scripts — MySQL FULLTEXT's word-boundary detection is shaky on CJK / Arabic; Meilisearch handles them natively.
  • Editors who actually use the search — the free typo correction covers the public site only; the dashboard's cmd-K palette (users, media, form submissions, every admin record) gets typo tolerance exclusively from Meilisearch. On large sites with many editors, this is the killer feature.
  • Public site search as a real product surface — when search is part of the visitor experience (knowledge base, large content library, large product catalog), Meilisearch's relevance + speed matters.