From algolia-pack
Configures Algolia indexes for faceting/filtering and implements searchSingleIndex queries with filters, facets, highlighting, pagination, and numeric ranges.
How this skill is triggered — by the user, by Claude, or both
Slash command
/algolia-pack:algolia-core-workflow-aThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Primary Algolia workflow: full-text search with filters, faceted navigation, hit highlighting, and pagination. Uses `searchSingleIndex` (v5) with real Algolia search parameters.
Primary Algolia workflow: full-text search with filters, faceted navigation, hit highlighting, and pagination. Uses searchSingleIndex (v5) with real Algolia search parameters.
algolia-install-auth and algolia-hello-world setupalgolia-hello-world)searchableAttributes and attributesForFacetingimport { algoliasearch } from 'algoliasearch';
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
await client.setSettings({
indexName: 'products',
indexSettings: {
// What to search (ordered = priority matters)
searchableAttributes: ['name', 'description', 'brand', 'category'],
// What to filter/facet on — prefix with filterOnly() if no facet counts needed
attributesForFaceting: [
'searchable(brand)', // Searchable facet: users can search within brand values
'category', // Regular facet: shown in facet panels
'filterOnly(price)', // Filter only: no counts computed, saves CPU
'filterOnly(in_stock)',
],
// Custom ranking: tie-breaker after Algolia's relevance ranking
customRanking: ['desc(sales_count)', 'desc(rating)'],
// What comes back in hits
attributesToRetrieve: ['name', 'brand', 'price', 'image_url', 'category'],
attributesToHighlight: ['name', 'description'],
attributesToSnippet: ['description:30'], // 30-word snippet
},
});
// Algolia filter syntax uses SQL-like expressions
const { hits, nbHits, facets } = await client.searchSingleIndex({
indexName: 'products',
searchParams: {
query: 'running shoes',
// Numeric/boolean/string filters
filters: 'price < 150 AND in_stock = true',
// OR: facetFilters for UI-driven filtering (array = OR, nested = AND)
// facetFilters: [['category:shoes', 'category:sneakers'], ['brand:Nike']],
// ^ shoes OR sneakers, AND brand is Nike
// Numeric range filters
numericFilters: ['price >= 50', 'price <= 150'],
// Request facet counts for these attributes
facets: ['category', 'brand'],
// Pagination
hitsPerPage: 20,
page: 0,
// Highlighting
highlightPreTag: '<mark>',
highlightPostTag: '</mark>',
},
});
console.log(`${nbHits} results found`);
// Access facet counts for building filter UI
// facets = { category: { shoes: 42, sneakers: 18 }, brand: { Nike: 30, Adidas: 25 } }
for (const [facetName, values] of Object.entries(facets || {})) {
console.log(`${facetName}:`);
for (const [value, count] of Object.entries(values)) {
console.log(` ${value}: ${count}`);
}
}
hits.forEach(hit => {
// _highlightResult contains highlighted versions of each field
const highlighted = hit._highlightResult;
const name = highlighted?.name?.value || hit.name;
const snippet = hit._snippetResult?.description?.value || '';
console.log(`${name} — $${hit.price}`);
if (snippet) console.log(` ${snippet}`);
});
async function paginatedSearch(query: string, page: number = 0) {
const { hits, nbHits, nbPages, hitsPerPage } = await client.searchSingleIndex({
indexName: 'products',
searchParams: {
query,
hitsPerPage: 20,
page,
},
});
return {
hits,
totalHits: nbHits,
totalPages: nbPages,
currentPage: page,
hasMore: page < nbPages - 1,
};
}
| Error | Cause | Solution |
|---|---|---|
Invalid filter syntax | Malformed filters string | Check filter syntax: field:value, field < N, use AND/OR/NOT |
Attribute not valid for filtering | Field not in attributesForFaceting | Add field to attributesForFaceting in settings |
0 results unexpectedly | Typo tolerance may be disabled | Check typoTolerance setting; verify data is indexed |
| Stale results after update | Didn't wait for task | Use await client.waitForTask() after indexing |
const { results } = await client.search({
requests: [
{ indexName: 'products', query: 'laptop', hitsPerPage: 5 },
{ indexName: 'articles', query: 'laptop', hitsPerPage: 3 },
],
});
// results[0].hits = product hits, results[1].hits = article hits
const { hits } = await client.searchSingleIndex({
indexName: 'products',
searchParams: {
query: 'shoes',
optionalFilters: ['brand:Nike'], // Nike products ranked higher but not required
},
});
For indexing and data sync workflows, see algolia-core-workflow-b.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin algolia-packProvides expert patterns for Algolia search implementation, indexing strategies, React InstantSearch hooks, relevance tuning, and Next.js SSR integration.
Provides expert patterns for Algolia search implementation, including React InstantSearch hooks, indexing strategies, relevance tuning, and Next.js SSR integration.
Indexes records into Algolia with saveObjects and searches using searchSingleIndex via algoliasearch v5 client. For new integrations, setup testing, or learning core patterns.