Skip to content

Commit 8eb583d

Browse files
review(instantsearch): address Sarah's review on PR #22
- source-of-truth.md: append `.md` to canonical Algolia doc URLs so agents fetch markdown (no HTML chrome). Replace the duplicated CSS grep section with a one-liner pointing to styling.md. - technology-rules.md: append `.md` to the Upgrade-guides link. Fold all Next.js / SSR guidance into the v7 import rule (App Router, Pages Router, Remix/SSR, CSR-only). Drop the legacy-libraries rule (overlaps with v6 rule and autocomplete/anti-patterns.md). Drop the middleware rule and the `[custom-widgets.md]` cross-ref (those land with PR 3 alongside the dedicated reference files). - anti-patterns.md: drop the SSR-doubling and middleware-specific entries; they belong with PR 3 alongside ssr.md / middleware.md. - glossary.md: keep the new terms but drop the cross-reference links to middleware.md / ssr.md (added back in PR 3). Net effect: PR 1 is now self-contained — all internal links resolve on this branch alone — and stops restating rules that already live in autocomplete/anti-patterns.md. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent e541904 commit 8eb583d

4 files changed

Lines changed: 25 additions & 39 deletions

File tree

skills/instantsearch/references/react/anti-patterns.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ If you catch yourself doing any of these, stop and reconsider:
1414
| Guessing `ais-*` class names without checking | Names are CamelCase and easy to get wrong. Broken styles with no error | Grep `node_modules/react-instantsearch` for actual class names before writing CSS |
1515
| Rebuilding `<Pagination>`, `<RefinementList>`, `<SortBy>`, `<HierarchicalMenu>` from `useHits` + local state | Reimplements behavior the widget already handles (URL sync, refinements API, accessibility) | Use the widget. Reach for the corresponding hook only when the rendering shape genuinely cannot be styled |
1616
| Guessing prop shapes for refinement widgets (`limit`, `showMore`, `showMoreLimit`, `searchable`, `searchablePlaceholder`, `transformItems`, `operator`, `sortBy`) | Prop names and accepted values change between versions; silent runtime breakage | Read the widget's `.d.ts` from `node_modules/react-instantsearch/dist/es/widgets/` first |
17-
| Writing a custom `useConnector` hook when a built-in widget + `classNames` would do | Adds maintenance burden and re-renders; loses built-in accessibility and routing wiring | Use the widget. Custom widgets are for cases the built-in widget genuinely cannot render. See [custom-widgets.md](custom-widgets.md) |
18-
| Using middleware to sync state to the URL | `routing` already does this; middleware will conflict with it | Configure `routing={true}` (or `routing={{ router, stateMapping }}`). See [middleware.md](middleware.md) |
19-
| Using middleware to set default refinements or query params | These belong in `<Configure>` or refinement widget defaults, not in middleware | Use `<Configure>` for index params; use the widget's default-selection prop where supported |
17+
| Writing a custom `useConnector` hook when a built-in widget + `classNames` would do | Adds maintenance burden and re-renders; loses built-in accessibility and routing wiring | Use the widget. Custom widgets are for cases the built-in widget genuinely cannot render |
2018
| Destructuring `useInstantSearch()` / `useXxx()` return values from training-data recall | `renderState` field names and nesting change across versions | Read the hook's return type before destructuring |
21-
| Adding `getServerState` on top of `<InstantSearchNext>` in App Router | App Router SSR is already handled by `<InstantSearchNext>`; doubling up causes hydration mismatches | Drop `getServerState` for App Router. Use it only for Pages Router / non-Next React with SSR. See [ssr.md](ssr.md) |
2219
| Enabling `future.*` flags from training-data recall | Flags change defaults and semantics; defaults flip across releases | Read `InstantSearchProps['future']` from installed types and the Upgrade guides before enabling |

