agentsclimarketplace

Algolia core workflow b

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/algolia-pack/skills/algolia-core-workflow-b

425 plugins, 2,810 skills, 200 agents for Claude Code. Open-source marketplace at tonsofskills.com with the ccpi CLI package manager.

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill algolia-core-workflow-b

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

'Implement Algolia indexing pipeline: data sync, partial updates, synonyms, and rules.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

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 algolia-install-auth setup
  • Familiarity with algolia-core-workflow-a (search)
  • 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

ErrorCauseSolution
Record is too big (limit: 10KB)Object exceeds free-tier limitStrip unnecessary fields; paid plans allow 100KB
Synonym already existsDuplicate objectIDUse replaceExistingSynonyms: true or unique IDs
Invalid rule conditionWrong anchoring valueUse is, startsWith, endsWith, or contains
Partial update creates new recordcreateIfNotExists default is trueSet createIfNotExists: false

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.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.