From algolia-pack
Implements Algolia indexing pipeline: full reindex, partial updates, synonyms, and rules to sync source database or API with search index.
How this skill is triggered — by the user, by Claude, or both
Slash command
/algolia-pack:algolia-core-workflow-bThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Keep your Algolia index synchronized with your source database. Covers full reindex, incremental updates, partial updates, synonyms, and query rules.
Keep your Algolia index synchronized with your source database. Covers full reindex, incremental updates, partial updates, synonyms, and query rules.
algolia-install-auth setupalgolia-core-workflow-a (search)import { algoliasearch } from 'algoliasearch';
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
// replaceAllObjects atomically swaps index content
// Internally: creates temp index → indexes all records → moves temp to target
// Search continues on old data until swap is complete — zero downtime
async function fullReindex(records: Record<string, any>[]) {
const { taskID } = await client.replaceAllObjects({
indexName: 'products',
objects: records,
batchSize: 1000, // Records per batch (default 1000)
});
await client.waitForTask({ indexName: 'products', taskID });
console.log(`Full reindex complete: ${records.length} records`);
}
// Only update changed fields — much faster than full saveObjects
async function updateProductPrice(objectID: string, newPrice: number) {
await client.partialUpdateObject({
indexName: 'products',
objectID,
attributesToUpdate: {
price: newPrice,
updated_at: new Date().toISOString(),
},
createIfNotExists: false, // Don't create if missing
});
}
// Batch partial updates
async function syncPriceChanges(changes: { id: string; price: number }[]) {
const { taskID } = await client.partialUpdateObjects({
indexName: 'products',
objects: changes.map(c => ({
objectID: c.id,
price: c.price,
updated_at: new Date().toISOString(),
})),
createIfNotExists: false,
});
await client.waitForTask({ indexName: 'products', taskID });
}
// Synonyms help users find products with different terminology
await client.saveSynonyms({
indexName: 'products',
synonymHit: [
// Two-way synonym: any of these terms match each other
{
objectID: 'syn-1',
type: 'synonym',
synonyms: ['laptop', 'notebook', 'portable computer'],
},
// One-way synonym: "phone" also searches for "smartphone" but not reverse
{
objectID: 'syn-2',
type: 'oneWaySynonym',
input: 'phone',
synonyms: ['smartphone', 'mobile phone', 'cell phone'],
},
// Alt correction: minor typos/variations
{
objectID: 'syn-3',
type: 'altCorrection1',
word: 'color',
corrections: ['colour'],
},
// Placeholder: replace pattern with alternatives
{
objectID: 'syn-4',
type: 'placeholder',
placeholder: '<size>',
replacements: ['small', 'medium', 'large', 'XL'],
},
],
forwardToReplicas: true,
replaceExistingSynonyms: false, // true = wipe existing first
});
// Rules let you pin, hide, boost, or filter results for specific queries
await client.saveRule({
indexName: 'products',
objectID: 'rule-sale-banner',
rule: {
conditions: [{
anchoring: 'contains',
pattern: 'sale',
}],
consequence: {
// Pin a specific record to position 1
promote: [{ objectID: 'promo-banner-sale', position: 0 }],
// Add automatic filter
params: {
filters: 'on_sale = true',
},
},
description: 'When user searches "sale", filter to sale items and pin banner',
enabled: true,
},
});
// Hide a product from search results
await client.saveRule({
indexName: 'products',
objectID: 'rule-hide-discontinued',
rule: {
conditions: [{ anchoring: 'is', pattern: '' }], // Matches all queries
consequence: {
hide: [{ objectID: 'discontinued-product-123' }],
},
description: 'Hide discontinued product from all searches',
enabled: true,
},
});
| Error | Cause | Solution |
|---|---|---|
Record is too big (limit: 10KB) | Object exceeds free-tier limit | Strip unnecessary fields; paid plans allow 100KB |
Synonym already exists | Duplicate objectID | Use replaceExistingSynonyms: true or unique IDs |
Invalid rule condition | Wrong anchoring value | Use is, startsWith, endsWith, or contains |
| Partial update creates new record | createIfNotExists default is true | Set createIfNotExists: false |
// Listen for DB changes and push to Algolia
import { getClient } from './algolia/client';
async function onDatabaseChange(event: { type: string; record: any }) {
const client = getClient();
const idx = 'products';
switch (event.type) {
case 'INSERT':
case 'UPDATE':
await client.saveObject({ indexName: idx, body: event.record });
break;
case 'DELETE':
await client.deleteObject({ indexName: idx, objectID: event.record.id });
break;
}
}
// List all synonyms matching a query
const { hits } = await client.searchSynonyms({
indexName: 'products',
searchSynonymsParams: { query: 'phone', type: 'synonym' },
});
console.log(`Found ${hits.length} synonym sets matching "phone"`);
For common errors, see algolia-common-errors.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin algolia-packImplements Algolia data handling: transforms records, filters PII before indexing, manages retention and GDPR/CCPA compliance with deleteByQuery and Insights deletion.
Provides 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.