environment-setup-guide
Guide developers through setting up development environments with proper tools, dependencies, and configurations
lokalise-performance-tuning
Optimize Lokalise API performance with caching, pagination, and bulk operations. Use when experiencing slow API responses, implementing caching strategies, or optimizing request throughput for Lokalise integrations. Trigger with phrases like "lokalise performance", "optimize lokalise", "lokalise ...
Full skill instructions
Optimize Lokalise API performance with caching, pagination, and bulk operations.
| Operation | Typical P50 | Typical P95 | Max Items |
|---|---|---|---|
| List projects | 100ms | 300ms | 100 |
| List keys | 150ms | 500ms | 500 |
| Create key | 200ms | 600ms | 1 |
| Bulk create keys | 300ms | 1000ms | 500 |
| Download files | 500ms | 2000ms | All |
| Upload file | 1000ms | 5000ms | 1 |
const client = new LokaliseApi({
apiKey: process.env.LOKALISE_API_TOKEN!,
enableCompression: true, // Enable gzip for large responses
});
import { LRUCache } from "lru-cache";
const cache = new LRUCache<string, any>({
max: 1000,
ttl: 60000, // 1 minute default TTL
updateAgeOnGet: true,
});
async function cachedRequest<T>(
key: string,
fetcher: () => Promise<T>,
ttl?: number
): Promise<T> {
const cached = cache.get(key);
if (cached !== undefined) {
return cached as T;
}
const result = await fetcher();
cache.set(key, result, { ttl });
return result;
}
// Usage
async function getProject(projectId: string) {
return cachedRequest(
`project:${projectId}`,
() => client.projects().get(projectId),
300000 // 5 minutes
);
}
async function getKeys(projectId: string) {
return cachedRequest(
`keys:${projectId}`,
() => client.keys().list({ project_id: projectId, limit: 500 }),
60000 // 1 minute
);
}
// Cursor pagination is more efficient for large datasets
async function* iterateAllKeys(projectId: string) {
let cursor: string | undefined;
do {
const result = await client.keys().list({
project_id: projectId,
limit: 500, // Max allowed
pagination: "cursor",
cursor,
});
for (const key of result.items) {
yield key;
}
cursor = result.hasNextCursor() ? result.nextCursor : undefined;
} while (cursor);
}
// Usage
async function getAllKeys(projectId: string) {
const keys = [];
for await (const key of iterateAllKeys(projectId)) {
keys.push(key);
}
return keys;
}
// Batch creates are much faster than individual creates
async function createKeysBatched(
projectId: string,
keys: any[],
batchSize = 100
): Promise<any[]> {
const results: any[] = [];
for (let i = 0; i < keys.length; i += batchSize) {
const batch = keys.slice(i, i + batchSize);
const result = await client.keys().create({
project_id: projectId,
keys: batch,
});
results.push(...result.items);
// Small delay to respect rate limits
await new Promise(r => setTimeout(r, 200));
}
return results;
}
// DataLoader for automatic batching
import DataLoader from "dataloader";
const keyLoader = new DataLoader<string, any>(
async (keyIds) => {
// Batch fetch keys
const result = await client.keys().list({
project_id: projectId,
filter_key_ids: keyIds.join(","),
});
// Return in same order as requested
return keyIds.map(id =>
result.items.find(k => k.key_id.toString() === id) || null
);
},
{
maxBatchSize: 100,
batchScheduleFn: callback => setTimeout(callback, 10),
}
);
import PQueue from "p-queue";
const queue = new PQueue({
concurrency: 5,
interval: 1000,
intervalCap: 5,
});
async function downloadMultipleProjects(projectIds: string[]) {
return Promise.all(
projectIds.map(id =>
queue.add(() =>
client.files().download(id, {
format: "json",
original_filenames: false,
})
)
)
);
}
| Issue | Cause | Solution |
|---|---|---|
| Cache miss storm | TTL expired | Use stale-while-revalidate |
| Memory pressure | Cache too large | Set max entries, use Redis |
| Slow pagination | Offset pagination | Switch to cursor pagination |
| Rate limit hit | Too many parallel requests | Use request queue |
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
async function cachedWithRedis<T>(
key: string,
fetcher: () => Promise<T>,
ttlSeconds = 60
): Promise<T> {
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
const result = await fetcher();
await redis.setex(key, ttlSeconds, JSON.stringify(result));
return result;
}
// Stale-while-revalidate pattern
async function staleWhileRevalidate<T>(
key: string,
fetcher: () => Promise<T>,
staleTtl = 60,
maxTtl = 3600
): Promise<T> {
const cached = await redis.get(key);
if (cached) {
const { data, timestamp } = JSON.parse(cached);
const age = (Date.now() - timestamp) / 1000;
if (age < staleTtl) {
return data; // Fresh
}
if (age < maxTtl) {
// Stale but usable - revalidate in background
revalidate(key, fetcher, staleTtl, maxTtl);
return data;
}
}
// Cache miss or expired - fetch fresh
return revalidate(key, fetcher, staleTtl, maxTtl);
}
async function revalidate<T>(
key: string,
fetcher: () => Promise<T>,
staleTtl: number,
maxTtl: number
): Promise<T> {
const data = await fetcher();
await redis.setex(key, maxTtl, JSON.stringify({
data,
timestamp: Date.now(),
}));
return data;
}
async function measuredRequest<T>(
operation: string,
fn: () => Promise<T>
): Promise<T> {
const start = performance.now();
try {
const result = await fn();
const duration = performance.now() - start;
console.log({
operation,
duration: `${duration.toFixed(2)}ms`,
status: "success",
});
// Report to metrics
await reportMetric("lokalise_request_duration", duration, {
operation,
status: "success",
});
return result;
} catch (error: any) {
const duration = performance.now() - start;
console.error({
operation,
duration: `${duration.toFixed(2)}ms`,
status: "error",
error: error.message,
});
await reportMetric("lokalise_request_duration", duration, {
operation,
status: "error",
});
throw error;
}
}
// Preload translations during app startup
async function preloadTranslations(
projectId: string,
locales: string[]
): Promise<Map<string, any>> {
const translations = new Map();
// Download all in parallel
const downloads = await Promise.all(
locales.map(async (locale) => {
const result = await cachedWithRedis(
`translations:${projectId}:${locale}`,
() => fetchTranslationsForLocale(projectId, locale),
3600 // 1 hour cache
);
return { locale, translations: result };
})
);
for (const { locale, translations: trans } of downloads) {
translations.set(locale, trans);
}
return translations;
}
For cost optimization, see lokalise-cost-tuning.
Guide developers through setting up development environments with proper tools, dependencies, and configurations
Implement Exa lint rules, policy enforcement, and automated guardrails. Use when setting up code quality rules for Exa integrations, implementing pre-commit hooks, or configuring CI policy checks for Exa best practices. Trigger with phrases like "exa policy", "exa lint", "exa guardrails", "exa be...
Configure CI/CD pipelines for Documenso integrations. Use when setting up automated testing, deployment pipelines, or continuous integration for Documenso projects. Trigger with phrases like "documenso CI", "documenso GitHub Actions", "documenso pipeline", "documenso automated testing".
Build check model availability and implement fallback chains. Use when building resilient systems or handling model outages. Trigger with phrases like 'openrouter availability', 'openrouter fallback', 'openrouter model down', 'openrouter health check'.
Configure Langfuse enterprise organization management and access control. Use when implementing team access controls, configuring organization settings, or setting up role-based permissions for Langfuse projects. Trigger with phrases like "langfuse RBAC", "langfuse teams", "langfuse organization"...
Execute compliance and security auditing for Cursor usage. Triggers on "cursor compliance", "cursor audit", "cursor security review", "cursor soc2", "cursor gdpr". Use when analyzing or auditing cursor compliance audit. Trigger with phrases like "cursor compliance audit", "cursor audit", "cursor".
Configure Apollo.io CI/CD integration. Use when setting up automated testing, continuous integration, or deployment pipelines for Apollo integrations. Trigger with phrases like "apollo ci", "apollo github actions", "apollo pipeline", "apollo ci/cd", "apollo automated tests".
Create robust Python automation with full logging and safety checks. Use when tasks need complex data processing, authenticated API work, conditional file operations, or error handling beyond simple shell commands.
Configure PostHog across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific PostHog configurations. Trigger with phrases like "posthog environments", "posthog staging", "po...
Expert in designing and building autonomous AI agents. Masters tool use, memory systems, planning strategies, and multi-agent orchestration. Use when: build agent, AI agent, autonomous agent, tool use, function calling.
Validate insecure deserialization checker operations. Auto-activating skill for Security Fundamentals. Triggers on: insecure deserialization checker, insecure deserialization checker Part of the Security Fundamentals skill category. Use when working with insecure deserialization checker functiona...
Manage path traversal finder operations. Auto-activating skill for Security Fundamentals. Triggers on: path traversal finder, path traversal finder Part of the Security Fundamentals skill category. Use when working with path traversal finder functionality. Trigger with phrases like "path traversa...
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience