jeremylongshore/claude-code-plugins-plus-skills
juicebox-pack
plugins/saas-packs/juicebox-pack/skills/juicebox-sdk-patterns/SKILL.md
January 22, 2026
Select agents to install to:
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/main/plugins/saas-packs/juicebox-pack/skills/juicebox-sdk-patterns/SKILL.md -a claude-code --skill juicebox-sdk-patternsInstallation paths:
.claude/skills/juicebox-sdk-patterns/# Juicebox SDK Patterns
## Overview
Production-ready patterns for robust Juicebox integration including error handling, retries, and caching.
## Prerequisites
- Juicebox SDK installed
- Understanding of async/await patterns
- Familiarity with dependency injection
## Instructions
### Step 1: Create Client Wrapper
```typescript
// lib/juicebox-client.ts
import { JuiceboxClient, JuiceboxError } from '@juicebox/sdk';
export class JuiceboxService {
private client: JuiceboxClient;
private cache: Map<string, { data: any; expires: number }>;
constructor(apiKey: string) {
this.client = new JuiceboxClient({
apiKey,
timeout: 30000,
retries: 3
});
this.cache = new Map();
}
async searchPeople(query: string, options?: SearchOptions) {
const cacheKey = `search:${query}:${JSON.stringify(options)}`;
const cached = this.getFromCache(cacheKey);
if (cached) return cached;
try {
const results = await this.client.search.people({
query,
...options
});
this.setCache(cacheKey, results, 300000); // 5 min cache
return results;
} catch (error) {
if (error instanceof JuiceboxError) {
throw this.handleJuiceboxError(error);
}
throw error;
}
}
private handleJuiceboxError(error: JuiceboxError) {
switch (error.code) {
case 'RATE_LIMITED':
return new Error(`Rate limited. Retry after ${error.retryAfter}s`);
case 'INVALID_QUERY':
return new Error(`Invalid query: ${error.message}`);
default:
return error;
}
}
}
```
### Step 2: Implement Retry Logic
```typescript
// lib/retry.ts
export async function withRetry<T>(
fn: () => Promise<T>,
options: { maxRetries: number; backoff: number }
): Promise<T> {
let lastError: Error;
for (let i = 0; i < options.maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
await sleep(options.backoff * Math.pow(2,