{"id":30302697,"url":"https://github.com/soderlind/wp-loupe","last_synced_at":"2026-02-20T13:01:44.536Z","repository":{"id":218277019,"uuid":"745012783","full_name":"soderlind/wp-loupe","owner":"soderlind","description":"WP Loupe is a powerful search enhancement plugin for WordPress that delivers fast, accurate, and typo-tolerant search results. WP Loupe exposes a developer-friendly API so you can build your own search UI.","archived":false,"fork":false,"pushed_at":"2026-01-22T22:38:59.000Z","size":1822,"stargazers_count":81,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-26T01:24:17.942Z","etag":null,"topics":["developer-friendly","loupe","search-engine","searching","typo-tolerant","wordpress-plugin"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soderlind.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":"https://paypal.me/PerSoderlind"}},"created_at":"2024-01-18T13:19:00.000Z","updated_at":"2026-01-15T10:00:32.000Z","dependencies_parsed_at":"2024-01-20T22:29:51.896Z","dependency_job_id":"33f786f3-18db-4ab0-83cc-82b310293b43","html_url":"https://github.com/soderlind/wp-loupe","commit_stats":null,"previous_names":["soderlind/wp-loupe"],"tags_count":49,"template":false,"template_full_name":null,"purl":"pkg:github/soderlind/wp-loupe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fwp-loupe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fwp-loupe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fwp-loupe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fwp-loupe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soderlind","download_url":"https://codeload.github.com/soderlind/wp-loupe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fwp-loupe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29651967,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T09:27:29.698Z","status":"ssl_error","status_checked_at":"2026-02-20T09:26:12.373Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-friendly","loupe","search-engine","searching","typo-tolerant","wordpress-plugin"],"created_at":"2025-08-17T05:09:59.177Z","updated_at":"2026-02-20T13:01:44.530Z","avatar_url":"https://github.com/soderlind.png","language":"PHP","funding_links":["https://paypal.me/PerSoderlind"],"categories":[],"sub_categories":[],"readme":"\u003e **0.5.2 and later, require PHP 8.3**\n\n# WP Loupe - Enhanced WordPress Search\n\nA search enhancement plugin for WordPress that builds a fast, typo-tolerant index and exposes a developer-friendly API so you can build your own search UI.\n\n## Quick Links\n\n[Installation](#installation) | [REST API](#rest-api) | [Building Your Own Search UI](#building-your-own-search-ui) | [Settings](#settings) | [Filters](#filters) | [MCP Docs](docs/mcp.md) | [Changelog](CHANGELOG.md)\n\n\n## Overview\n\nWP Loupe transforms WordPress's search functionality by:\n\n- Creating a dedicated search index for lightning-fast results\n- Supporting typo-tolerant searches\n- Automatically maintaining the search index\n- Providing a stable REST API for custom search experiences\n\n\u003e Integrating with external agents or automation? See **[docs/mcp.md](docs/mcp.md)**.\n\n## REST API\n\nWP Loupe exposes search via REST endpoints:\n\n- **POST** `/wp-json/wp-loupe/v1/search` (recommended; supports JSON filters, facets, geo, and explicit sorting)\n- **GET** `/wp-json/wp-loupe/v1/search?q=...` (legacy; kept for backward compatibility)\n\nDeveloper documentation (schema + examples + Gutenberg block example): **[docs/search-api.md](docs/search-api.md)**\n\n## MCP (Model Context Protocol) Integration (Summary)\n\nWP Loupe ships with an optional MCP server enabling external AI agents or automation tools to discover commands and query your site.\n\nKey points:\n- Discovery endpoints: `/.well-known/mcp.json` \u0026 `/.well-known/oauth-protected-resource` (enable in Settings → WP Loupe → MCP)\n- Hybrid access: anonymous users can run limited `searchPosts`; tokens increase limits \u0026 unlock `healthCheck`\n- Token UI: create, scope-limit, set TTL (1–168h) or indefinite (0), revoke individually or all\n- Last-used tracking for tokens; copy raw token once on creation\n- Configurable rate limits (window, per-window quotas, max hits) via admin UI + filter overrides\n- WP-CLI command for issuing tokens (mirrors into UI registry)\n- Secure pagination cursors (HMAC) and standardized envelope responses\n\nFull details, filter references, and examples: see [docs/mcp.md](docs/mcp.md).\n\n## Features\n\n- Fast index-backed search for configured post types\n- Typo-tolerance (Loupe)\n- Per-field weighting, filterable fields, sortable fields (configured in Settings)\n- Developer-facing REST API for building custom UIs\n- Optional MCP server for external agent/automation access\n\n## Installation\n\n1. **Quick Install**\n\n   - Download [`wp-loupe.zip`](https://github.com/soderlind/wp-loupe/releases/latest/download/wp-loupe.zip)\n   - Upload via WordPress Plugins \u003e Add New \u003e Upload Plugin\n\n2. **Composer Install**\n\n   ```bash\n   composer require soderlind/wp-loupe\n   ```\n\n3. **Post-Installation**\n   - Activate the plugin\n   - Go to Settings \u003e WP Loupe\n\t- Click \"Reindex\" to build the initial search index (runs in batches; safe for large sites)\n\n* Plugin [updates are handled automatically](https://github.com/soderlind/wordpress-plugin-github-updater#readme) via GitHub. No need to manually download and install updates.\n\n## Building Your Own Search UI\n\nWP Loupe works out of the box with WordPress’s standard search.\nIf your theme uses the normal search flow (e.g. a search form that routes to the built-in search results page), WP Loupe will power the results automatically — no custom UI required.\n\nWP Loupe intentionally does **not** ship a front-end search block/shortcode UI.\nIf you want a custom search experience (autocomplete, filters/facets, geo, custom sorting, etc.), build the UI you want and query WP Loupe via the REST API.\n\nStart here: **[docs/search-api.md](docs/search-api.md)**\n\n## Settings\n\nYou can configure WP Loupe's search behavior and performance via the WordPress admin: Settings \u003e WP Loupe.\n\n\n### General Settings\n\n#### Post Types\nSelect which post types to include in the search index.\n\n#### Field Weight\nWeight determines how important a field is in search results:\n\n- Higher weight (e.g., 2.0) makes matches in this field more important in results ranking.\n- Default weight is 1.0.\n- Lower weight (e.g., 0.5) makes matches less important but still searchable.\n\n#### Filterable Fields\nFilterable fields can be used to refine search results:\n\n- Enable this option to allow filtering search results by this field's values.\n- Best for fields with consistent, categorized values like taxonomies, status fields, or controlled metadata.\n- Examples: categories, tags, post type, author, or custom taxonomies.\n\nNote: Fields with highly variable or unique values (like content) make poor filters as each post would have its own filter value.\n\n\n#### Sortable Fields\nSortable fields can be used to order search results:\n\n- Enable this option to allow sorting search results by this field's values\n- Works best with numerical fields, dates, or short text values\n- Examples: date, price, rating, title\n\n### MCP Settings\n\nWP Loupe can optionally expose an MCP (Model Context Protocol) server so external AI agents or automation tools can discover capabilities and query your site.\n\nYou can configure MCP in the WordPress admin under Settings \u003e WP Loupe \u003e MCP, including:\n\n- Enable/disable the discovery endpoints (`/.well-known/mcp.json` and `/.well-known/oauth-protected-resource`)\n- Create and manage access tokens (scope + TTL + revoke)\n- Configure rate limits for anonymous vs token-authenticated requests\n- Add access tokens.\n\nFull details: **[docs/mcp.md](docs/mcp.md)**\n\n### Advanced Settings\n\nWP Loupe provides advanced configuration options to fine-tune your search experience:\n\n#### Prefix Search\n\n- Configure prefix search behavior. Prefix search allows finding terms by typing only the beginning (e.g., \"huck\" finds \"huckleberry\").\n- Prefix search is only performed on the last word in a search query. Prior words must be typed out fully to get accurate results. E.g. `my friend huck` would find documents containing huckleberry - `huck is my friend`, however, would not.\n\n#### Typo Tolerance\n\n- **Enable Typo Tolerance**: When enabled, searches will match terms with minor spelling errors.\n- **First Character Double Counting**: When enabled, typos in the first character of a word will count as two errors instead of one.\n- **Typo Tolerance for Prefix Search**: Allows typo tolerance in partial word searches.\n- **Alphabet Size**: Define the size of the alphabet for typo calculations.\n- **Index Length**: Configure the maximum length of indexed terms.\n- **Typo Thresholds**: Set the minimum word length required for allowing different numbers of typos.\n\n#### Query Parameters\n\n- **Maximum Query Tokens**: Limits the number of words processed in a search query (default: 12).\n- **Minimum Prefix Length**: Sets the minimum character length before prefix search activates (default: 3).\n\n#### Languages\n\n- Configure which languages the search index should optimize for. Default is English ('en').\n\nThese advanced settings can be accessed in the WordPress admin under Settings \u003e WP Loupe \u003e Advanced tab.\n\n## Reindexing\n\nReindexing rebuilds the index for your configured post types.\n\n- **Admin UI:** Settings → WP Loupe → click **Reindex** (runs in batches to avoid timeouts)\n- **WP-CLI (recommended for large sites):**\n\n\t```bash\n\twp wp-loupe reindex\n\t```\n\n\tOptional flags:\n\n\t```bash\n\twp wp-loupe reindex --post-types=post,page --batch-size=1000\n\t```\n\n## Testing\n\n- PHPUnit:\n\n\t```bash\n\tcomposer test\n\t```\n\n- Pest (runs using the PHPUnit config):\n\n\t```bash\n\tcomposer test:pest\n\t```\n\n\n\n## FAQ\n\n### How does it handle updates to posts?\n\nThe search index automatically updates when content is created, modified, or deleted.\n\n### Will it slow down my site?\n\nNo. WP Loupe uses a separate, optimized search index and doesn't impact your main database performance.\n\n### Can I customize what content is searchable?\n\nYes, using filters you can control exactly what content gets indexed and how it's searched.\n\n### Does it work with custom post types?\n\nYes, you can select which post types to include in the Settings page or via filters.\n\n## Filters\n\n### `wp_loupe_db_path`\n\nThis filter allows you to change the path where the Loupe database files are stored. By default, it's in the `WP_CONTENT_DIR .'/wp-loupe-db'` directory.\n\n```php\nadd_filter( 'wp_loupe_db_path', function ( $path ) {\n\treturn WP_CONTENT_DIR . '/my-path';\n} );\n```\n\n### `wp_loupe_post_types`\n\nThis filter allows you to modify the array of post types that the WP Loupe plugin works with. By default, it includes 'post' and 'page'.\n\n```php\nadd_filter( 'wp_loupe_post_types', [ 'post', 'page', 'book' ] );\n```\n\n### `wp_loupe_posts_per_page`\n\nThis filter allows you to modify the number of search results per page. By default it's 10, set in `WPAdmin-\u003eSettings-\u003eReading-\u003e\"Blog pages show at most\"`.\n\n```php\nadd_filter( 'wp_loupe_posts_per_page', 20 );\n```\n\n### `wp_loupe_index_protected`\n\nThis filter allows you to index posts and pages that are protected by a password. By default, it's set to `false`.\n\n```php\nadd_filter( 'wp_loupe_index_protected','__return_true' );\n```\n\n### `wp_loupe_field_{$field_name}`\n\nThis filter allows you to change the field content before it is indexed.\n\nBy default, the following is used to remove HTML tags and comments from `post_content`. Among others, it removes the WordPress block comments.\n\n```php\nadd_filter( 'wp_loupe_field_post_content', 'wp_strip_all_tags' );\n```\n\n### `wp_loupe_schema_{$post_type}`\n\nModify the search schema for a specific post type. The filter name is dynamically generated based on the post type.\n\n```php\n// Customize the schema for 'book' post type\nadd_filter( 'wp_loupe_schema_book', function( $schema ) {\n\t$schema['book_isbn'] = [\t\t// Add a new field\n\t\t'weight'     =\u003e 2.0,\t\t// Higher weight means higher relevance in search results\n\t\t'filterable' =\u003e true,\t\t// Allow filtering by this field\n\t\t'sortable'   =\u003e [\t\t\t// Allow sorting by this field\n\t\t\t'direction' =\u003e 'asc'\t// Default sort direction\n\t\t],\n\t];\n\n\t// Modify existing field settings\n\t$schema['post_title']['weight'] = 3.0; // Increase title weight for books\n\n\t// Remove a field\n\tunset( $schema['post_excerpt'] );\n\n\n\t$schema['book_author'] = [\n\t\t'weight'     =\u003e 1.5,\n\t\t'filterable' =\u003e true,\n\t\t'sortable'   =\u003e [ 'direction' =\u003e 'asc' ],\n\t];\n\n\treturn $schema;\n});\n```\n\nThe schema configuration supports the following options for each field:\n\n- `weight` (float): The relevance weight in search results. Default: 1.0\n- `filterable` (bool): Whether the field can be used for filtering. Default: false\n- `sortable` (array): Sorting configuration with `direction` key ('asc' or 'desc'). Default: null\n\nDefault schema fields:\n\n```php\n[\n\t'post_title'   =\u003e [\n\t\t'weight'     =\u003e 2,\n\t\t'filterable' =\u003e true,\n\t\t'sortable'   =\u003e [ 'direction' =\u003e 'asc' ],\n\t],\n\t'post_content' =\u003e [ 'weight' =\u003e 1.0],\n\t'post_excerpt' =\u003e [ 'weight' =\u003e 1.5 ],\n\t'post_date'    =\u003e [\n\t\t'weight'     =\u003e 1.0,\n\t\t'filterable' =\u003e true,\n\t\t'sortable'   =\u003e [ 'direction' =\u003e 'desc' ],\n\t],\n\t'post_author'  =\u003e [\n\t\t'weight'     =\u003e 1.0,\n\t\t'filterable' =\u003e true,\n\t\t'sortable'   =\u003e [ 'direction' =\u003e 'asc' ],\n\t],\n\t'permalink'    =\u003e [ 'weight' =\u003e 1.0 ],\n]\n```\n\n\n## Technical Requirements\n\n- PHP 8.3\n- SQLite 3.35+ (required by Loupe 0.13.x)\n- PHP extensions: `pdo_sqlite`, `intl`, `mbstring`\n- WordPress 6.7+\n\nThis architecture provides a balance between search quality, performance, and ease of integration with WordPress.\n\n\n## Acknowledgements\n\n- WP Loupe is built upon [Loupe](https://github.com/loupe-php/loupe/). Loupe is licensed under the MIT license.\n- The plugin uses [Select2](https://select2.org/) for the post type selection dropdown. Select2 is licensed under the MIT license.\n- The plugin uses Yannick Lefebvre's [WP Plugin Update Checker](https://github.com/YahnisElsts/plugin-update-checker?tab=readme-ov-file#github-integration) for updates. WP Plugin Update Checker is licensed under the MIT license.\n\n## Copyright and License\n\nWP Loupe is copyright © 2024 [Per Søderlind](http://github.com/soderlind).\n\nWP Loupe is open-source software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation.\n\nWP Loupe is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See [LICENSE](LICENSE) for more information.\n\n\u003c!--\nTOC MAINTENANCE\nThe Table of Contents near the top of this file is maintained manually (no automated script in build pipeline).\nUpdate procedure when headings change:\n1. Identify new/renamed/removed headings at levels ## and important ### subsections.\n2. Derive anchors (GitHub algorithm: lowercase, spaces -\u003e dashes, remove most punctuation).\n3. Insert/update list items inside the \u003c!-- TOC BEGIN --\u003e / \u003c!-- TOC END --\u003e block.\n4. Keep indentation with tabs (current style) or convert uniformly if you restyle the list.\n5. Avoid adding very small, single-sentence subsections to keep TOC scannable.\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoderlind%2Fwp-loupe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoderlind%2Fwp-loupe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoderlind%2Fwp-loupe/lists"}