Skip to content
● Grav 2.2 is out: 2x faster cold starts and 96% less memory on big sites. Read the announcement →
Premium / YetiSearch Pro
Premium Plugin · v2.3.1

YetiSearch Pro

YetiSearch Pro provides Grav with the fastest search engine via a powerful local search, without requiring any external services or fees. Built on the new YetiSearch PHP library, it provides lightning-fast file-backed search with fuzzy matching, chunked indexing, geospatial queries, and smart change detection.

Grav 1.7+
Live Demo Documentation

Everything you need. Nothing you don’t.

Over 30 distinct features and integrations, out of the box.

01
100% local file-backed search - no external services required
02
Optional semantic search finds pages by meaning as well as keywords, using OpenAI, OpenRouter, Ollama or any OpenAI-compatible embedding API
03
PDF indexing makes the text inside your PDFs searchable, with results that open the PDF at the right page (PHP 8.3+)
04
Two modal designs - Simple (lightweight typeahead) or Full (two-panel with preview)
05
Smart Indexing with fingerprint-based change detection for efficient updates
06
Built with vanilla JavaScript - no framework dependencies
07
Easy theming with CSS variables for quick customization
08
Fuzzy search with configurable typo tolerance
09
Optional stemming, so a search for runs also finds running (English, French, German and Spanish)
10
Chunked indexing for precise search results within long content
11
Multi-language support with per-language or single-index strategies
12
Real-time updates - index updates automatically on page save/delete
13
Orphan cleanup automatically removes stale documents from deleted pages
14
Keyboard shortcuts - Cmd+K / Ctrl+K to open, arrow keys to navigate, Enter to select
15
Beautiful search result highlighting with contextual snippets
16
Configurable field boosting for title, headers, content, and more
17
Filters on taxonomy and other fields
18
Geo search lists pages by distance or within a radius, with an optional Near me button for visitors
19
Analytics tracking for searches, clicks, and popular terms
20
Powerful CLI commands for indexing and querying
21
Scheduled indexing via Grav Scheduler for automated updates
22
Granular permissions - view, modify, and admin roles for team access control
23
Environment-aware configuration for dev/staging/production workflows
24
Page-level controls - exclude pages or content blocks via frontmatter or shortcode
25
Cache management CLI for monitoring, warming, and purging search cache
26
Suggestions endpoint for lightweight typeahead autocomplete
27
Extensible events to change documents before they're indexed and to index content that isn't a page
28
Works with any theme - includes ready-to-use Twig partials
29
Light/Dark/System appearance modes
30
Preview panel option showing breadcrumbs, content summary, and on-page sections
Smart Indexing

Smart Indexing

YetiSearch Pro features Smart Indexing with fingerprint-based change detection. When you update content, only the changed portions are re-indexed - not the entire site. Combined with chunked indexing that splits pages into smaller segments, you get precise search results that link directly to the relevant section. This makes indexing fast and keeps your search results highly relevant.

Two Beautiful Modal Designs

Choose between two search modal designs based on your needs. Full Modal provides a two-panel design with results on the left and a live preview on the right, including pagination, filter controls, breadcrumbs, and On This Page sections - perfect for documentation sites. Simple Modal offers a lightweight typeahead design with grouped results, clean and fast, ideal for blogs and general websites.

Two Beautiful Modal Designs
Powerful CLI

Powerful CLI

Full command-line interface for development, testing, and automation. Index your entire site or specific languages with progress bars. Query with filters, sorting, fuzzy search, and pagination. Manage cache with stats, monitoring, warming, and purging. Run scheduled tasks for automated maintenance. Supports JSON output for scripting and CI/CD integration.

Powerful Admin Interface

YetiSearch Pro includes a comprehensive Admin Dashboard for managing every aspect of your search. Monitor index health with document counts, index sizes, and timestamps, then trigger a full reindex with real-time progress tracking. The built-in Search Analytics panel tracks popular queries, top clicks, zero-result searches, and average response times - helping you identify content gaps. An Index Browser lets you inspect, search, and even edit individual documents, view debug statistics, and optimize indexes directly from the admin.

Powerful Admin Interface
Smart Fuzzy Queries

Smart Fuzzy Queries

YetiSearch Pro delivers highly relevant results through a multi-layered ranking system. Configurable field boosting lets you weight titles, headers, tags, and content independently, while a re-ranking engine applies bonuses for exact matches, prefix matches, and word matches in key fields. Enable fuzzy search with tunable typo tolerance so users find what they need even with misspellings, and "Did you mean" suggestions automatically guide users toward better queries when results come up empty.

