Claude-code-plugins-plus-skills algolia-core-workflow-b
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/algolia-pack/skills/algolia-core-workflow-b" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-algolia-core-workflow-b && rm -rf "$T"
manifest:
plugins/saas-packs/algolia-pack/skills/algolia-core-workflow-b/SKILL.mdsource content
Algolia Core Workflow B — Indexing & Data Sync
Overview
Keep your Algolia index synchronized with your source database. Covers full reindex, incremental updates, partial updates, synonyms, and query rules.
Prerequisites
- Completed
setupalgolia-install-auth - Familiarity with
(search)algolia-core-workflow-a - Source database or API with change tracking (timestamps, events)
Instructions
Step 1: Full Reindex with replaceAllObjects
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`); }
Step 2: Incremental Updates with partialUpdateObject
// 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 }); }
Step 3: Manage Synonyms
// 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 });
Step 4: Configure Query Rules
// 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 Handling
| Error | Cause | Solution |
|---|---|---|
| Object exceeds free-tier limit | Strip unnecessary fields; paid plans allow 100KB |
| Duplicate objectID | Use or unique IDs |
| Wrong value | Use , , , or |
| Partial update creates new record | default is | Set |
Examples
Database Change Listener → Algolia Sync
// 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; } }
Search for Synonyms
// 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"`);
Resources
Next Steps
For common errors, see
algolia-common-errors.