anthropics/skills180kfrontend-design
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
前端开发
Design production-ready SDKs with retry logic, error handling, pagination, and multi-language support. Use when building client libraries for APIs or creating developer-facing SDK interfaces.
把这段话发给 Claude Code、Codex 或 Cursor。智能体会先检查安全性,你确认后才安装。
读取 https://funcoding.ai/skills/ancoleman/ai-design-components/designing-sdks/install.md ,按里面的步骤帮我安装这个 Skill。
Design client libraries (SDKs) with excellent developer experience through intuitive APIs, robust error handling, automatic retries, and consistent patterns across programming languages.
Use when building a client library for a REST API, creating internal service SDKs, implementing retry logic with exponential backoff, handling authentication patterns, creating typed error hierarchies, implementing pagination with async iterators, or designing streaming APIs for real-time data.
Organize SDK code hierarchically:
Client (config: API key, base URL, retries, timeout)
├─ Resources (users, payments, posts)
│ ├─ create(), retrieve(), update(), delete()
│ └─ list() (with pagination)
└─ Top-Level Methods (convenience)
Resource-Based (Stripe style):
const client = new APIClient({ apiKey: 'sk_test_...' })
const user = await client.users.create({ email: '[email protected]' })
Use for APIs <100 methods. Prioritizes developer experience.
Command-Based (AWS SDK v3):
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
await client.send(new PutObjectCommand({ Bucket: '...' }))
Use for APIs >100 methods. Prioritizes bundle size and tree-shaking.
For detailed architectural guidance, see references/architecture-patterns.md.
const user = await client.users.create({ email: '[email protected]' })
All methods return Promises. Avoid callbacks.
# Sync
client = APIClient(api_key='sk_test_...')
user = client.users.create(email='[email protected]')
# Async
async_client = AsyncAPIClient(api_key='sk_test_...')
user = await async_client.users.create(email='[email protected]')
Provide both clients. Users choose based on architecture.
client := apiclient.New("api_key")
user, err := client.Users().Create(ctx, req)
Use context.Context for timeout and cancellation.
const client = new APIClient({ apiKey: process.env.API_KEY })
Store keys in environment variables, never hardcode.
const client = new APIClient({
clientId: 'id',
clientSecret: 'secret',
refreshToken: 'token',
onTokenRefresh: (newToken) => saveToken(newToken)
})
SDK automatically refreshes tokens before expiry.
await client.users.list({
headers: { Authorization: `Bearer ${userToken}` }
})
Use for multi-tenant applications.
See references/authentication.md for OAuth flows, JWT handling, and credential providers.
async function retryWithBackoff<T>(fn: () => Promise<T>, maxRetries: number): Promise<T> {
let attempt = 0
while (attempt <= maxRetries) {
try {
return await fn()
} catch (error) {
attempt++
if (attempt > maxRetries || !isRetryable(error)) throw error
const exponential = Math.min(1000 * Math.pow(2, attempt - 1), 10000)
const jitter = Math.random() * 500
await sleep(exponential + jitter)
}
}
}
function isRetryable(error: any): boolean {
return (
error.code === 'ECONNRESET' ||
error.code === 'ETIMEDOUT' ||
(error.status >= 500 && error.status < 600) ||
error.status === 429
)
}
Retry Decision Matrix:
| Error Type | Retry? | Rationale |
|---|---|---|
| 5xx, 429, Network Timeout | ✅ Yes | Transient errors |
| 4xx, 401, 403, 404 | ❌ No | Client errors won't fix themselves |
if (error.status === 429) {
const retryAfter = parseInt(error.headers['retry-after'] || '60')
await sleep(retryAfter * 1000)
}
Respect Retry-After header on 429 responses.
See references/retry-backoff.md for jitter strategies, circuit breakers, and idempotency keys.
class APIError extends Error {
constructor(
message: string,
public status: number,
public code: string,
public requestId: string
) {
super(message)
this.name = 'APIError'
}
}
class RateLimitError extends APIError {
constructor(message: string, requestId: string, public retryAfter: number) {
super(message, 429, 'rate_limit_error', requestId)
}
}
class AuthenticationError extends APIError {
constructor(message: string, requestId: string) {
super(message, 401, 'authentication_error', requestId)
}
}
try {
const user = await client.users.create({ email: 'invalid' })
} catch (error) {
if (error instanceof RateLimitError) {
await sleep(error.retryAfter * 1000)
} else if (error instanceof AuthenticationError) {
console.error('Invalid API key')
} else if (error instanceof APIError) {
console.error(`${error.message} (Request ID: ${error.requestId})`)
}
}
Include request ID in all errors for debugging.
See references/error-handling.md for user-friendly messages, validation errors, and debugging support.
TypeScript:
for await (const user of client.users.list({ limit: 100 })) {
console.log(user.id, user.email)
}
Python:
async for user in client.users.list(limit=100):
print(user.id, user.email)
SDK automatically fetches next page.
class UsersResource {
async *list(options?: { limit?: number }): AsyncGenerator<User> {
let cursor: string | undefined = undefined
while (true) {
const response = await this.client.request('GET', '/users', {
query: { limit: String(options?.limit || 100), ...(cursor ? { cursor } : {}) }
})
for (const user of response.data) yield user
if (!response.has_more) break
cursor = response.next_cursor
}
}
}
let cursor: string | undefined = undefined
while (true) {
const response = await client.users.list({ limit: 100, cursor })
for (const user of response.data) console.log(user.id)
if (!response.has_more) break
cursor = response.next_cursor
}
Provide both automatic and manual options.
See references/pagination.md for cursor vs. offset pagination and Go channel patterns.
async *stream(path: string, body?: any): AsyncGenerator<any> {
const response = await fetch(url, {
headers: { 'Accept': 'text/event-stream' },
body: JSON.stringify(body)
})
const reader = response.body!.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
for (const line of chunk.split('\n')) {
if (line.startsWith('data: ')) {
const data = line.slice(6)
if (data === '[DONE]') return
yield JSON.parse(data)
}
}
}
}
// Usage
for await (const chunk of client.posts.stream({ prompt: 'Write a story' })) {
process.stdout.write(chunk.content)
}
Prevent duplicate operations during retries:
import { randomUUID } from 'crypto'
if (['POST', 'PATCH', 'PUT'].includes(method)) {
headers['Idempotency-Key'] = options?.idempotencyKey || randomUUID()
}
// Usage
await client.charges.create(
{ amount: 1000 },
{ idempotencyKey: 'charge_unique_123' }
)
Server deduplicates requests by key.
1.0.0 → 1.1.0: New features (safe)1.1.0 → 2.0.0: Breaking changes (review)1.0.0 → 1.0.1: Bug fixes (safe)function deprecated(message: string, since: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value
descriptor.value = function (...args: any[]) {
console.warn(`[DEPRECATED] ${propertyKey} since ${since}. ${message}`)
return originalMethod.apply(this, args)
}
return descriptor
}
}
@deprecated('Use users.list() instead', 'v2.0.0')
async getAll() { return this.list() }
const client = new APIClient({
apiKey: 'sk_test_...',
apiVersion: '2025-01-01'
})
See references/versioning.md for migration strategies.
interface ClientConfig {
apiKey: string
baseURL?: string
maxRetries?: number
timeout?: number
apiVersion?: string
onTokenRefresh?: (token: string) => void
}
class APIClient {
constructor(config: ClientConfig) {
this.apiKey = config.apiKey
this.baseURL = config.baseURL || 'https://api.example.com'
this.maxRetries = config.maxRetries ?? 3
this.timeout = config.timeout ?? 30000
}
}
Provide sensible defaults, require only apiKey.
| Pattern | Use Case |
|---|---|
| API Key | Service-to-service |
| OAuth Refresh | User-based auth |
| Bearer Per-Request | Multi-tenant |
| Strategy | Use Case |
|---|---|
| Exponential Backoff | Default retry |
| Rate Limit | 429 responses |
| Max Retries | Avoid infinite loops (3-5) |
| Pattern | Language | Use Case |
|---|---|---|
| Async Iterator | TypeScript, Python | Automatic pagination |
| Generator | Python | Sync pagination |
| Channels | Go | Concurrent iteration |
| Manual | All | Explicit control |
Architecture:
references/architecture-patterns.md - Resource vs. command organizationCore Patterns:
references/authentication.md - OAuth, token refresh, credential providersreferences/retry-backoff.md - Exponential backoff, jitter, circuit breakersreferences/error-handling.md - Error hierarchies, debugging supportreferences/pagination.md - Cursor vs. offset, async iteratorsreferences/versioning.md - SemVer, deprecation strategiesreferences/testing-sdks.md - Unit testing, mocking, integration testsTypeScript:
examples/typescript/basic-client.ts - Simple async SDKexamples/typescript/advanced-client.ts - Retry, errors, streamingexamples/typescript/resource-based.ts - Stripe-style organizationPython:
examples/python/sync-client.py - Synchronous clientexamples/python/async-client.py - Async client with asyncioexamples/python/dual-client.py - Both sync and asyncGo:
examples/go/basic-client.go - Simple Go clientexamples/go/context-client.go - Context patternsexamples/go/channel-pagination.go - Channel-based paginationStudy these production SDKs:
TypeScript/JavaScript:
@aws-sdk/client-*): Modular, tree-shakeable, middlewarestripe): Resource-based, typed errors, excellent DXopenai): Streaming, async iterators, modern TypeScriptPython:
boto3): Resource vs. client patterns, paginatorsstripe): Dual sync/async, context managersGo:
github.com/aws/aws-sdk-go-v2): Context, middlewareAvoid these mistakes:
Retry-After header on 429 responsesReview language-specific examples for implementation details. Study references for deep dives on specific patterns. Examine best-in-class SDKs (Stripe, AWS, OpenAI) for inspiration.
anthropics/skills180kGuidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
前端开发
anthropics/skills180kSuite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
前端开发
addyosmani/agent-skills103kGuides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend.
前端开发
addyosmani/agent-skills103kBuilds production-quality, accessible, responsive user-facing UIs. Use when building or modifying interfaces and pages, creating components, implementing layouts, meeting WCAG accessibility requirements, managing state, or when the output needs to look and feel production-quality rather than AI-generated.
前端开发
addyosmani/agent-skills103kOptimizes application performance across frontend, backend, queries, and databases. Use when performance requirements exist, when you suspect performance regressions, when Core Web Vitals or load times need improvement, when N+1 query patterns need fixing, or when profiling reveals bottlenecks.
前端开发
nexu-io/open-design100kOpenDesign's feature business case for the plugin marketplace: the user pain, options, tradeoffs, and the measure of success. Built as a decision-grade product management deck for PM, eng, design, leadership.
前端开发