agentsclimarketplace

Algolia local dev loop

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/algolia-pack/skills/algolia-local-dev-loop

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-local-dev-loop

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

'Configure Algolia local development with separate dev index, mocking, and testing.

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

5.7 KB, as published. Nobody here has run it

Algolia Local Dev Loop

Overview

Set up a fast, reproducible local development workflow for Algolia. Use separate dev indices, mock the client in tests, and iterate without touching production data.

Prerequisites

  • Completed algolia-install-auth setup
  • Node.js 18+ with npm/pnpm
  • Vitest or Jest for testing

Instructions

Step 1: Environment-Based Index Names

// src/algolia/config.ts
import { algoliasearch } from 'algoliasearch';

const ENV = process.env.NODE_ENV || 'development';

// Each environment gets its own index prefix
export function indexName(base: string): string {
  if (ENV === 'production') return base;
  return `${ENV}_${base}`; // e.g., "development_products"
}

export const client = algoliasearch(
  process.env.ALGOLIA_APP_ID!,
  process.env.ALGOLIA_ADMIN_KEY!
);

Step 2: Seed Script for Dev Data

// scripts/seed-algolia.ts
import { client, indexName } from '../src/algolia/config';

const SEED_DATA = [
  { objectID: 'prod-1', name: 'Widget A', category: 'tools', price: 29.99 },
  { objectID: 'prod-2', name: 'Widget B', category: 'tools', price: 49.99 },
  { objectID: 'prod-3', name: 'Gadget C', category: 'electronics', price: 199.99 },
];

async function seed() {
  const idx = indexName('products');

  // replaceAllObjects atomically swaps index content
  const { taskID } = await client.replaceAllObjects({
    indexName: idx,
    objects: SEED_DATA,
  });
  await client.waitForTask({ indexName: idx, taskID });

  // Configure settings for the dev index
  await client.setSettings({
    indexName: idx,
    indexSettings: {
      searchableAttributes: ['name', 'category'],
      attributesForFaceting: ['category', 'filterOnly(price)'],
      customRanking: ['asc(price)'],
    },
  });

  console.log(`Seeded ${SEED_DATA.length} records into ${idx}`);
}

seed().catch(console.error);
{
  "scripts": {
    "seed:algolia": "npx tsx scripts/seed-algolia.ts",
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:watch": "vitest --watch"
  }
}

Step 3: Mock Algolia in Unit Tests

// tests/algolia.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock the entire algoliasearch module
vi.mock('algoliasearch', () => ({
  algoliasearch: vi.fn(() => ({
    searchSingleIndex: vi.fn().mockResolvedValue({
      hits: [
        { objectID: '1', name: 'Widget A', _highlightResult: {} },
      ],
      nbHits: 1,
      page: 0,
      nbPages: 1,
    }),
    saveObjects: vi.fn().mockResolvedValue({ taskID: 123 }),
    waitForTask: vi.fn().mockResolvedValue({}),
  })),
}));

import { algoliasearch } from 'algoliasearch';

describe('Product Search', () => {
  const client = algoliasearch('test-app-id', 'test-api-key');

  it('returns matching products', async () => {
    const { hits } = await client.searchSingleIndex({
      indexName: 'development_products',
      searchParams: { query: 'widget' },
    });
    expect(hits).toHaveLength(1);
    expect(hits[0].name).toBe('Widget A');
  });
});

Step 4: Integration Test with Real API

// tests/integration/algolia.integration.test.ts
import { describe, it, expect } from 'vitest';
import { algoliasearch } from 'algoliasearch';

describe.skipIf(!process.env.ALGOLIA_APP_ID)('Algolia Integration', () => {
  const client = algoliasearch(
    process.env.ALGOLIA_APP_ID!,
    process.env.ALGOLIA_ADMIN_KEY!
  );
  const testIndex = `test_${Date.now()}_products`;

  it('indexes and searches records', async () => {
    // Index
    const { taskID } = await client.saveObjects({
      indexName: testIndex,
      objects: [{ objectID: '1', name: 'Test Product' }],
    });
    await client.waitForTask({ indexName: testIndex, taskID });

    // Search
    const { hits } = await client.searchSingleIndex({
      indexName: testIndex,
      searchParams: { query: 'test' },
    });
    expect(hits.length).toBeGreaterThan(0);

    // Cleanup
    await client.deleteIndex({ indexName: testIndex });
  });
});

Error Handling

ErrorCauseSolution
Index does not existDev index not seededRun npm run seed:algolia
Test pollutionShared index between testsUse unique timestamped index names
Stale search resultsIndexing not waitedAlways await client.waitForTask() after writes
Mock not appliedWrong import orderEnsure vi.mock() is before imports

Examples

Clean Dev Index on Start

// scripts/reset-dev-algolia.ts
import { client, indexName } from '../src/algolia/config';

async function reset() {
  const idx = indexName('products');
  try {
    await client.deleteIndex({ indexName: idx });
    console.log(`Deleted ${idx}`);
  } catch (e) {
    // Index may not exist yet — that's fine
  }
}

reset().catch(console.error);

Resources

Next Steps

See algolia-sdk-patterns for production-ready code patterns.

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.