Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 56 additions & 10 deletions skills/instantsearch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description: >-
license: MIT
metadata:
author: algolia
version: '1.0'
version: '1.1'
---

# InstantSearch
Expand All @@ -29,7 +29,10 @@ InstantSearch comes in three libraries. Detect which one applies from the projec

Once identified, use the matching reference directory (e.g., `references/react/`) for all technology rules, anti-patterns, styling, glossary, and pattern-specific guidance.

> **Note:** This skill currently has references for **React InstantSearch** only. If the project uses Vue or vanilla JS, let the user know and ask how they'd like to proceed.
> **Note:** Coverage by library:
>
> - **React InstantSearch**: full coverage (autocomplete, search results page, custom widgets, middleware, SSR).
> - **Vue InstantSearch** and **InstantSearch.js**: library-level rules and autocomplete only. For other patterns, follow the [Source-of-truth check](#2-source-of-truth-check) and ask the user before scaffolding non-trivial flows.

## Workflow

Expand Down Expand Up @@ -59,15 +62,54 @@ If starting fresh, go step by step, waiting for the user's answer before moving

Do not proceed until you have credentials, schema, rendering preferences, and an understanding of the project's design.

### 2. Build
### 2. Source-of-truth check

This skill currently covers **autocomplete**. If the user asks for a different search pattern (e.g., a search results page, faceted search), let them know and ask how they'd like to proceed.
This skill bakes guidance for the highest-value patterns only. Whenever you need a widget, hook, connector, prop, middleware, future flag, or API that is **not explicitly documented in this skill**, you must consult the source of truth before writing code. Training data is stale, lossy, and frequently wrong on prop shapes.

Follow the library's source-of-truth reference for the exact commands and URL patterns:

| Library | Reference |
| ------- | ---------------------------------------------------------- |
| React | [source-of-truth.md](references/react/source-of-truth.md) |
| Vue | [source-of-truth.md](references/vue/source-of-truth.md) |
| JS | [source-of-truth.md](references/js/source-of-truth.md) |

The reference always covers, in order:

1. **Read installed types** in `node_modules` for prop shapes, renderState, and connector contracts.
2. **Fetch the live Algolia docs** at the canonical URL pattern.
3. **Grep installed CSS / source** for class names you intend to style.
4. **Only then write code.** If a step fails (offline, 404, missing types), ask the user before guessing.

Do this even when a pattern reference exists, if you need any prop or behavior the pattern reference does not explicitly cover.

### 3. Build

Pick the matching pattern reference for the library and the user's request. If no pattern reference exists for what the user asked for, fall back on the source-of-truth check (Step 2) and ask the user before scaffolding speculative widget trees.

Patterns available for each library:

| Pattern | React | Vue | JS |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | --- |
| Autocomplete | [features](references/react/autocomplete/features.md), [styling](references/react/autocomplete/styling.md), [anti-patterns](references/react/autocomplete/anti-patterns.md) | — | — |
| Pattern | React | Vue | JS |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Autocomplete | [features](references/react/autocomplete/features.md), [styling](references/react/autocomplete/styling.md), [anti-patterns](references/react/autocomplete/anti-patterns.md) | [features](references/vue/autocomplete/features.md), [styling](references/vue/autocomplete/styling.md), [anti-patterns](references/vue/autocomplete/anti-patterns.md) | [features](references/js/autocomplete/features.md), [styling](references/js/autocomplete/styling.md), [anti-patterns](references/js/autocomplete/anti-patterns.md) |
| Search results page (incl. faceted search, sort, pagination) | [features](references/react/search-results-page/features.md), [styling](references/react/search-results-page/styling.md), [anti-patterns](references/react/search-results-page/anti-patterns.md) | — | — |

Also read and apply the library-level references (apply regardless of pattern):

| Reference | React | Vue | JS |
| ---------------- | ----------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------- |
| Technology rules | [technology-rules.md](references/react/technology-rules.md) | [technology-rules.md](references/vue/technology-rules.md) | [technology-rules.md](references/js/technology-rules.md) |
| Anti-patterns | [anti-patterns.md](references/react/anti-patterns.md) | [anti-patterns.md](references/vue/anti-patterns.md) | [anti-patterns.md](references/js/anti-patterns.md) |
| Styling | [styling.md](references/react/styling.md) | [styling.md](references/vue/styling.md) | [styling.md](references/js/styling.md) |
| Glossary | [glossary.md](references/react/glossary.md) | [glossary.md](references/vue/glossary.md) | [glossary.md](references/js/glossary.md) |
| Source of truth | [source-of-truth.md](references/react/source-of-truth.md) | [source-of-truth.md](references/vue/source-of-truth.md) | [source-of-truth.md](references/js/source-of-truth.md) |
| Custom widgets | [custom-widgets.md](references/react/custom-widgets.md) | — | — |
| Middleware | [middleware.md](references/react/middleware.md) | — | — |
| SSR | [ssr.md](references/react/ssr.md) | — | — |
| Pattern | React | Vue | JS |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --- | --- |
| Autocomplete | [features](references/react/autocomplete/features.md), [styling](references/react/autocomplete/styling.md), [anti-patterns](references/react/autocomplete/anti-patterns.md) | — | — |
| Search results page (incl. faceted search, sort, pagination) | [features](references/react/search-results-page/features.md), [styling](references/react/search-results-page/styling.md), [anti-patterns](references/react/search-results-page/anti-patterns.md) | — | — |

Also read and apply the library-level references (apply regardless of pattern):

Expand All @@ -77,13 +119,17 @@ Also read and apply the library-level references (apply regardless of pattern):
| Anti-patterns | [anti-patterns.md](references/react/anti-patterns.md) | — | — |
| Styling | [styling.md](references/react/styling.md) | — | — |
| Glossary | [glossary.md](references/react/glossary.md) | — | — |
| Source of truth | [source-of-truth.md](references/react/source-of-truth.md) | — | — |
| Custom widgets | [custom-widgets.md](references/react/custom-widgets.md) | — | — |
| Middleware | [middleware.md](references/react/middleware.md) | — | — |
| SSR | [ssr.md](references/react/ssr.md) | — | — |

If you are unsure how to implement a feature with built-in widgets, ask the user. Do not fall back to legacy libraries or custom connectors.
Consult types and live docs first (Step 2). Ask the user only if both fail. Never fall back to legacy libraries or guessed APIs.

### 3. Style
### 4. Style

Follow the library's styling guide step by step, then apply the pattern-specific styling guide. Match the site's existing CSS methodology, color scheme, typography, spacing, and component patterns.

### 4. Review
### 5. Review

Review your work against the library's anti-patterns, the pattern-specific anti-patterns, and the features checklist. Fix any violations.
106 changes: 106 additions & 0 deletions skills/instantsearch/evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,112 @@
"Matches the dark theme",
"Does not guess ais-* class names"
]
},
{
"id": 6,
"prompt": "Add a search results page at /search for my Next.js App Router site. Users should be able to filter by brand and category, sort by price ascending or descending, and paginate. The index has replicas products_price_asc and products_price_desc.",
"expected_output": "A results page using InstantSearchNext with the canonical widget tree, refinements, sort, pagination, routing, insights, and a no-results boundary, with all non-trivial props sourced from installed types",
"files": [],
"expectations": [
"Uses InstantSearchNext from react-instantsearch-nextjs at the layout level, not wrapping a single page",
"Sets routing={true} and insights={true} on the provider",
"Uses Configure to set hitsPerPage, attributesToHighlight, and attributesToSnippet",
"Uses RefinementList for brand and HierarchicalMenu (or RefinementList/Menu, justified) for category",
"Uses SortBy with the provided replica index names (products, products_price_asc, products_price_desc)",
"Uses Pagination, not InfiniteHits, since the user did not ask for infinite scroll",
"Renders a NoResultsBoundary using useInstantSearch().results.nbHits",
"Uses Highlight on hit text attributes; does not render raw strings",
"Reads RefinementList and SortBy props from node_modules/react-instantsearch/dist/es/widgets before writing prop values it has not used before",
"Does NOT add getServerState (App Router handles SSR via InstantSearchNext)",
"Does NOT combine Pagination with InfiniteHits"
]
},
{
"id": 7,
"prompt": "I want a searchable refinement list for brand (so the user can type to filter brands) and active filter chips that show as removable pills at the top of the results.",
"expected_output": "RefinementList with searchable + searchablePlaceholder configured from the type, plus CurrentRefinements wired with widget-aware classNames for the chip layout",
"files": [],
"expectations": [
"Reads RefinementList .d.ts to confirm the searchable, searchablePlaceholder, limit, and showMore props before using them",
"Adds searchable={true} and a searchablePlaceholder on RefinementList",
"Uses CurrentRefinements (not a custom hook) for the active-filter chips",
"Pairs CurrentRefinements with ClearRefinements where appropriate, with excludedAttributes considered when needed",
"Greps installed source for ais-CurrentRefinements-* class names before writing chip CSS",
"Does not rebuild a refinement list with useRefinementList when RefinementList suffices"
]
},
{
"id": 8,
"prompt": "Add SSR to my React InstantSearch results page. I'm using Next.js Pages Router (not App Router).",
"expected_output": "Pages Router SSR using getServerState plus InstantSearchSSRProvider, with the same widget tree on server and client",
"files": [],
"expectations": [
"Uses getServerState from react-instantsearch/server inside getServerSideProps",
"Wraps the widget tree in InstantSearchSSRProvider with serverState",
"Passes renderToString from react-dom/server into getServerState",
"Configures routing with a serverUrl (or framework equivalent) so the server-side router can resolve URL state",
"Declares the searchClient at module scope, not inside getServerSideProps",
"Renders the same widget tree on server and client",
"Does NOT use InstantSearchNext (that's App Router only)",
"Reads getServerState.d.ts and InstantSearchSSRProvider.d.ts from node_modules before wiring props"
]
},
{
"id": 9,
"prompt": "I need a custom widget that renders the available brands as round colored chips with each brand's logo, instead of the default checkbox list. Selecting a chip refines the results.",
"expected_output": "A custom widget built with useRefinementList that renders chips, with renderState fields read from the hook's installed type",
"files": [],
"expectations": [
"Uses useRefinementList from react-instantsearch (not useConnector with a raw connector, since a hook exists)",
"Reads node_modules/react-instantsearch/dist/es/connectors/useRefinementList.d.ts to learn the return type before destructuring",
"Calls refine(item.value) on chip click",
"Renders accessibility attributes (role, aria-pressed) explicitly since the built-in widget's accessibility is lost",
"Considers transformItems on RefinementList as a lighter-weight alternative before going custom",
"Does NOT rebuild refinement state from useHits + useState"
]
},
{
"id": 10,
"prompt": "Set up my React InstantSearch project with the correct future flags so it's ready for the next major release.",
"expected_output": "Future flags applied based on installed types and the live Upgrade guides, not training-data recall",
"files": [],
"expectations": [
"Reads InstantSearchProps['future'] from node_modules/react-instantsearch types to enumerate available flags",
"Fetches https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react to confirm current recommended flags and defaults",
"Applies flags on the InstantSearch (or InstantSearchNext) provider with values matching the installed package version",
"Does NOT enable a flag that does not appear in the installed type",
"Asks the user before enabling any flag whose default cannot be determined from types or docs"
]
},
{
"id": 11,
"prompt": "Add an autocomplete search bar to my Vue 3 app. I'm using vue-instantsearch elsewhere on the site for a results page. The autocomplete should query my products index and clicking a result should navigate to /products/[objectID].",
"expected_output": "Autocomplete built with @algolia/autocomplete-js mounted from a Vue component (onMounted/onBeforeUnmount), reusing the module-level searchClient",
"files": [],
"expectations": [
"Picks @algolia/autocomplete-js as the autocomplete library, NOT a vue-instantsearch widget such as <ais-search-box> or <ais-autocomplete>",
"Does NOT treat @algolia/autocomplete-js as an anti-pattern (it is the recommended path for Vue, unlike React)",
"Mounts autocomplete inside a Vue component via onMounted with a ref to the host element, and calls instance.destroy() in onBeforeUnmount",
"Declares the searchClient at module scope (outside the component), reusing the same one used by vue-instantsearch where applicable",
"Configures getSources with an Algolia source that uses algoliasearch v5's search method shape",
"Wires getItemUrl and a templates.item that links to /products/[objectID]",
"Confirms the autocomplete options shape (getSources, templates) against the live Algolia docs or installed types before scaffolding"
]
},
{
"id": 12,
"prompt": "Add autocomplete search to a vanilla JS site. The page already mounts an InstantSearch.js results page. The autocomplete should sit in the header and link to product detail pages.",
"expected_output": "Autocomplete built with @algolia/autocomplete-js, separate from the instantsearch.js widget tree, sharing the same module-level searchClient",
"files": [],
"expectations": [
"Picks @algolia/autocomplete-js as the autocomplete library, NOT the instantsearch.js searchBox widget for autocomplete behavior",
"Does NOT treat @algolia/autocomplete-js as an anti-pattern (it is the recommended path for vanilla JS, unlike React)",
"Calls autocomplete({ container, getSources, ... }) once and saves the returned instance for later destroy() on teardown",
"Reuses the module-level searchClient already used by instantsearch.js, declared outside any function",
"Uses algoliasearch v5's search method shape inside getSources",
"Imports @algolia/autocomplete-theme-classic (or documents the chosen theme) so the dropdown is styled",
"Confirms the autocomplete options shape against the live Algolia docs or installed types before scaffolding"
]
}
]
}
Loading
Loading