Algolia Local Dev Loop
SkillSearchSets up a local Algolia development loop with a separate dev index and mocking so search changes stay isolated.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Algolia Local Dev Loop skill
About this capability
Create a fast local development loop for Algolia record transforms and search behavior without contaminating shared indices. Use when iterating on search code, fixtures, or client wrappers. Trigger with "Algolia local development", "mock Algolia", or "test search locally".
What this skill tells your AI
The instructions your AI receives, as published by jeremylongshore/tons-of-skills-marketplace in skills/.curated/algolia-local-dev-loop/SKILL.md and read by ahel’s review.
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-authsetup - 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 });
});
});
Output
The local loop provides an isolated development index, repeatable seed data, and a fast verification path for search and indexing changes. Production data and credentials remain outside the local development workflow.
Error Handling
| Error | Cause | Solution |
|---|---|---|
Index does not exist | Dev index not seeded | Run npm run seed:algolia |
| Test pollution | Shared index between tests | Use unique timestamped index names |
| Stale search results | Indexing not waited | Always await client.waitForTask() after writes |
| Mock not applied | Wrong import order | Ensure 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.
Signals
- GitHub stars
- 3k
- Forks
- 396
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
algolia-local-dev-loop- Source
- github.com/jeremylongshore/tons-of-skills-marketplace