feat: add feeds widgets for JS, React, and Vue#6969
Merged
drodriguln merged 31 commits intofeat/composition-multifeedfrom Apr 30, 2026
Merged
feat: add feeds widgets for JS, React, and Vue#6969drodriguln merged 31 commits intofeat/composition-multifeedfrom
drodriguln merged 31 commits intofeat/composition-multifeedfrom
Conversation
Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Haroen Viaene <hello@haroen.me>
Move storeRenderState from module-private in index.ts to render-args.ts so FeedContainer can reuse it in the feeds connector (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dContainer Introduce indexWidgetTypes const and IndexWidgetType as single source of truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription, BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and 'ais.feedContainer' to builtin type unions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The metadata middleware hardcoded 'ais.index' instead of using isIndexWidget, so widgets inside feed containers were invisible to the Algolia Crawler metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Made-with: Cursor
…tions Made-with: Cursor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ized flag Replace `instantSearchInstance.started` check with a local `initialized` flag so that child widgets added before `container.init()` are not eagerly initialized. This prevents double-init when the parent index tree calls `init()` on the container after widgets have already been added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…omputation
Remove FeedContainer lifecycle management from the connector — widget layers
now own container creation, registration, and cleanup. The connector only
computes feedIDs from results.feeds and exposes them as render state.
- Remove `widgets` param and internal `feedContainers` map
- Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]`
- Make `getWidgetRenderState` stateless (derives feedIDs from results)
- Simplify `dispose()` to only call `unmountFn()`
- Extract shared test helpers to `test/createFeedsTestHelpers.ts`
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 276 |
| Duplication | 67 |
TIP This summary will be updated as you push new changes.
- Use `import type` for type-only imports - Fix import ordering in test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0bdc7d6 to
29a3827
Compare
More templates
algoliasearch-helper
instantsearch-ui-components
instantsearch.css
instantsearch.js
react-instantsearch
react-instantsearch-core
react-instantsearch-nextjs
react-instantsearch-router-nextjs
vue-instantsearch
commit: |
1fd7ba0 to
eff4746
Compare
This was referenced Apr 15, 2026
FabienMotte
reviewed
Apr 28, 2026
6f2bae7 to
5d0261b
Compare
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add `feeds()` widget that creates per-feed DOM containers and manages FeedContainer lifecycle. Each feed gets a scoped `<div class="ais-Feeds-feed">` and its own FeedContainer registered with the parent index. - DOM creation, reuse, reorder, and cleanup per feed - Deferred removal with coalesced timer (matches connectDynamicWidgets pattern) - Dispose merges active + pending containers for clean teardown - Exported from both main and UMD entrypoints - 11 unit tests + 1 integration test with real search lifecycle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `<Feeds>` component that creates per-feed `IndexContext.Provider` scopes, and `useFeeds` hook wrapping `connectFeeds` via `useConnector`. - FeedContainer creation + registration fused in render body for SSR compat - Deferred removal with coalesced timer (single ref pattern from useWidget) - Unmount cleanup merges active + pending containers - 5 unit tests + 2 integration tests (real InstantSearch + SSR) - Exported from react-instantsearch-core Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `<ais-feeds>` component with per-feed `AisFeedProvider` scoping via Vue's provide/inject for `$_ais_getParentIndex`. - Container reconciliation in watcher (side-effect-free render) - Deferred removal with coalesced timer (single timer pattern) - Unmount cleanup merges active + pending containers - 5 unit tests + 1 integration test with real InstantSearch - Exported as AisFeeds from vue-instantsearch - Updated mock and index tests for compositionID support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…type safety FeedContainer.render() ignores the argument internally but IndexWidget type requires it. Pass renderOptionsRef to satisfy TypeScript. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@algolia/composition doesn't exist under algoliasearch v4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… to renderFeed
Switch from a children render function to a dedicated `renderFeed` prop with
an object argument `({ feedID })`. Keeps the API consistent with other React
InstantSearch components (`hitComponent`, `itemComponent`, `bannerComponent`),
which all use explicit, non-children customization props.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…veWidgets findIndex expects a predicate function, not the widget object — the call threw at runtime the first time removeWidgets was invoked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42ea90c to
a4af193
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 70 out of 81 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
98bd1e8 to
d874101
Compare
d874101 to
c6a2105
Compare
FabienMotte
approved these changes
Apr 29, 2026
Base automatically changed from
feat/composition-multifeed-layer2-connector
to
feat/composition-multifeed
April 30, 2026 15:42
…feed-layer3-widgets
drodriguln
added a commit
that referenced
this pull request
Apr 30, 2026
* feat(helper): support multifeed composition responses
Compositions can return multiple result sets (feeds), each identified by
a `feedID`. Previously, `_runComposition` spliced only 1 result per
derived helper, discarding additional feeds. This changes `queriesCount`
to `Infinity` so all feeds are captured, and builds a `_feedResults` map
and `_feedOrder` array on the primary `SearchResults` for downstream
consumption by `connectFeeds` (Layer 2).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: bump bundlesize limits for multifeed helper changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(helper): omit queriesCount for composition instead of using Infinity
Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse,
avoiding the Infinity hack. When queriesCount is undefined (composition path), use
results directly; when defined (regular search path), splice as before.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(helper): remove composition type definitions, defer to layer 2
The feedID, _feedResults, and _feedOrder type definitions have no consumers
yet. Defer the typing decision (interface vs class, naming) to Layer 2 when
connectFeeds introduces the first consumer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(helper): use lastResults.feeds array instead of _feedResults map
Replace _feedResults (Record<string, SearchResults>) and _feedOrder
(string[]) with a single lastResults.feeds (CompositionSearchResults[])
ordered array. This simplifies the API and ensures feeds survive the
SSR getInitialResults → JSON → hydration round-trip naturally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(helper): avoid circular ref in multifeed lastResults
Create a separate SearchResults instance for lastResults instead of
reusing feeds[0], which caused circular references during
JSON.stringify (lastResults.feeds[0] === lastResults).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* apply suggestions from code review
Co-authored-by: Haroen Viaene <hello@haroen.me>
* refactor(instantsearch): extract storeRenderState to shared util
Move storeRenderState from module-private in index.ts to render-args.ts
so FeedContainer can reuse it in the feeds connector (Layer 2).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(instantsearch): centralize index widget types, widen for feedContainer
Introduce indexWidgetTypes const and IndexWidgetType as single source of
truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription,
BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and
'ais.feedContainer' to builtin type unions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(metadata): use isIndexWidget to recurse into feed containers
The metadata middleware hardcoded 'ais.index' instead of using
isIndexWidget, so widgets inside feed containers were invisible
to the Algolia Crawler metadata.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(instantsearch): add FeedContainer for per-feed widget subtrees
Made-with: Cursor
* feat(instantsearch): add connectFeeds connector for multifeed compositions
Made-with: Cursor
* test(instantsearch): add unit tests for FeedContainer and connectFeeds
Made-with: Cursor
* chore: bump bundlesize limits for multifeed connector
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(instantsearch): prevent double-init in FeedContainer with initialized flag
Replace `instantSearchInstance.started` check with a local `initialized` flag
so that child widgets added before `container.init()` are not eagerly
initialized. This prevents double-init when the parent index tree calls
`init()` on the container after widgets have already been added.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(instantsearch): simplify connectFeeds to stateless feedIDs computation
Remove FeedContainer lifecycle management from the connector — widget layers
now own container creation, registration, and cleanup. The connector only
computes feedIDs from results.feeds and exposes them as render state.
- Remove `widgets` param and internal `feedContainers` map
- Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]`
- Make `getWidgetRenderState` stateless (derives feedIDs from results)
- Simplify `dispose()` to only call `unmountFn()`
- Extract shared test helpers to `test/createFeedsTestHelpers.ts`
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(instantsearch): fix lint errors in feeds test helpers
- Use `import type` for type-only imports
- Fix import ordering in test files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* review: use setState
* feedback: chain state when removing widgets (same as in dispose below)
* feedback: register FeedsWidgetDescription in IndexRenderState
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(instantsearch): add feeds widget for vanilla JS
Add `feeds()` widget that creates per-feed DOM containers and manages
FeedContainer lifecycle. Each feed gets a scoped `<div class="ais-Feeds-feed">`
and its own FeedContainer registered with the parent index.
- DOM creation, reuse, reorder, and cleanup per feed
- Deferred removal with coalesced timer (matches connectDynamicWidgets pattern)
- Dispose merges active + pending containers for clean teardown
- Exported from both main and UMD entrypoints
- 11 unit tests + 1 integration test with real search lifecycle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(react-instantsearch): add Feeds component and useFeeds hook
Add `<Feeds>` component that creates per-feed `IndexContext.Provider` scopes,
and `useFeeds` hook wrapping `connectFeeds` via `useConnector`.
- FeedContainer creation + registration fused in render body for SSR compat
- Deferred removal with coalesced timer (single ref pattern from useWidget)
- Unmount cleanup merges active + pending containers
- 5 unit tests + 2 integration tests (real InstantSearch + SSR)
- Exported from react-instantsearch-core
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(vue-instantsearch): add AisFeeds component
Add `<ais-feeds>` component with per-feed `AisFeedProvider` scoping via
Vue's provide/inject for `$_ais_getParentIndex`.
- Container reconciliation in watcher (side-effect-free render)
- Deferred removal with coalesced timer (single timer pattern)
- Unmount cleanup merges active + pending containers
- 5 unit tests + 1 integration test with real InstantSearch
- Exported as AisFeeds from vue-instantsearch
- Updated mock and index tests for compositionID support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fix import ordering lint errors across Layer 3 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(instantsearch): pass renderOptions to feedContainer.render() for type safety
FeedContainer.render() ignores the argument internally but IndexWidget type
requires it. Pass renderOptionsRef to satisfy TypeScript.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* temp: add examples
* fix: exclude composition examples from v4 type-check
@algolia/composition doesn't exist under algoliasearch v4.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(react-instantsearch-core): rename Feeds children render-prop to renderFeed
Switch from a children render function to a dedicated `renderFeed` prop with
an object argument `({ feedID })`. Keeps the API consistent with other React
InstantSearch components (`hitComponent`, `itemComponent`, `bannerComponent`),
which all use explicit, non-children customization props.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(vue-instantsearch): use indexOf instead of findIndex in mock removeWidgets
findIndex expects a predicate function, not the widget object — the call
threw at runtime the first time removeWidgets was invoked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: copilot feedback
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Haroen Viaene <hello@haroen.me>
Co-authored-by: Dan Rodriguez <daniel.rodriguez@algolia.com>
Co-authored-by: Dan Rodriguez <drodriguln@icloud.com>
Haroenv
added a commit
that referenced
this pull request
May 4, 2026
* feat(helper): support multifeed composition responses (#6954) * feat(helper): support multifeed composition responses Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limits for multifeed helper changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): omit queriesCount for composition instead of using Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): remove composition type definitions, defer to layer 2 The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): use lastResults.feeds array instead of _feedResults map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(helper): avoid circular ref in multifeed lastResults Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * apply suggestions from code review Co-authored-by: Haroen Viaene <hello@haroen.me> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me> * feat(instantsearch): add connectFeeds connector for multifeed compositions (#6964) * feat(helper): support multifeed composition responses Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limits for multifeed helper changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): omit queriesCount for composition instead of using Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): remove composition type definitions, defer to layer 2 The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): use lastResults.feeds array instead of _feedResults map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(helper): avoid circular ref in multifeed lastResults Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * apply suggestions from code review Co-authored-by: Haroen Viaene <hello@haroen.me> * refactor(instantsearch): extract storeRenderState to shared util Move storeRenderState from module-private in index.ts to render-args.ts so FeedContainer can reuse it in the feeds connector (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): centralize index widget types, widen for feedContainer Introduce indexWidgetTypes const and IndexWidgetType as single source of truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription, BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and 'ais.feedContainer' to builtin type unions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(metadata): use isIndexWidget to recurse into feed containers The metadata middleware hardcoded 'ais.index' instead of using isIndexWidget, so widgets inside feed containers were invisible to the Algolia Crawler metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add FeedContainer for per-feed widget subtrees Made-with: Cursor * feat(instantsearch): add connectFeeds connector for multifeed compositions Made-with: Cursor * test(instantsearch): add unit tests for FeedContainer and connectFeeds Made-with: Cursor * chore: bump bundlesize limits for multifeed connector Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): prevent double-init in FeedContainer with initialized flag Replace `instantSearchInstance.started` check with a local `initialized` flag so that child widgets added before `container.init()` are not eagerly initialized. This prevents double-init when the parent index tree calls `init()` on the container after widgets have already been added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): simplify connectFeeds to stateless feedIDs computation Remove FeedContainer lifecycle management from the connector — widget layers now own container creation, registration, and cleanup. The connector only computes feedIDs from results.feeds and exposes them as render state. - Remove `widgets` param and internal `feedContainers` map - Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]` - Make `getWidgetRenderState` stateless (derives feedIDs from results) - Simplify `dispose()` to only call `unmountFn()` - Extract shared test helpers to `test/createFeedsTestHelpers.ts` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): fix lint errors in feeds test helpers - Use `import type` for type-only imports - Fix import ordering in test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * review: use setState * feedback: chain state when removing widgets (same as in dispose below) * feedback: register FeedsWidgetDescription in IndexRenderState Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me> Co-authored-by: Dan Rodriguez <drodriguln@icloud.com> * feat: add feeds widgets for JS, React, and Vue (#6969) * feat(helper): support multifeed composition responses Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limits for multifeed helper changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): omit queriesCount for composition instead of using Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): remove composition type definitions, defer to layer 2 The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): use lastResults.feeds array instead of _feedResults map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(helper): avoid circular ref in multifeed lastResults Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * apply suggestions from code review Co-authored-by: Haroen Viaene <hello@haroen.me> * refactor(instantsearch): extract storeRenderState to shared util Move storeRenderState from module-private in index.ts to render-args.ts so FeedContainer can reuse it in the feeds connector (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): centralize index widget types, widen for feedContainer Introduce indexWidgetTypes const and IndexWidgetType as single source of truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription, BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and 'ais.feedContainer' to builtin type unions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(metadata): use isIndexWidget to recurse into feed containers The metadata middleware hardcoded 'ais.index' instead of using isIndexWidget, so widgets inside feed containers were invisible to the Algolia Crawler metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add FeedContainer for per-feed widget subtrees Made-with: Cursor * feat(instantsearch): add connectFeeds connector for multifeed compositions Made-with: Cursor * test(instantsearch): add unit tests for FeedContainer and connectFeeds Made-with: Cursor * chore: bump bundlesize limits for multifeed connector Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): prevent double-init in FeedContainer with initialized flag Replace `instantSearchInstance.started` check with a local `initialized` flag so that child widgets added before `container.init()` are not eagerly initialized. This prevents double-init when the parent index tree calls `init()` on the container after widgets have already been added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): simplify connectFeeds to stateless feedIDs computation Remove FeedContainer lifecycle management from the connector — widget layers now own container creation, registration, and cleanup. The connector only computes feedIDs from results.feeds and exposes them as render state. - Remove `widgets` param and internal `feedContainers` map - Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]` - Make `getWidgetRenderState` stateless (derives feedIDs from results) - Simplify `dispose()` to only call `unmountFn()` - Extract shared test helpers to `test/createFeedsTestHelpers.ts` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): fix lint errors in feeds test helpers - Use `import type` for type-only imports - Fix import ordering in test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * review: use setState * feedback: chain state when removing widgets (same as in dispose below) * feedback: register FeedsWidgetDescription in IndexRenderState Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(instantsearch): add feeds widget for vanilla JS Add `feeds()` widget that creates per-feed DOM containers and manages FeedContainer lifecycle. Each feed gets a scoped `<div class="ais-Feeds-feed">` and its own FeedContainer registered with the parent index. - DOM creation, reuse, reorder, and cleanup per feed - Deferred removal with coalesced timer (matches connectDynamicWidgets pattern) - Dispose merges active + pending containers for clean teardown - Exported from both main and UMD entrypoints - 11 unit tests + 1 integration test with real search lifecycle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(react-instantsearch): add Feeds component and useFeeds hook Add `<Feeds>` component that creates per-feed `IndexContext.Provider` scopes, and `useFeeds` hook wrapping `connectFeeds` via `useConnector`. - FeedContainer creation + registration fused in render body for SSR compat - Deferred removal with coalesced timer (single ref pattern from useWidget) - Unmount cleanup merges active + pending containers - 5 unit tests + 2 integration tests (real InstantSearch + SSR) - Exported from react-instantsearch-core Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(vue-instantsearch): add AisFeeds component Add `<ais-feeds>` component with per-feed `AisFeedProvider` scoping via Vue's provide/inject for `$_ais_getParentIndex`. - Container reconciliation in watcher (side-effect-free render) - Deferred removal with coalesced timer (single timer pattern) - Unmount cleanup merges active + pending containers - 5 unit tests + 1 integration test with real InstantSearch - Exported as AisFeeds from vue-instantsearch - Updated mock and index tests for compositionID support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix import ordering lint errors across Layer 3 files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): pass renderOptions to feedContainer.render() for type safety FeedContainer.render() ignores the argument internally but IndexWidget type requires it. Pass renderOptionsRef to satisfy TypeScript. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * temp: add examples * fix: exclude composition examples from v4 type-check @algolia/composition doesn't exist under algoliasearch v4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(react-instantsearch-core): rename Feeds children render-prop to renderFeed Switch from a children render function to a dedicated `renderFeed` prop with an object argument `({ feedID })`. Keeps the API consistent with other React InstantSearch components (`hitComponent`, `itemComponent`, `bannerComponent`), which all use explicit, non-children customization props. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(vue-instantsearch): use indexOf instead of findIndex in mock removeWidgets findIndex expects a predicate function, not the widget object — the call threw at runtime the first time removeWidgets was invoked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: copilot feedback --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me> Co-authored-by: Dan Rodriguez <daniel.rodriguez@algolia.com> Co-authored-by: Dan Rodriguez <drodriguln@icloud.com> * feat(instantsearch): SSR support for composition multifeed (#6975) * feat(helper): support multifeed composition responses Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limits for multifeed helper changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): omit queriesCount for composition instead of using Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): remove composition type definitions, defer to layer 2 The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): use lastResults.feeds array instead of _feedResults map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(helper): avoid circular ref in multifeed lastResults Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * apply suggestions from code review Co-authored-by: Haroen Viaene <hello@haroen.me> * refactor(instantsearch): extract storeRenderState to shared util Move storeRenderState from module-private in index.ts to render-args.ts so FeedContainer can reuse it in the feeds connector (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): centralize index widget types, widen for feedContainer Introduce indexWidgetTypes const and IndexWidgetType as single source of truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription, BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and 'ais.feedContainer' to builtin type unions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(metadata): use isIndexWidget to recurse into feed containers The metadata middleware hardcoded 'ais.index' instead of using isIndexWidget, so widgets inside feed containers were invisible to the Algolia Crawler metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add FeedContainer for per-feed widget subtrees Made-with: Cursor * feat(instantsearch): add connectFeeds connector for multifeed compositions Made-with: Cursor * test(instantsearch): add unit tests for FeedContainer and connectFeeds Made-with: Cursor * chore: bump bundlesize limits for multifeed connector Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): prevent double-init in FeedContainer with initialized flag Replace `instantSearchInstance.started` check with a local `initialized` flag so that child widgets added before `container.init()` are not eagerly initialized. This prevents double-init when the parent index tree calls `init()` on the container after widgets have already been added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): simplify connectFeeds to stateless feedIDs computation Remove FeedContainer lifecycle management from the connector — widget layers now own container creation, registration, and cleanup. The connector only computes feedIDs from results.feeds and exposes them as render state. - Remove `widgets` param and internal `feedContainers` map - Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]` - Make `getWidgetRenderState` stateless (derives feedIDs from results) - Simplify `dispose()` to only call `unmountFn()` - Extract shared test helpers to `test/createFeedsTestHelpers.ts` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): fix lint errors in feeds test helpers - Use `import type` for type-only imports - Fix import ordering in test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * review: use setState * feedback: chain state when removing widgets (same as in dispose below) * feedback: register FeedsWidgetDescription in IndexRenderState Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(instantsearch): add feeds widget for vanilla JS Add `feeds()` widget that creates per-feed DOM containers and manages FeedContainer lifecycle. Each feed gets a scoped `<div class="ais-Feeds-feed">` and its own FeedContainer registered with the parent index. - DOM creation, reuse, reorder, and cleanup per feed - Deferred removal with coalesced timer (matches connectDynamicWidgets pattern) - Dispose merges active + pending containers for clean teardown - Exported from both main and UMD entrypoints - 11 unit tests + 1 integration test with real search lifecycle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(react-instantsearch): add Feeds component and useFeeds hook Add `<Feeds>` component that creates per-feed `IndexContext.Provider` scopes, and `useFeeds` hook wrapping `connectFeeds` via `useConnector`. - FeedContainer creation + registration fused in render body for SSR compat - Deferred removal with coalesced timer (single ref pattern from useWidget) - Unmount cleanup merges active + pending containers - 5 unit tests + 2 integration tests (real InstantSearch + SSR) - Exported from react-instantsearch-core Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(vue-instantsearch): add AisFeeds component Add `<ais-feeds>` component with per-feed `AisFeedProvider` scoping via Vue's provide/inject for `$_ais_getParentIndex`. - Container reconciliation in watcher (side-effect-free render) - Deferred removal with coalesced timer (single timer pattern) - Unmount cleanup merges active + pending containers - 5 unit tests + 1 integration test with real InstantSearch - Exported as AisFeeds from vue-instantsearch - Updated mock and index tests for compositionID support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix import ordering lint errors across Layer 3 files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): pass renderOptions to feedContainer.render() for type safety FeedContainer.render() ignores the argument internally but IndexWidget type requires it. Pass renderOptionsRef to satisfy TypeScript. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * temp: add examples * fix: exclude composition examples from v4 type-check @algolia/composition doesn't exist under algoliasearch v4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(react-instantsearch-core): rename Feeds children render-prop to renderFeed Switch from a children render function to a dedicated `renderFeed` prop with an object argument `({ feedID })`. Keeps the API consistent with other React InstantSearch components (`hitComponent`, `itemComponent`, `bannerComponent`), which all use explicit, non-children customization props. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(vue-instantsearch): use indexOf instead of findIndex in mock removeWidgets findIndex expects a predicate function, not the widget object — the call threw at runtime the first time removeWidgets was invoked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(instantsearch): extract isTwoPassWidget utility Replace inline `$$type === 'ais.dynamicWidgets'` checks with a shared `isTwoPassWidget` predicate. This prepares for the feeds widget which also requires a two-pass SSR cycle, and fixes a missing `shouldRefetch ||` in InitializePromise. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add SSR support for composition multifeed Serialize per-feed results as `compositionFeedsResults` in `getInitialResults`, hydrate them in `hydrateSearchClient`, and reconstruct `lastResults.feeds` in the feeds connector so that composition multifeed works with server-side rendering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(instantsearch): add composition multifeed SSR integration test End-to-end integration test covering the full SSR cycle: server-side rendering with getInitialResults, hydration via hydrateSearchClient, and client-side rehydration of per-feed results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add Next.js App Router composition example Demo app showing composition multifeed with SSR using react-instantsearch-nextjs. Excluded from v4 type-check since it uses composition-only APIs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(react-instantsearch-core): adapt Feeds usages to renderFeed prop Update the SSR test and the Next.js App Router composition example to the new `renderFeed` prop introduced on Layer 3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limit for SSR multifeed The composition multifeed SSR additions push the development bundle just over the 256.5 kB ceiling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me> Co-authored-by: Dan Rodriguez <drodriguln@icloud.com> * chore: remove internal composition examples (#6977) * feat(helper): support multifeed composition responses Compositions can return multiple result sets (feeds), each identified by a `feedID`. Previously, `_runComposition` spliced only 1 result per derived helper, discarding additional feeds. This changes `queriesCount` to `Infinity` so all feeds are captured, and builds a `_feedResults` map and `_feedOrder` array on the primary `SearchResults` for downstream consumption by `connectFeeds` (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limits for multifeed helper changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): omit queriesCount for composition instead of using Infinity Use undefined queriesCount to signal "take all results" in _dispatchAlgoliaResponse, avoiding the Infinity hack. When queriesCount is undefined (composition path), use results directly; when defined (regular search path), splice as before. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): remove composition type definitions, defer to layer 2 The feedID, _feedResults, and _feedOrder type definitions have no consumers yet. Defer the typing decision (interface vs class, naming) to Layer 2 when connectFeeds introduces the first consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(helper): use lastResults.feeds array instead of _feedResults map Replace _feedResults (Record<string, SearchResults>) and _feedOrder (string[]) with a single lastResults.feeds (CompositionSearchResults[]) ordered array. This simplifies the API and ensures feeds survive the SSR getInitialResults → JSON → hydration round-trip naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(helper): avoid circular ref in multifeed lastResults Create a separate SearchResults instance for lastResults instead of reusing feeds[0], which caused circular references during JSON.stringify (lastResults.feeds[0] === lastResults). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * apply suggestions from code review Co-authored-by: Haroen Viaene <hello@haroen.me> * refactor(instantsearch): extract storeRenderState to shared util Move storeRenderState from module-private in index.ts to render-args.ts so FeedContainer can reuse it in the feeds connector (Layer 2). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): centralize index widget types, widen for feedContainer Introduce indexWidgetTypes const and IndexWidgetType as single source of truth for index-like widget types. Update isIndexWidget, IndexWidgetDescription, BuiltinTypes, and BuiltinWidgetTypes to use them. Add 'ais.feeds' and 'ais.feedContainer' to builtin type unions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(metadata): use isIndexWidget to recurse into feed containers The metadata middleware hardcoded 'ais.index' instead of using isIndexWidget, so widgets inside feed containers were invisible to the Algolia Crawler metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add FeedContainer for per-feed widget subtrees Made-with: Cursor * feat(instantsearch): add connectFeeds connector for multifeed compositions Made-with: Cursor * test(instantsearch): add unit tests for FeedContainer and connectFeeds Made-with: Cursor * chore: bump bundlesize limits for multifeed connector Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): prevent double-init in FeedContainer with initialized flag Replace `instantSearchInstance.started` check with a local `initialized` flag so that child widgets added before `container.init()` are not eagerly initialized. This prevents double-init when the parent index tree calls `init()` on the container after widgets have already been added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(instantsearch): simplify connectFeeds to stateless feedIDs computation Remove FeedContainer lifecycle management from the connector — widget layers now own container creation, registration, and cleanup. The connector only computes feedIDs from results.feeds and exposes them as render state. - Remove `widgets` param and internal `feedContainers` map - Change render state from `feeds: [{ feedID, container }]` to `feedIDs: string[]` - Make `getWidgetRenderState` stateless (derives feedIDs from results) - Simplify `dispose()` to only call `unmountFn()` - Extract shared test helpers to `test/createFeedsTestHelpers.ts` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): fix lint errors in feeds test helpers - Use `import type` for type-only imports - Fix import ordering in test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * review: use setState * feedback: chain state when removing widgets (same as in dispose below) * feedback: register FeedsWidgetDescription in IndexRenderState Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(instantsearch): add feeds widget for vanilla JS Add `feeds()` widget that creates per-feed DOM containers and manages FeedContainer lifecycle. Each feed gets a scoped `<div class="ais-Feeds-feed">` and its own FeedContainer registered with the parent index. - DOM creation, reuse, reorder, and cleanup per feed - Deferred removal with coalesced timer (matches connectDynamicWidgets pattern) - Dispose merges active + pending containers for clean teardown - Exported from both main and UMD entrypoints - 11 unit tests + 1 integration test with real search lifecycle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(react-instantsearch): add Feeds component and useFeeds hook Add `<Feeds>` component that creates per-feed `IndexContext.Provider` scopes, and `useFeeds` hook wrapping `connectFeeds` via `useConnector`. - FeedContainer creation + registration fused in render body for SSR compat - Deferred removal with coalesced timer (single ref pattern from useWidget) - Unmount cleanup merges active + pending containers - 5 unit tests + 2 integration tests (real InstantSearch + SSR) - Exported from react-instantsearch-core Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(vue-instantsearch): add AisFeeds component Add `<ais-feeds>` component with per-feed `AisFeedProvider` scoping via Vue's provide/inject for `$_ais_getParentIndex`. - Container reconciliation in watcher (side-effect-free render) - Deferred removal with coalesced timer (single timer pattern) - Unmount cleanup merges active + pending containers - 5 unit tests + 1 integration test with real InstantSearch - Exported as AisFeeds from vue-instantsearch - Updated mock and index tests for compositionID support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix import ordering lint errors across Layer 3 files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(instantsearch): pass renderOptions to feedContainer.render() for type safety FeedContainer.render() ignores the argument internally but IndexWidget type requires it. Pass renderOptionsRef to satisfy TypeScript. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * temp: add examples * fix: exclude composition examples from v4 type-check @algolia/composition doesn't exist under algoliasearch v4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(react-instantsearch-core): rename Feeds children render-prop to renderFeed Switch from a children render function to a dedicated `renderFeed` prop with an object argument `({ feedID })`. Keeps the API consistent with other React InstantSearch components (`hitComponent`, `itemComponent`, `bannerComponent`), which all use explicit, non-children customization props. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(vue-instantsearch): use indexOf instead of findIndex in mock removeWidgets findIndex expects a predicate function, not the widget object — the call threw at runtime the first time removeWidgets was invoked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(instantsearch): extract isTwoPassWidget utility Replace inline `$$type === 'ais.dynamicWidgets'` checks with a shared `isTwoPassWidget` predicate. This prepares for the feeds widget which also requires a two-pass SSR cycle, and fixes a missing `shouldRefetch ||` in InitializePromise. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(instantsearch): add SSR support for composition multifeed Serialize per-feed results as `compositionFeedsResults` in `getInitialResults`, hydrate them in `hydrateSearchClient`, and reconstruct `lastResults.feeds` in the feeds connector so that composition multifeed works with server-side rendering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(instantsearch): add composition multifeed SSR integration test End-to-end integration test covering the full SSR cycle: server-side rendering with getInitialResults, hydration via hydrateSearchClient, and client-side rehydration of per-feed results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add Next.js App Router composition example Demo app showing composition multifeed with SSR using react-instantsearch-nextjs. Excluded from v4 type-check since it uses composition-only APIs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(react-instantsearch-core): adapt Feeds usages to renderFeed prop Update the SSR test and the Next.js App Router composition example to the new `renderFeed` prop introduced on Layer 3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump bundlesize limit for SSR multifeed The composition multifeed SSR additions push the development bundle just over the 256.5 kB ceiling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: remove internal composition examples These examples reference an internal Algolia application and should not be published. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: reapply removal commits after merge commit --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me> Co-authored-by: Dan Rodriguez <drodriguln@icloud.com> Co-authored-by: Dan Rodriguez <daniel.rodriguez@algolia.com> * chore: bump bundlesize * fix: stale umd import * chore: remove lock file deps from removed examples --------- Co-authored-by: Emmanuel Krebs <e-krebs@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Haroen Viaene <hello@haroen.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Layer 3 of the Multifeed Composition Support (RFC). Stacked on
feat/composition-multifeed-layer2-connector(PR #6964).Adds user-facing
feedswidgets for all three flavors. Each widget owns FeedContainer lifecycle (create, register, remove, reorder) — the connector only computesfeedIDs.InstantSearch.js
feeds()widget with per-feed DOM containers, widget scoping, and DOM reorderingReact InstantSearch
<Feeds>component with per-feedIndexContext.ProviderscopingrenderFeed={({ feedID }) => ...}render prop (not children) — consistent with other customization props in the library (hitComponent,itemComponent, etc.)useFeedshook wrappingconnectFeedsviauseConnectorVue InstantSearch
<ais-feeds>component with per-feedAisFeedProvider(provide/inject)Shared patterns across all flavors
Test plan
🤖 Generated with Claude Code