Skill Index

instantsearch/

port-widget

community[skill]

Port or introduce an InstantSearch widget or connector-driven feature across this monorepo's JavaScript, React, and Vue flavors. Use when the task is to add a missing wrapper around an existing connector, bring a widget from one flavor to another, or implement a new shared widget end-to-end in `instantsearch.js`, `react-instantsearch`, and `vue-instantsearch`. Triggers include requests like "port X to vue", "add Y to react-instantsearch", "make Z available in all flavors", or "implement the missing InstantSearch wrapper for this connector".

$/plugin install instantsearch

details

Port InstantSearch Widgets Across Flavors

Start with the repo audit

  • Run python3 scripts/audit_widget_coverage.py <widget-kebab-name> from this skill folder before editing.
  • Use --repo /path/to/instantsearch if your current working directory is not inside the InstantSearch repo.
  • Treat placeholder Vue failures in packages/vue-instantsearch/src/__tests__/common-widgets.test.js or common-connectors.test.js as evidence that the connector exists but the Vue wrapper still needs work.

Layer map

  • Connector: packages/instantsearch.js/src/connectors/<widget>/connect<Pascal>.ts
  • JS widget: packages/instantsearch.js/src/widgets/<widget>/<widget>.tsx
  • React hook: packages/react-instantsearch-core/src/connectors/use<Pascal>.ts
  • React widget: packages/react-instantsearch/src/widgets/<Pascal>.tsx
  • Optional React UI: packages/react-instantsearch/src/ui/<Pascal>.tsx
  • Vue wrapper: packages/vue-instantsearch/src/components/<Pascal>.vue or .js
  • Shared widget tests: tests/common/widgets/<widget>/
  • Shared connector tests: tests/common/connectors/<widget>/

Variant widgets

Some widgets reuse another widget's connector with different defaults or UI. For example, menuSelect uses connectMenu/useMenu (not a dedicated connectMenuSelect). The audit will show no for connector and hook rows — this is expected. The $$widgetType still differs (ais.menuSelect vs ais.menu). When porting a variant widget, skip connector/hook creation and reuse the existing hook directly in the widget file.

Known variants: menuSelectconnectMenu/useMenu.

Workflow

  1. Decide the scope.
    • Existing connector, missing wrapper: keep the connector API unchanged and port only the wrapper plus wrapper tests.
    • Variant widget (shared connector, different UI): skip connector/hook creation; reuse the existing hook and set a distinct $$widgetType.
    • Missing connector or changed render state: start in instantsearch.js, then update every flavor and both common test suites.
    • Vue port for a newer recommendation, chat, or filter-suggestions feature: inspect Hits.js, Highlighter.js, DynamicWidgets.js, and util/vue-compat.js before designing the wrapper.
  2. Match a real precedent.
    • Pick one close widget in the target flavor and one close widget in another flavor.
    • Reuse the same prop names, slot or component escape hatches, $$widgetType, and test style.
  3. Build from the bottom up.
    • Connector exports belong in packages/instantsearch.js/src/connectors/index.ts.
    • JS widget exports belong in packages/instantsearch.js/src/widgets/index.ts.
    • React hook exports belong in packages/react-instantsearch-core/src/index.ts.
    • React widget exports belong in packages/react-instantsearch/src/widgets/index.ts; packages/react-instantsearch/src/index.ts already re-exports widgets.
    • Vue exports belong in packages/vue-instantsearch/src/widgets.js; src/instantsearch.js and the plugin re-export and register from there automatically.
  4. Choose the right sharing model.
    • JS and React: prefer instantsearch-ui-components when the markup can be shared.
    • React: create src/ui/<Pascal>.tsx whenever the widget has no shared factory in instantsearch-ui-components. This includes simple widgets like MenuSelect (a plain <select>) — src/ui/ is for all React-rendered markup, not only complex cases.
    • Vue: use .vue SFCs for slot-heavy markup and .js render functions with renderCompat when reusing instantsearch-ui-components.
  5. Wire tests before finishing.
    • Update tests/common/widgets/<widget>/ whenever the wrapper behavior changes.
    • Update tests/common/connectors/<widget>/ whenever connector params or render state change.
    • Register the suite in each flavor's common-widgets.test.* and common-connectors.test.*.
    • Replace any throw new Error('X is not supported in ...') placeholder with real setup code in the target flavor's common-widgets.test.*.
    • Remove the corresponding skippedTests entry in testOptions for that widget.
    • For React: always add the widget to the switch in packages/react-instantsearch/src/widgets/__tests__/__utils__/all-widgets.tsx with the required minimum props.
  6. Check examples only when the widget is user-facing.
    • Search existing examples first. Recommendation, chat, and query-suggestion widgets already live in getting-started or query-suggestions examples, not only the e-commerce apps.
    • Add to examples/*/e-commerce only when the widget fits the shared storefront UX or existing Playwright coverage.

Reminders

  • Keep $$widgetType aligned across flavors.
  • Do not invent new Vue patterns; match createWidgetMixin, createSuitMixin, scoped slots, and renderCompat.
  • Do not add memoization hooks in React unless an adjacent widget uses them for the same reason.

Cross-package API migration checks

  • Update all affected layers in one pass when moving or splitting behavior: wrapper APIs, shared UI components, layout/type contracts, exports, and tests. Wrapper-only edits create cross-package type drift.
  • If you remove a required prop or render path, either delete it end-to-end or make downstream contracts optional in the same change; partial migrations often fail during declaration builds.
  • Before finishing, grep for legacy names (old props, options, class names, template keys, translations keys) to catch leftovers across flavors.
  • Keep control contracts explicit and consistent when behavior is externally controlled (e.g., imperative handles or widget methods), so external integrations do not depend on internal layout details.
  • Do not add ad-hoc top-level markdown change logs unless requested; keep source of truth in code, tests, and existing docs.
  • Always run monorepo build validation (yarn build --ignore='example*') after cross-package API changes; it catches declaration and export drift that local tests may miss.

References

technical

github
algolia/instantsearch
stars
4047
license
MIT
contributors
100
last commit
2026-05-28T21:49:29Z
file
.claude/skills/port-widget/SKILL.md

related