Skip to main content 首页 创作者 jeremylongshore tons-of-skills-marketplace algolia-multi-env-setup
algolia-multi-env-setup Configure Algolia across dev/staging/production: index prefixing, per-environment
API keys, settings-as-code, and environment isolation guards.
Trigger: "algolia environments", "algolia staging", "algolia dev prod",
"algolia environment setup", "algolia config by env".
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/jeremylongshore/tons-of-skills-marketplace --skill algolia-multi-env-setup命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... 同仓库更多 Skills langchain-deploy-integration Deploy a LangChain 1.0 / LangGraph 1.0 app to Cloud Run, Vercel, or LangServe correctly — with timeouts sized for chain length, cold-start mitigation, SSE anti-buffering headers, and Secret Manager over .env. Use when prepping a first production deploy, debugging a stream that hangs behind a proxy, or diagnosing p99 latency spikes. Trigger with "langchain deploy", "langchain cloud run", "langchain vercel python", "langchain langserve", or "langchain docker".
langchain-langgraph-agents Build a correct LangGraph 1.0 ReAct agent with create_react_agent — typed tools, error propagation, recursion caps, and stop conditions that actually stop. Use when writing a first tool-calling agent, migrating from AgentExecutor or initialize_agent, or diagnosing an agent that loops on vague prompts. Trigger with "langgraph agent", "create_react_agent", "langgraph tool calling", "AgentExecutor migration", or "agent loop cost".
langchain-langgraph-human-in-loop Build LangGraph 1.0 human-in-the-loop approval flows with interrupt_before /
interrupt_after and Command(resume=...) — JSON-serializable state, clean
resume semantics, and UI wiring for approval decisions. Use when adding an
approval gate before an expensive tool call, wiring a Slack/web UI for agent
approvals, or debugging a graph that crashes on interrupt.
Trigger with "langgraph human in loop", "langgraph interrupt_before",
"langgraph approval flow", "Command resume", "langgraph HITL".
name algolia-multi-env-setup description Configure Algolia across dev/staging/production: index prefixing, per-environment
API keys, settings-as-code, and environment isolation guards.
Trigger: "algolia environments", "algolia staging", "algolia dev prod",
"algolia environment setup", "algolia config by env".
allowed-tools Read, Write, Edit, Bash(npm:*), Bash(gcloud:*), Bash(vault:*) version 1.7.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","search","algolia"] compatibility Designed for Claude Code
Algolia Multi-Environment Setup
Overview
Algolia doesn't have built-in environment separation. You either use separate Algolia applications (strongest isolation) or index prefixing within one application (simpler). This skill covers both approaches.
Prerequisites
Separate environment names or application credentials and a clear production promotion policy.
CI secrets scoped to the environment that performs indexing.
A naming convention that prevents a staging job from writing to the production index.
Environment Strategies
Strategy Isolation Cost Complexity Index prefixing Shared app, prefixed names Lowest Low Separate API keys Shared app, scoped keys Low Medium Separate applications Full isolation Highest High
Instructions
Examples
The index-prefix and configuration examples below demonstrate environment isolation and controlled promotion. Keep the same convention in local tooling, CI, and runtime configuration to avoid cross-environment writes.
Step 1: Index Prefixing (Recommended for Most Teams)
import { algoliasearch, type Algoliasearch } from 'algoliasearch' ;
type Environment = 'development' | 'staging' | 'production' ;
interface AlgoliaConfig {
appId : string ;
apiKey : string ;
searchKey : string ;
environment : Environment ;
}
function ( ): {
env = (process. . || ) ;
{
: process. . !,
: process. . !,
: process. . !,
: env,
};
}
( ): {
{ environment } = ();
(environment === ) base;
;
}
: | = ;
( ): {
(!_client) {
config = ();
_client = (config. , config. );
}
_client;
}
getConfig
AlgoliaConfig
const
env
NODE_ENV
'development'
as
Environment
return
appId
env
ALGOLIA_APP_ID
apiKey
env
ALGOLIA_ADMIN_KEY
searchKey
env
ALGOLIA_SEARCH_KEY
environment
export
function
indexName
base : string
string
const
getConfig
if
'production'
return
return
`${environment} _${base} `
let
_client
Algoliasearch
null
null
export
function
getClient
Algoliasearch
if
const
getConfig
algoliasearch
appId
apiKey
return
Step 2: Scoped API Keys Per Environment import { algoliasearch } from 'algoliasearch' ;
const adminClient = algoliasearch (process.env .ALGOLIA_APP_ID !, process.env .ALGOLIA_ADMIN_KEY !);
async function createEnvironmentKeys ( ) {
const { key : stagingKey } = await adminClient.addApiKey ({
apiKey : {
acl : ['search' , 'addObject' , 'deleteObject' , 'editSettings' , 'browse' ],
description : 'Staging environment — full access to staging indices only' ,
indexes : ['staging_*' ],
maxQueriesPerIPPerHour : 10000 ,
},
});
console .log (`Staging key: ${stagingKey} ` );
const { key : devKey } = await adminClient.addApiKey ({
apiKey : {
acl : ['search' , 'addObject' , 'deleteObject' , 'editSettings' , 'browse' ],
description : 'Development environment — full access to dev indices only' ,
indexes : ['development_*' ],
maxQueriesPerIPPerHour : 5000 ,
},
});
console .log (`Dev key: ${devKey} ` );
const { key : prodSearchKey } = await adminClient.addApiKey ({
apiKey : {
acl : ['search' ],
description : 'Production search — read only' ,
indexes : ['products' , 'articles' , 'faq' ],
maxQueriesPerIPPerHour : 50000 ,
maxHitsPerQuery : 100 ,
},
});
console .log (`Prod search key: ${prodSearchKey} ` );
}
Step 3: Environment Variables Per Platform
ALGOLIA_APP_ID=YourAppID
ALGOLIA_ADMIN_KEY=dev_scoped_key_here
ALGOLIA_SEARCH_KEY=dev_search_key_here
NODE_ENV=development
ALGOLIA_APP_ID=YourAppID
ALGOLIA_ADMIN_KEY=staging_scoped_key_here
ALGOLIA_SEARCH_KEY=staging_search_key_here
NODE_ENV=staging
Step 4: Settings-as-Code with Environment Overrides
import type { IndexSettings } from 'algoliasearch' ;
const baseSettings : IndexSettings = {
searchableAttributes : ['name' , 'brand' , 'category' , 'unordered(description)' ],
attributesForFaceting : ['searchable(brand)' , 'category' , 'filterOnly(price)' ],
customRanking : ['desc(review_count)' , 'desc(rating)' ],
};
const envOverrides : Partial <Record <string , Partial <IndexSettings >>> = {
development : {
replicas : [],
},
staging : {
replicas : ['virtual(staging_products_price_asc)' ],
},
production : {
replicas : [
'virtual(products_price_asc)' ,
'virtual(products_price_desc)' ,
'virtual(products_newest)' ,
],
},
};
export function getSettings (env : string ): IndexSettings {
return { ...baseSettings, ...envOverrides[env] };
}
Step 5: Environment Isolation Guard
export function guardEnvironment (operation : string , targetIndex : string ) {
const env = process.env .NODE_ENV || 'development' ;
if (env === 'production' ) {
if (targetIndex.startsWith ('development_' ) || targetIndex.startsWith ('staging_' )) {
throw new Error (`Blocked: ${operation} on ${targetIndex} from production` );
}
} else {
if (!targetIndex.startsWith (`${env} _` )) {
throw new Error (`Blocked: ${operation} on ${targetIndex} from ${env} . Use prefixed index.` );
}
}
}
async function deleteIndex (name : string ) {
guardEnvironment ('deleteIndex' , name);
await getClient ().deleteIndex ({ indexName : name });
}
Step 6: Seed Script Per Environment
import { getClient, indexName } from '../src/algolia/config' ;
import { getSettings } from '../config/algolia-settings' ;
async function seedEnvironment ( ) {
const env = process.env .NODE_ENV || 'development' ;
const client = getClient ();
const idx = indexName ('products' );
console .log (`Seeding ${env} environment → index: ${idx} ` );
await client.setSettings ({ indexName : idx, indexSettings : getSettings (env) });
if (env !== 'production' ) {
const testData = await import ('../fixtures/products.json' );
const { taskID } = await client.replaceAllObjects ({
indexName : idx,
objects : testData.default ,
});
await client.waitForTask ({ indexName : idx, taskID });
console .log (`Seeded ${testData.default .length} records` );
}
}
seedEnvironment ().catch (console .error );
Output Each environment resolves to the intended index and credentials, with promotion and rollback paths that do not expose production keys or overwrite production data from staging.
Error Handling Issue Cause Solution Wrong index in production Missing prefix logic Use indexName() helper everywhere Staging data leaking to prod Shared API key Use scoped keys restricted to index patterns Settings drift between envs Manual dashboard changes Apply settings from code in CI Dev index polluting record count Old test indices Scheduled cleanup job for development_* indices
Resources
Next Steps For observability setup, see algolia-observability.