Frequently Asked Questions

The most commonly asked questions about YetiSearch Pro

How does YetiSearch Pro compare to Algolia Pro?

Both are excellent search solutions with different approaches:

  • Algolia Pro uses Algolia's cloud infrastructure - Fast, AI-powered, but requires an Algolia account and has usage-based pricing
  • YetiSearch Pro runs entirely locally on your server - Incredible fast due to network latency, no external services, no API costs, no usage limits, and your data never leaves your infrastructure

Choose Algolia Pro for massive scale and AI features. Choose YetiSearch Pro for privacy, simplicity, and zero recurring costs.

Do I need any external services?

No! YetiSearch Pro is completely self-contained. The search index is stored as files in your user/data/yetisearch-pro directory. There are no API keys to configure, no external services to maintain, and no usage limits to worry about. The one exception is optional semantic search, which needs an embedding API if you choose to turn it on.

Can it search inside PDFs?

Yes, from version 2.2.0. Turn on PDF Indexing in the plugin settings and reindex. Every PDF sitting in an indexed page's folder becomes a search result of its own, and clicking a hit opens the PDF at the page where the words were found.

The text is pulled out by YetiPDF, a PHP library we wrote for the job, so there are no server tools to install and it works on shared hosting. It's quick too: a 3,000 page manual takes about two seconds, and the extracted text is cached so a reindex only reads the PDFs that changed.

  • Needs PHP 8.3 or newer. On older PHP versions the setting is ignored and the rest of the plugin works as before
  • Scanned PDFs with no text layer can't be read, as there's no OCR
  • Limits on file size and page count keep very large PDFs from slowing down indexing
  • A PDF follows its page, so an unpublished or excluded page keeps its PDFs out of search
What are the server requirements?

YetiSearch Pro has minimal server requirements:

  • PHP 7.4 or higher (PHP 8.0+ recommended)
  • SQLite 3.24.0 or higher (3.35.0+ recommended for best performance)
  • SQLite FTS5 extension enabled
  • PHP extensions: pdo, sqlite3, mbstring, json
  • Standard Grav 1.7+ hosting environment
  • PHP 8.3 or higher for PDF indexing only. Everything else works on older versions

Check your SQLite version with: php -r "echo SQLite3::version()['versionString'];"

Can I use YetiSearch Pro on multiple sites?

Per the Grav Premium License, you need to have a license for each use.

How do I trigger search updates?

YetiSearch Pro offers multiple ways to keep your index current:

  • Real-time - Automatically re-indexes pages when saved or deleted in the Admin
  • CLI - Run bin/plugin yetisearch-pro index manually or in scripts
  • Scheduler - Configure automated indexing via Grav's built-in scheduler
What content can YetiSearch Pro index?

By default, YetiSearch Pro indexes Grav pages including title, content, excerpt, URL, taxonomy tags, and categories. Turn on PDF Indexing and the PDFs in those pages' folders are indexed as well. Using the plugin's events, you can:

  • Add custom page header fields
  • Index FlexObjects data
  • Include any custom content sources
How does geo search work?

Give a page a location, either with geo: { lat: 51.5074, lng: -0.1278 } in its frontmatter or with the Location fields on the page editor's YetiSearch tab. If your pages already keep coordinates under other keys, point YetiSearch Pro at those keys in the plugin settings. A search can then:

  • List the nearest pages first, with or without search words
  • Keep only the pages within a radius, in kilometers, miles or meters
  • Show the distance on every result, such as 1.3 km

Turn on the Near me button in the full modal and visitors can find what's around them. Their location stays in the browser and is sent only with the search, and it's never stored. It's useful for store locators, event listings, real estate sites, and any content with a location. Available from version 2.3.0.

Can a search find other forms of a word?

Yes, with stemming, available from version 2.3.0. A search for "runs" also finds "running", and "configured" finds "configuration". Pages with the word exactly as typed still rank first. It works in English, French, German and Spanish, and on a multi-language site each page is stemmed in its own language.

Stemming is off by default, because it makes indexing slower and the index bigger: on the Helios demo the index grew by about a third. Turning it on or off rebuilds the search index from what's already stored, so there's nothing to reindex by hand. On the Helios demo that took a few hundredths of a second.

Can I extend YetiSearch Pro for custom content?