skills/instantsearch/references/react/glossary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Terms the AI must use correctly. Misusing these leads to wrong code or wrong lib
1414
| **Filter** | A broader term. In Algolia, filters can be set programmatically via `<Configure filters="..." />` or by the user via refinement widgets. | Don't confuse programmatic filters (set by the developer) with refinements (set by the user). |
1515
| **renderState** | The shape returned by a connector / `useXxx` hook (and exposed under `useInstantSearch().renderState`). Field names depend on the connector and version. | Never destructure from training-data recall. Read the hook's `.d.ts` before pulling fields. |
1616
| **InstantSearch instance** | The object returned by `useInstantSearch()` (also accessible as `instance` in middleware). Holds search state, helper, status, results, and `renderState`. | Not a React state object. Mutating it directly is unsupported. Drive it via widgets, hooks, or middleware. |
17-
| **Middleware** | A pluggable hook into the InstantSearch lifecycle (`subscribe`, `started`, `unsubscribe`, `onStateChange`). Used for analytics, custom URL params, side effects. | Not a place to re-implement what `routing` or `<Configure>` already does. See [middleware.md](middleware.md). |
18-
| **getServerState / SSR provider** | `getServerState` (from `react-instantsearch`) walks the tree, performs initial searches, returns serializable state. `<InstantSearchSSRProvider>` re-hydrates it on the client. Used for Next.js Pages Router / Remix / other React SSR. | Not needed for App Router (`<InstantSearchNext>` handles SSR). Don't combine the two. See [ssr.md](ssr.md). |
17+
| **Middleware** | A pluggable hook into the InstantSearch lifecycle (`subscribe`, `started`, `unsubscribe`, `onStateChange`). Used for analytics, custom URL params, side effects. | Not a place to re-implement what `routing` or `<Configure>` already does. |
18+
| **getServerState / SSR provider** | `getServerState` (from `react-instantsearch`) walks the tree, performs initial searches, returns serializable state. `<InstantSearchSSRProvider>` re-hydrates it on the client. Used for Next.js Pages Router / Remix / other React SSR. | Not needed for App Router (`<InstantSearchNext>` handles SSR). Don't combine the two. |
1919
| **Virtual widget** | A widget that registers search parameters with the InstantSearch instance without rendering UI (e.g., a `useSearchBox()` hook called in a parent that doesn't render the search input). | Useful for SSR or for splitting state from rendering. Not the same as `<Configure>`, which is itself effectively a virtual widget. |
2020
| **Dynamic widgets** | A pattern (`<DynamicWidgets>`) that renders refinement widgets based on facets returned by the search response, using `attributesForFaceting` `searchable(...)` markers and `facetOrdering`. | Read the live doc before using; the rendering rules depend on index `renderingContent` settings. |
2121
| **Future flags** | Opt-in switches under `<InstantSearch future={...}>` that toggle upcoming default behaviors (e.g., `preserveSharedStateOnUnmount`). | Defaults flip between releases. Read `InstantSearchProps['future']` and the Upgrade guides before enabling. |

skills/instantsearch/references/react/source-of-truth.md

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,36 +41,25 @@ Read the type definition **before** writing the prop. Do not copy a prop from tr
4141

4242
Live docs cover behavior, defaults, and recently shipped widgets that may not be in your training data. Use the canonical URL patterns:
4343

44-
| Topic | URL pattern |
45-
| ----------------------------- | ------------------------------------------------------------------------------------ |
46-
| Widget reference | `https://www.algolia.com/doc/api-reference/widgets/<widget-slug>/react` |
47-
| Hook / connector reference | `https://www.algolia.com/doc/api-reference/widgets/<widget-slug>/react/#hook` |
48-
| Guides (concepts, patterns) | `https://www.algolia.com/doc/guides/building-search-ui/<topic>/react` |
49-
| Custom widgets | `https://www.algolia.com/doc/guides/building-search-ui/widgets/create-your-own-widgets/react` |
50-
| Routing | `https://www.algolia.com/doc/guides/building-search-ui/going-further/routing-urls/react` |
51-
| SSR | `https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react` |
52-
| Upgrade guides / future flags | `https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react` |
44+
| Topic | URL pattern |
45+
| ----------------------------- | ------------------------------------------------------------------------------------------------ |
46+
| Widget reference | `https://www.algolia.com/doc/api-reference/widgets/<widget-slug>/react.md` |
47+
| Hook / connector reference | `https://www.algolia.com/doc/api-reference/widgets/<widget-slug>/react.md#hook` |
48+
| Guides (concepts, patterns) | `https://www.algolia.com/doc/guides/building-search-ui/<topic>/react.md` |
49+
| Custom widgets | `https://www.algolia.com/doc/guides/building-search-ui/widgets/create-your-own-widgets/react.md` |
50+
| Routing | `https://www.algolia.com/doc/guides/building-search-ui/going-further/routing-urls/react.md` |
51+
| SSR | `https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react.md` |
52+
| Upgrade guides / future flags | `https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react.md` |
53+
54+
Append `.md` to the URL so the agent fetches the markdown source instead of the rendered HTML page (saves tokens, no layout chrome).
5355

5456
The widget slug is the kebab-case form of the widget name: `<RefinementList>` -> `refinement-list`, `<HierarchicalMenu>` -> `hierarchical-menu`, `<CurrentRefinements>` -> `current-refinements`.
5557

5658
If the URL 404s, search `site:algolia.com/doc <widget>` as a fallback. Do not invent URLs.
5759

58-
## 3. Grep installed CSS / source for class names
60+
## 3. Grep installed source for class names
5961

60-
`ais-*` class names are CamelCase and easy to get wrong. Always grep for the actual rendered classes before writing CSS:
61-
62-
```bash
63-
rg -o 'ais-[A-Za-z]+(-[a-z]+)?' node_modules/react-instantsearch | sort -u
64-
rg -o 'ais-[A-Za-z]+(-[a-z]+)?' node_modules/instantsearch.js | sort -u
65-
```
66-
67-
Scope by widget when you only care about one:
68-
69-
```bash
70-
rg -o 'ais-[A-Za-z]+(-[a-z]+)?' node_modules/instantsearch.js/es/widgets/refinement-list | sort -u
71-
```
72-
73-
For Tailwind v4 specifics, see [styling.md](styling.md).
62+
For `ais-*` CSS class names you intend to style, follow [styling.md](styling.md). The same rule applies here: grep installed source, never guess.
7463

7564
## 4. Only then write code
7665

skills/instantsearch/references/react/technology-rules.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ These rules apply to **all** React InstantSearch patterns, not just autocomplete
66

77
- **Before using any widget, hook, connector, prop, middleware, or `future.*` flag not explicitly documented in this skill, complete the [Source-of-truth check](source-of-truth.md).** Read the installed types, fetch the live Algolia docs, grep installed CSS for class names. Do not write code from training-data recall alone.
88
- If `react-instantsearch` and `algoliasearch` are not already installed, install the latest versions and **wait for the install to complete** before proceeding. If using Next.js App Router, also install `react-instantsearch-nextjs`. Use the same package manager as the rest of the project (npm, yarn, pnpm, bun, etc.). If the project uses a CDN (e.g., jsDelivr with script tags), follow that pattern instead. Do not read types or import from packages until the install has finished. Do not fetch types from the web (unpkg, GitHub, etc.).
9-
- Use `react-instantsearch` v7. Import from `react-instantsearch`, never from `react-instantsearch-dom`. **If using Next.js App Router**, use `InstantSearchNext` from `react-instantsearch-nextjs` instead of `<InstantSearch>`. The props are the same.
9+
- Use `react-instantsearch` v7. Import from `react-instantsearch`, never from `react-instantsearch-dom`. **For Next.js, pick the provider by router**:
10+
- **App Router**: use `<InstantSearchNext>` from `react-instantsearch-nextjs` instead of `<InstantSearch>`. It already handles SSR — do not add `getServerState` on top.
11+
- **Pages Router**: use `<InstantSearch>` together with `getServerState` and `<InstantSearchSSRProvider>` from `react-instantsearch`. Do not use `react-instantsearch-router-nextjs`.
12+
- **Remix or other React frameworks with SSR**: same as Pages Router (`getServerState` + `<InstantSearchSSRProvider>`).
13+
- **CSR-only React (Vite, CRA-style)**: plain `<InstantSearch>`. Do not add SSR helpers.
14+
15+
The props of `<InstantSearch>` and `<InstantSearchNext>` match.
1016
- **Place the `<InstantSearch>` (or `<InstantSearchNext>`) provider high in the component tree**. At the layout level, not wrapping a single widget. Other widgets (search results, facets, etc.) will need to be nested inside it later. Decouple the provider from any specific widget.
1117
- Use `algoliasearch` v5 (the latest) to create the search client. Do not use older v4/v3 patterns. If already installed, check `package.json` for the version. The API changed between v4 and v5. If not installed, install the latest version. For web applications, prefer the lite client for a smaller bundle: `import { liteClient as algoliasearch } from "algoliasearch/lite";`
1218
- **Declare the search client outside of React components.** The client's reference must remain stable to preserve its internal cache. Do not inline `algoliasearch(...)` inside the `searchClient` prop, and do not create it inside a component with `useCallback` or `useMemo` unless there is no alternative.
@@ -16,18 +22,12 @@ These rules apply to **all** React InstantSearch patterns, not just autocomplete
1622
- **Follow the [styling guide](styling.md) for all widget styling.** Write CSS targeting `ais-*` selectors. Grep for actual class names before writing CSS.
1723
- Set `insights={true}` on the `<InstantSearch>` wrapper to enable click analytics via Algolia Insights.
1824
- **Set up routing** so the search state is reflected in the URL. Search result URLs must be shareable and bookmarkable. Enable routing by passing `routing` or `routing={true}` on the `<InstantSearch>` (or `<InstantSearchNext>`) wrapper. For further customization, pass an object to `routing` where `router` accepts the same options as `history`, and `stateMapping` accepts the same options as in `InstantSearch`. Read the type definitions for full configuration options.
19-
- **`future.*` flags must be looked up, not guessed.** Flags like `preserveSharedStateOnUnmount` change semantics across versions. Read `InstantSearchProps['future']` from the installed types and the [Upgrade guides](https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react) before enabling, disabling, or assuming a default.
20-
- **For SSR, pick the right tool for the framework**:
21-
- **Next.js App Router**: `<InstantSearchNext>` from `react-instantsearch-nextjs` already handles SSR. Do not add `getServerState` on top.
22-
- **Next.js Pages Router, Remix, or other React with SSR**: use `getServerState` + `<InstantSearchSSRProvider>` per [ssr.md](ssr.md).
23-
- **CSR-only React (Vite, CRA-style)**: SSR is not applicable. Do not add SSR helpers.
24-
- **Use middleware only for what `routing`, `Configure`, and built-in widgets cannot do.** Custom analytics tagging, syncing search state to a non-URL store, or instrumenting refinements are legitimate. Re-implementing URL sync, query persistence, or facet defaults is not. See [middleware.md](middleware.md).
25+
- **`future.*` flags must be looked up, not guessed.** Flags like `preserveSharedStateOnUnmount` change semantics across versions. Read `InstantSearchProps['future']` from the installed types and the [Upgrade guides](https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react.md) before enabling, disabling, or assuming a default.
2526

2627
## Never
2728

2829
- **Never use v6 APIs.** Do not import from `react-instantsearch-dom`, do not use class-based connectors, do not use `connectSearchBox` or similar v6 patterns.
2930
- **Never guess credentials or index names.** Always ask the user. Never silently use a public demo index.
3031
- **Never start coding before completing discovery.** You need credentials, schema understanding, rendering preferences, and project design context first.
31-
- **Never overuse connectors.** If you're reaching for `useSearchBox`, `useHits`, `useRefinementList` etc., first check whether the built-in widget with a `classNames` prop achieves the same result. Custom hooks/connectors are for genuinely custom rendering that widgets cannot handle. See [custom-widgets.md](custom-widgets.md) for the contract and when it's justified.
32+
- **Never overuse connectors.** If you're reaching for `useSearchBox`, `useHits`, `useRefinementList` etc., first check whether the built-in widget with a `classNames` prop achieves the same result. Custom hooks/connectors are for genuinely custom rendering that widgets cannot handle.
3233
- **Never guess `renderState` shape.** When using `useInstantSearch()` or any `useXxx` hook, read the hook's return type from `node_modules` before destructuring. Field names and nesting change across versions.
33-
- **Never fall back to legacy libraries when something feels missing.** No `@algolia/autocomplete-js`, no `react-instantsearch-dom`, no `react-instantsearch-router-nextjs` on App Router. If the source-of-truth check still leaves a gap, ask the user.

0 commit comments

Comments
 (0)