Absolutely! YetiSearch Pro fires several events for extensibility:

  • onYetisearchCollectObjects - Add non-page documents (FlexObjects, custom data) to the index
  • onYetisearchBuildDocument - Change a document's fields before it's indexed (add custom frontmatter fields or a location)
  • onYetisearchProBeforeSearch - Modify filters or options before queries execute
Does it work with the Helios theme?

Yes! YetiSearch Pro and the Helios documentation theme are designed to work together beautifully. Helios includes built-in YetiSearch Pro integration with the Cmd+K keyboard shortcut pre-configured.

YetiSearch Pro Changelog

v2.3.1

2 days ago

    • The simple modal is the default everywhere. The shipped yetisearch-pro.yaml has used it since 1.0.3, but the plugin settings form, the code's fallback when no type is set and the README still said full. A site that sets modal.type keeps its choice
    • The plugin's description, shown in GPM and the admin's plugin list, mentions stemming instead of facets, which YetiSearch Pro does not offer

v2.3.0

4 days ago

    • Geo search. Give a page a location with geo: { lat: 51.5074, lng: -0.1278 } in its frontmatter, or with the new Location group on the YetiSearch tab of the page editor (Admin Next and the classic admin), and search by distance. A page gets a location only when both numbers are valid (latitude -90 to 90, longitude -180 to 180), never 0,0 from a missing value. PDFs and chunks are found at their page's location, and changing a location is picked up by the next index and by saving the page. It works without SQLite's R-Tree module
    • The /ys endpoint, the Twig yetisearch() function and the onYetisearchProBeforeSearch event's options take lat and lng (both needed), radius (without it every page with a location is returned), units (km, mi or m) and sort=distance. With a location, an empty query lists the nearest pages (as if sort=distance were given, on the endpoint, in Twig and in the CLI). That rule is applied after the onYetisearchProBeforeSearch event, so a listener can supply a location for an empty query, and an empty query with no valid location after the event returns an empty result. Invalid coordinates are ignored and the search runs as a normal one. Every hit has distance (meters) and distance_text (for example 1.3 km or 0.8 mi, translatable), and the response has a geo entry with the location used
    • A Near me button for the full modal, off by default. Turn it on with modal.near_me: true: the visitor's browser is asked for their location, the modal lists nearby results (also with an empty search box), offers a radius menu (modal.near_me_radii, plus the starting modal.near_me_radius when it is not in the list), and says so when the location is denied or unavailable. The coordinates stay in the browser and are sent only with the search request. Both modals and the built-in search page show each result's distance
    • Analytics never store a visitor's coordinates. A recent search only records whether it used a location
    • New settings: indexes.pages.geo (lat and lng, dot paths into the page header, default geo.lat and geo.lng) replaces geo_fields, which nothing read, so a site that already keeps coordinates under other keys can point at them; indexes.pages.query_defaults.geo.units (default km) sets the units when a request names none. All of them, and the Near me options, are in the plugin settings form
    • bin/plugin yetisearch-pro query takes --lat, --lng, --radius, --units and --sort distance, and shows a distance column. The query can be left out when there is a location
    • To set a page's location from code, an onYetisearchBuildDocument listener must assign the changed document back with $event['doc'] = $doc; editing $event['doc']['geo'] in place is not kept. The README has a tested example
    • Stemming, per index and off by default. With indexes.pages.stemming: true, or Stemming (Pages) in the plugin settings, a search also matches other forms of a word: runs finds "running", configured finds "configuration", utilisateur finds "utilisateurs". A per-language index stems in its own language. A single index stems each page in its own language, and a search in the language it names, else the site's default language. English, French, German and Spanish are supported. Matches on the word as typed rank first, search.stem_weight (default 0.5) sets how much a stem match counts, and highlights include stem matches. It costs indexing time and index size: on the Helios demo the database was about a third bigger, and the library measured indexing about 2.5 times slower and the database about 50% larger on 32,000 documents. The README's new Stemming section has the details
    • Changing the stemming setting switches each existing index with one rebuild of its full-text index from the documents it holds, without indexing the pages again. It happens when the plugin settings are saved in either admin, with the settings the site runs with after the save (an environment's override included), or else at the next index run, page save or page delete. Saving another environment's settings file leaves this environment's indexes alone; that environment switches at its own next index run or page save. While any GRAV_CONFIG__ environment variable is set, whichever settings it is for, a save leaves the indexes alone too, and the next index run, page save or page delete switches them with the settings the site runs with. bin/plugin yetisearch-pro index prints a line for each index it rebuilt, and the Grav log records it
    • Updated the bundled YetiSearch library to 2.6.1. With 2.5.x, deleting a page that has chunks or PDFs, or saving one that is left out of search (an unpublished page, for one), added the field names of the stored documents (title, route, content, url, ...) to the index as words, so a search for title or route returned every document until the next page save rebuilt the index. YetiSearch Pro rebuilds the full-text index of each existing index once after the upgrade, before anything is written to it or deleted from it: at the first index run, page save, page delete, PDF change or settings save, and records it in the index so it never runs again. This matters, as with 2.6.0 a delete from an index still holding those words breaks every later search for one of them (2.6.1 also rebuilds such an index itself on its first write). If the rebuild fails, the Grav log says so and nothing is written to that index until a later request rebuilds it. On the Helios demo sites it took a hundredth of a second per index, and nothing needs to be reindexed by hand. A page indexed again with less content no longer keeps the chunks of its longer version, which were still found by words the page no longer has. Stop words now follow the language code, so a French search leaves out French stop words rather than English ones, and a language with no list, such as Italian, leaves out none. From the 2.5.x releases since 2.2.2: a search never returns results from before a write made in the same process, geo search works on PHP builds whose SQLite has no R-Tree module, with exact radius searches, totals and paging, and a page whose location is removed drops out of location searches the next time it is indexed
    • An index run reported success when an index failed: bin/plugin yetisearch-pro index, the reindex in either admin, the API and the scheduler all said the run had completed. They now report the failure, naming the index and the reason: the command exits with status 1, the admins show the error, and the result's success is false. A stale document (one whose page is gone) that a run could not remove, for instance while its index waits for the one-time cleanup, was dropped from the saved index state anyway, so it stayed searchable and no later run would remove it; it now stays recorded, the next run removes it, and only documents actually removed are counted. The same goes for a PDF whose old pages could not be cleared before it was indexed again. A page save that could not clear the page's old chunks or PDF pages saved the new fingerprints anyway, so the next run skipped the page and its PDFs as unchanged and the old chunks and PDF pages stayed searchable; the page and its PDFs are now recorded as not yet indexed, and the next run indexes them again and removes their old chunks and PDF pages first
    • The built-in search page (built_in_search_page: true) works. Its template called the Twig functions yetisearch() and yetisearch_form(), which were never registered, so the page failed to render. Both exist now, and yetisearch(query, options) runs the same search as the /ys endpoint, so language handling, the onYetisearchProBeforeSearch event and analytics apply to it too. The template reads the fields hits really have, takes q and page from the query string, shows the search time in seconds, and escapes result text while keeping the <mark> highlights
    • The Type filter in the admin Index Browser now applies when you search by text. It was only applied when browsing without a query
    • Search results are no longer able to inject markup. The library's highlights escape nothing and titles are stored as typed, so a page titled <img src=x onerror=...> came back with live markup in the full modal's preview, its breadcrumb line, the simple modal and the built-in search page. Every place that outputs a highlight now turns each < that does not start <mark> or </mark> into &lt;, and leaves page text's own entities alone, so code samples in your pages still read as code
    • The built-in search page prints the search text and the "did you mean" suggestion escaped, so it is safe with Twig autoescaping off, and a result's link is only used when it is a relative path or an http(s) URL: a custom document with url: javascript:... gets #
    • Paged results sorted by distance keep their order with unique_by_route on (the default), and unique_by_route=0, semantic=0 and fuzzy=0 in a request are no longer read as absent (0 is falsy, so unique_by_route=0 left de-duplication on). fuzzy=true and fuzzy=false work too.
    • Editing a document in the admin Index Browser keeps its location and its type, and the classic admin editor's save works again: it sent the document without the content object the update requires, so every save failed with "Document payload must include a content object"
    • The full modal's radius menu always contains the starting radius, sorted and without duplicates. With near_me_radius: 17 and the default list, nothing was selected and the browser picked "Any distance"
    • The search modals send their requests to your configured query_route instead of always using /ys (the site's base URL is still included for sites in a subfolder). Themes that build their own modal still need to read query_route themselves
    • A search request with an array q (?q[]=x) no longer fails with a server error on the search page, the /ys endpoint or any page; it counts as no query
    • A request with ?q= on an ordinary page (/blog?q=anything, a tracking link, a theme's own search form, a bot) no longer runs a YetiSearch search whose results nothing read. The search now runs only on the query_route page (the /ys result without ajax or a JSON header) and on a page of the site's own at search_route (one that reads yetisearch_results); the built-in search page calls yetisearch() instead. yetisearch_query is still set everywhere
    • The query_route page without ajax or a JSON header (opening /ys?q=coffee in a browser) returned its JSON HTML-escaped (&quot; for every quote) with Twig autoescaping on, which is the default, so it could not be parsed. It is valid JSON now, and without a query it returns the empty result envelope instead of []
    • The full modal marked a search word twice in a title (<mark><mark>coffee</mark></mark>) and could match inside markup or an entity: a search for mark broke the highlight tag and showed it as text, and a search for 39 matched inside Tom&#39;s. Titles and breadcrumb lines are now highlighted in one pass over the plain text, using the search words and the words the search engine highlighted, and escaped afterwards
    • Saving a page no longer rebuilds the whole full-text index afterwards. YetiSearch 2.6.0 keeps the index's words in step on every write and delete, so a page save no longer takes longer as the index grows
    • Removed settings that nothing read: Indexed Fields (Pages) (indexes.pages.fields), indexes.pages.facets, indexes.pages.options.typo_tolerance, and the README's claim that options.search can be set per index. They are gone from the plugin settings form, the default yetisearch-pro.yaml and the README. Values already saved in your own config are ignored, as they were before. Search settings come from engine.search and indexer settings can still be set per index with options.indexer
    • README: the Filter DSL section now shows the two forms the /ys endpoint accepts, filter[field][operator]=value and field:operator:value joined with AND. The old field[op]value example was never accepted and its filter was dropped without an error. The onYetisearchPageSkip event is documented with the arguments it receives, page and config, and setting skip to true on the event leaves a page out
    • bin/plugin yetisearch-pro query -F help and the README said field[op]value, but the filter is written without brackets: type=content, price>=10, taxonomy.category=plugins. A filter the command cannot read, such as type[=]content, now prints a warning naming it on stderr (so --raw JSON on stdout stays valid) instead of being dropped without a word, or read as a filter on a field called type[

v2.2.2

6 days ago

    • Updated the bundled YetiSearch library to 2.5.3, which fixes facets: range facets now work on any numeric field (they were only read by the distance facet), YetiSearch::search() no longer drops the facets option, a facet on a list field such as tags no longer fails the search, and float values are no longer cut to integers. YetiSearch Pro's own search does not request facets, so this matters to sites that call the bundled library directly

v2.2.1

1 week ago

    • Updated the bundled YetiSearch library to 2.5.2, which ships its SQLite feature check again. Run php user/plugins/yetisearch-pro/vendor/yetidevworks/yetisearch/scripts/check_sqlite_features.php to see whether your PHP has the FTS5 and R-tree support that search needs

v2.2.0

1 week ago

    • PDF indexing. The text inside PDFs is now searchable. Turn on PDF Indexing in the plugin settings and reindex: every PDF in an indexed page's folder becomes a search result of its own, and a hit links to the page of the PDF where the words were found (file.pdf#page=12). Text is extracted in PHP by the bundled YetiPDF library, so there is nothing to install on the server
    • PDF indexing needs PHP 8.3 or newer. On older PHP versions the setting is ignored, a notice goes to the Grav log, and everything else works as before
    • Largest PDF (default 50MB) and Most Pages per PDF (default 1000) settings keep very large files from slowing down indexing
    • Extracted text is cached, so a reindex only reads the PDFs that changed. Uploading or deleting a PDF in the admin updates the index straight away when real-time indexing is on
    • Index this page's PDFs on the page editor's YetiSearch tab (yetisearch-pro: index-pdfs: false in frontmatter) keeps the page in the index but leaves its PDFs out
    • PDF hits carry doc_type: pdf, pdf_file, pdf_page, pdf_pages, page_route and page_title in their metadata (result._meta) for use in templates
    • The YetiSearch tab on the page editor works again. It saved its settings under yetisearch-pro: in the page's frontmatter while indexing only read yetisearch:, so Index this page, Index child pages and the extra fields list had no effect when set in the admin. Both keys are now read, yetisearch-pro: is the documented one, and it wins if a page sets both. Pages that were switched off in the admin will leave the index on the next reindex
    • Saving a page in the admin no longer removes its child pages from the index. With real-time indexing on, saving /blog deleted the entries for every page under /blog, and because smart indexing still saw them as unchanged, only a reindex with --flush brought them back. Saving the home page did the same to the whole site
    • A page removed, unpublished or excluded outside the admin no longer leaves its sections behind in search results. A reindex removed the page's own entry but not the separate entries for each of its headings
    • Changes made by real-time indexing are now recorded in the smart indexing state, so the next reindex knows about pages added or removed since the last one
    • The plugin runs on PHP 7.4 as its requirements say. Several files used PHP 8 syntax (match, static return types, mixed and union parameter types), which stopped the search client, the indexer and the CLI commands from loading on PHP 7.4

v2.1.2

2 weeks ago

    • Plugins that change documents through onYetisearchBuildDocument now see pages saved in the admin too. Before, the event fired only during a full reindex, so a page saved in the admin was stored as built until the next reindex

v2.1.1

3 weeks ago

    • Noise calibration. Semantic search now works out for itself where nonsense stops and real searches start on your content. After each full embedding run it embeds a set of meaningless test phrases, measures how closely they match your pages, and sets the cutoff just above that. A small site and a large one need very different cutoffs, and one fixed number either let nonsense through on the large site or turned real searches away on the small one. Set Noise Calibration to Off to keep the 2.1.0 behavior
    • Calibration Strictness setting (default 2.0) moves the cutoff up or down without re-embedding. Lower it if good matches are missing, raise it if nonsense gets through
    • The YetiSearch Pro page in Admin Next shows each index's noise cutoff, whether it was measured or is the default, and any test phrases that were skipped because they match your own content. bin/plugin yetisearch-pro embed --status shows the cutoff too
    • Requires yetidevworks/yetisearch 2.5.1
    • bin/plugin yetisearch-pro embed measures the cutoff even when every page is already embedded, so an upgraded site gets calibrated without re-embedding anything

v2.1.0

3 weeks ago

    • Semantic search. Search can now find pages by meaning as well as keywords: "can't log in" finds the password reset page, "hire an advisor" finds the consulting page. Turn it on under Semantic Search in the plugin settings and point it at an embedding API: OpenAI, OpenRouter, a self-hosted Ollama server, or anything else that speaks the OpenAI embeddings API. Keyword and meaning rankings are merged, so pages that match on both rank first. Without it enabled nothing changes
    • Pages are embedded after each save once the response has been sent, after a reindex, by a new Semantic Search Embedding scheduler job (every 15 minutes, on by default, runs only while semantic search is enabled), or with the new bin/plugin yetisearch-pro embed command (--status, --test, --reset). Only new or changed pages are sent to the provider, so reindexing unchanged content costs nothing. bin/plugin yetisearch-pro index embeds afterwards unless given --no-embed, and bin/plugin yetisearch-pro schedule --task embed runs the job by hand
    • The YetiSearch Pro page in Admin Next shows embedding coverage with a progress bar, and has Embed, Test connection and Re-embed all buttons
    • The search modals show keyword results while the visitor types and replace them with results ranked by meaning once typing pauses, so no keystroke waits on the embedding provider. The /ys endpoint accepts semantic=0 for keyword ranking only and reports semantic in its response
    • Settings for provider, API base URL, API key (or env:NAME to read it from the environment), model, dimensions, the balance between meaning and keywords, minimum similarity, minimum query length, search timeout and query/document prefixes, plus a Semantic Search toggle per index. If the provider is slow or unreachable, searches fall back to keywords
    • Requires yetidevworks/yetisearch 2.4, under its correct package name (the plugin asked for yetisearch/yetisearch, a name that does not exist on Packagist)
    • Pages saved in Admin Next are indexed again right away. Admin Next saves pages through the API plugin, which fires onAdminAfterSave rather than onFlexAfterSave, so realtime indexing never ran for those saves
    • On a multi-language site, a page saved with realtime indexing on no longer ends up in the index twice. The realtime update built the document id without the page's language, so it added a second copy next to the one a full index had written instead of replacing it

v2.0.3

1 month ago

    • A page reached through version fallback no longer has its Twig processed twice, which could abort the whole index run. A page that documents Twig inside {% verbatim %} threw "Unexpected end of template" on the second pass, and because that happened outside the guard around normal rendering, one such page stopped the run instead of falling back to raw markdown

v2.0.2

1 month ago

    • An API key limited to specific permissions can no longer use YetiSearch Pro's tools beyond what it was given, even when the account that created it is a super admin. A key limited to YetiSearch Pro keeps working at the level it was given