[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7EMSW0765HXF2NHADRN56NG":3,"skill-same:01M7EMSW0765HXF2NHADRN56NG":49},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":13,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":28,"install":29,"resources":42},"01M7EMSW0765HXF2NHADRN56NG","backend-patterns",null,"Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes. Use when building or reviewing Node.js, Express, or Next.js API routes and their data access.","mhyahya854\u002FAI-Second-Brain_Universal-Rules","mhyahya854","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F194078115?v=4","01M7EGSP2M9T858SDHJMXQ257Y","01M7EGSP3N6HN6879SVDPMD4DZ",0,"MIT","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Faffaan-m\u002FECC\u002Fbackend-patterns\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: backend-patterns\ndescription: Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes. Use when building or reviewing Node.js, Express, or Next.js API routes and their data access.\nlicense: MIT\n---\n\n# Backend Development Patterns\n\nBackend architecture patterns and best practices for scalable server-side applications.\n\n## When to Activate\n\n- Designing REST or GraphQL API endpoints\n- Implementing repository, service, or controller layers\n- Optimizing database queries (N+1, indexing, connection pooling)\n- Adding caching (Redis, in-memory, HTTP cache headers)\n- Setting up background jobs or async processing\n- Structuring error handling and validation for APIs\n- Building middleware (auth, logging, rate limiting)\n\n## API Design Patterns\n\n### RESTful API Structure\n\n```typescript\n\u002F\u002F PASS: Resource-based URLs\nGET    \u002Fapi\u002Fmarkets                 # List resources\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Get single resource\nPOST   \u002Fapi\u002Fmarkets                 # Create resource\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Replace resource\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Update resource\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Delete resource\n\n\u002F\u002F PASS: Query parameters for filtering, sorting, pagination\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Pattern\n\n```typescript\n\u002F\u002F Abstract data access logic\ninterface MarketRepository {\n  findAll(filters?: MarketFilters): Promise\u003CMarket[]>\n  findById(id: string): Promise\u003CMarket | null>\n  create(data: CreateMarketDto): Promise\u003CMarket>\n  update(id: string, data: UpdateMarketDto): Promise\u003CMarket>\n  delete(id: string): Promise\u003Cvoid>\n}\n\nclass SupabaseMarketRepository implements MarketRepository {\n  async findAll(filters?: MarketFilters): Promise\u003CMarket[]> {\n    let query = supabase.from('markets').select('*')\n\n    if (filters?.status) {\n      query = query.eq('status', filters.status)\n    }\n\n    if (filters?.limit) {\n      query = query.limit(filters.limit)\n    }\n\n    const { data, error } = await query\n\n    if (error) throw new Error(error.message)\n    return data\n  }\n\n  \u002F\u002F Other methods...\n}\n```\n\n### Service Layer Pattern\n\n```typescript\n\u002F\u002F Business logic separated from data access\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F Business logic\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Fetch full data\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Sort by similarity\n    return markets.sort((a, b) => {\n      const scoreA = results.find(r => r.id === a.id)?.score || 0\n      const scoreB = results.find(r => r.id === b.id)?.score || 0\n      return scoreA - scoreB\n    })\n  }\n\n  private async vectorSearch(embedding: number[], limit: number) {\n    \u002F\u002F Vector search implementation\n  }\n}\n```\n\n### Middleware Pattern\n\n```typescript\n\u002F\u002F Request\u002Fresponse processing pipeline\nexport function withAuth(handler: NextApiHandler): NextApiHandler {\n  return async (req, res) => {\n    const token = req.headers.authorization?.replace('Bearer ', '')\n\n    if (!token) {\n      return res.status(401).json({ error: 'Unauthorized' })\n    }\n\n    try {\n      const user = await verifyToken(token)\n      req.user = user\n      return handler(req, res)\n    } catch (error) {\n      return res.status(401).json({ error: 'Invalid token' })\n    }\n  }\n}\n\n\u002F\u002F Usage\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler has access to req.user\n})\n```\n\n## Database Patterns\n\n### Query Optimization\n\n```typescript\n\u002F\u002F PASS: GOOD: Select only needed columns\nconst { data } = await supabase\n  .from('markets')\n  .select('id, name, status, volume')\n  .eq('status', 'active')\n  .order('volume', { ascending: false })\n  .limit(10)\n\n\u002F\u002F FAIL: BAD: Select everything\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Query Prevention\n\n```typescript\n\u002F\u002F FAIL: BAD: N+1 query problem\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N queries\n}\n\n\u002F\u002F PASS: GOOD: Batch fetch\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 query\nconst creatorMap = new Map(creators.map(c => [c.id, c]))\n\nmarkets.forEach(market => {\n  market.creator = creatorMap.get(market.creator_id)\n})\n```\n\n### Transaction Pattern\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Use Supabase transaction\n  const { data, error } = await supabase.rpc('create_market_with_position', {\n    market_data: marketData,\n    position_data: positionData\n  })\n\n  if (error) throw new Error('Transaction failed')\n  return data\n}\n\n\u002F\u002F SQL function in Supabase\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Start transaction automatically\n  INSERT INTO markets VALUES (market_data);\n  INSERT INTO positions VALUES (position_data);\n  RETURN jsonb_build_object('success', true);\nEXCEPTION\n  WHEN OTHERS THEN\n    -- Rollback happens automatically\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Caching Strategies\n\n### Redis Caching Layer\n\n```typescript\nclass CachedMarketRepository implements MarketRepository {\n  constructor(\n    private baseRepo: MarketRepository,\n    private redis: RedisClient\n  ) {}\n\n  async findById(id: string): Promise\u003CMarket | null> {\n    \u002F\u002F Check cache first\n    const cached = await this.redis.get(`market:${id}`)\n\n    if (cached) {\n      return JSON.parse(cached)\n    }\n\n    \u002F\u002F Cache miss - fetch from database\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F Cache for 5 minutes\n      await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))\n    }\n\n    return market\n  }\n\n  async invalidateCache(id: string): Promise\u003Cvoid> {\n    await this.redis.del(`market:${id}`)\n  }\n}\n```\n\n### Cache-Aside Pattern\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Try cache\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - fetch from DB\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Update cache\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Error Handling Patterns\n\n### Centralized Error Handler\n\n```typescript\nclass ApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public message: string,\n    public isOperational = true\n  ) {\n    super(message)\n    Object.setPrototypeOf(this, ApiError.prototype)\n  }\n}\n\nexport function errorHandler(error: unknown, req: Request): Response {\n  if (error instanceof ApiError) {\n    return NextResponse.json({\n      success: false,\n      error: error.message\n    }, { status: error.statusCode })\n  }\n\n  if (error instanceof z.ZodError) {\n    return NextResponse.json({\n      success: false,\n      error: 'Validation failed',\n      details: error.errors\n    }, { status: 400 })\n  }\n\n  \u002F\u002F Log unexpected errors\n  console.error('Unexpected error:', error)\n\n  return NextResponse.json({\n    success: false,\n    error: 'Internal server error'\n  }, { status: 500 })\n}\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  try {\n    const data = await fetchData()\n    return NextResponse.json({ success: true, data })\n  } catch (error) {\n    return errorHandler(error, request)\n  }\n}\n```\n\n### Retry with Exponential Backoff\n\n```typescript\nasync function fetchWithRetry\u003CT>(\n  fn: () => Promise\u003CT>,\n  maxRetries = 3\n): Promise\u003CT> {\n  let lastError: Error\n\n  for (let i = 0; i \u003C maxRetries; i++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error as Error\n\n      if (i \u003C maxRetries - 1) {\n        \u002F\u002F Exponential backoff: 1s, 2s, 4s\n        const delay = Math.pow(2, i) * 1000\n        await new Promise(resolve => setTimeout(resolve, delay))\n      }\n    }\n  }\n\n  throw lastError!\n}\n\n\u002F\u002F Usage\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Authentication & Authorization\n\n### JWT Token Validation\n\n```typescript\nimport jwt from 'jsonwebtoken'\n\ninterface JWTPayload {\n  userId: string\n  email: string\n  role: 'admin' | 'user'\n}\n\nexport function verifyToken(token: string): JWTPayload {\n  try {\n    const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload\n    return payload\n  } catch (error) {\n    throw new ApiError(401, 'Invalid token')\n  }\n}\n\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get('authorization')?.replace('Bearer ', '')\n\n  if (!token) {\n    throw new ApiError(401, 'Missing authorization token')\n  }\n\n  return verifyToken(token)\n}\n\n\u002F\u002F Usage in API route\nexport async function GET(request: Request) {\n  const user = await requireAuth(request)\n\n  const data = await getDataForUser(user.userId)\n\n  return NextResponse.json({ success: true, data })\n}\n```\n\n### Role-Based Access Control\n\n```typescript\ntype Permission = 'read' | 'write' | 'delete' | 'admin'\n\ninterface User {\n  id: string\n  role: 'admin' | 'moderator' | 'user'\n}\n\nconst rolePermissions: Record\u003CUser['role'], Permission[]> = {\n  admin: ['read', 'write', 'delete', 'admin'],\n  moderator: ['read', 'write', 'delete'],\n  user: ['read', 'write']\n}\n\nexport function hasPermission(user: User, permission: Permission): boolean {\n  return rolePermissions[user.role].includes(permission)\n}\n\nexport function requirePermission(permission: Permission) {\n  return (handler: (request: Request, user: User) => Promise\u003CResponse>) => {\n    return async (request: Request) => {\n      const user = await requireAuth(request)\n\n      if (!hasPermission(user, permission)) {\n        throw new ApiError(403, 'Insufficient permissions')\n      }\n\n      return handler(request, user)\n    }\n  }\n}\n\n\u002F\u002F Usage - HOF wraps the handler\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler receives authenticated user with verified permission\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Simple In-Memory Rate Limiter\n\n```typescript\nclass RateLimiter {\n  private requests = new Map\u003Cstring, number[]>()\n\n  async checkLimit(\n    identifier: string,\n    maxRequests: number,\n    windowMs: number\n  ): Promise\u003Cboolean> {\n    const now = Date.now()\n    const requests = this.requests.get(identifier) || []\n\n    \u002F\u002F Remove old requests outside window\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit exceeded\n    }\n\n    \u002F\u002F Add current request\n    recentRequests.push(now)\n    this.requests.set(identifier, recentRequests)\n\n    return true\n  }\n}\n\nconst limiter = new RateLimiter()\n\nexport async function GET(request: Request) {\n  const ip = request.headers.get('x-forwarded-for') || 'unknown'\n\n  const allowed = await limiter.checkLimit(ip, 100, 60000)  \u002F\u002F 100 req\u002Fmin\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F Continue with request\n}\n```\n\n## Background Jobs & Queues\n\n### Simple Queue Pattern\n\n```typescript\nclass JobQueue\u003CT> {\n  private queue: T[] = []\n  private processing = false\n\n  async add(job: T): Promise\u003Cvoid> {\n    this.queue.push(job)\n\n    if (!this.processing) {\n      this.process()\n    }\n  }\n\n  private async process(): Promise\u003Cvoid> {\n    this.processing = true\n\n    while (this.queue.length > 0) {\n      const job = this.queue.shift()!\n\n      try {\n        await this.execute(job)\n      } catch (error) {\n        console.error('Job failed:', error)\n      }\n    }\n\n    this.processing = false\n  }\n\n  private async execute(job: T): Promise\u003Cvoid> {\n    \u002F\u002F Job execution logic\n  }\n}\n\n\u002F\u002F Usage for indexing markets\ninterface IndexJob {\n  marketId: string\n}\n\nconst indexQueue = new JobQueue\u003CIndexJob>()\n\nexport async function POST(request: Request) {\n  const { marketId } = await request.json()\n\n  \u002F\u002F Add to queue instead of blocking\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Logging & Monitoring\n\n### Structured Logging\n\n```typescript\ninterface LogContext {\n  userId?: string\n  requestId?: string\n  method?: string\n  path?: string\n  [key: string]: unknown\n}\n\nclass Logger {\n  log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {\n    const entry = {\n      timestamp: new Date().toISOString(),\n      level,\n      message,\n      ...context\n    }\n\n    console.log(JSON.stringify(entry))\n  }\n\n  info(message: string, context?: LogContext) {\n    this.log('info', message, context)\n  }\n\n  warn(message: string, context?: LogContext) {\n    this.log('warn', message, context)\n  }\n\n  error(message: string, error: Error, context?: LogContext) {\n    this.log('error', message, {\n      ...context,\n      error: error.message,\n      stack: error.stack\n    })\n  }\n}\n\nconst logger = new Logger()\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  const requestId = crypto.randomUUID()\n\n  logger.info('Fetching markets', {\n    requestId,\n    method: 'GET',\n    path: '\u002Fapi\u002Fmarkets'\n  })\n\n  try {\n    const markets = await fetchMarkets()\n    return NextResponse.json({ success: true, data: markets })\n  } catch (error) {\n    logger.error('Failed to fetch markets', error as Error, { requestId })\n    return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n  }\n}\n```\n\n**Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.\n","# Backend Development Patterns\n\nBackend architecture patterns and best practices for scalable server-side applications.\n\n## When to Activate\n\n- Designing REST or GraphQL API endpoints\n- Implementing repository, service, or controller layers\n- Optimizing database queries (N+1, indexing, connection pooling)\n- Adding caching (Redis, in-memory, HTTP cache headers)\n- Setting up background jobs or async processing\n- Structuring error handling and validation for APIs\n- Building middleware (auth, logging, rate limiting)\n\n## API Design Patterns\n\n### RESTful API Structure\n\n```typescript\n\u002F\u002F PASS: Resource-based URLs\nGET    \u002Fapi\u002Fmarkets                 # List resources\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Get single resource\nPOST   \u002Fapi\u002Fmarkets                 # Create resource\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Replace resource\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Update resource\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Delete resource\n\n\u002F\u002F PASS: Query parameters for filtering, sorting, pagination\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Pattern\n\n```typescript\n\u002F\u002F Abstract data access logic\ninterface MarketRepository {\n  findAll(filters?: MarketFilters): Promise\u003CMarket[]>\n  findById(id: string): Promise\u003CMarket | null>\n  create(data: CreateMarketDto): Promise\u003CMarket>\n  update(id: string, data: UpdateMarketDto): Promise\u003CMarket>\n  delete(id: string): Promise\u003Cvoid>\n}\n\nclass SupabaseMarketRepository implements MarketRepository {\n  async findAll(filters?: MarketFilters): Promise\u003CMarket[]> {\n    let query = supabase.from('markets').select('*')\n\n    if (filters?.status) {\n      query = query.eq('status', filters.status)\n    }\n\n    if (filters?.limit) {\n      query = query.limit(filters.limit)\n    }\n\n    const { data, error } = await query\n\n    if (error) throw new Error(error.message)\n    return data\n  }\n\n  \u002F\u002F Other methods...\n}\n```\n\n### Service Layer Pattern\n\n```typescript\n\u002F\u002F Business logic separated from data access\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F Business logic\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Fetch full data\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Sort by similarity\n    return markets.sort((a, b) => {\n      const scoreA = results.find(r => r.id === a.id)?.score || 0\n      const scoreB = results.find(r => r.id === b.id)?.score || 0\n      return scoreA - scoreB\n    })\n  }\n\n  private async vectorSearch(embedding: number[], limit: number) {\n    \u002F\u002F Vector search implementation\n  }\n}\n```\n\n### Middleware Pattern\n\n```typescript\n\u002F\u002F Request\u002Fresponse processing pipeline\nexport function withAuth(handler: NextApiHandler): NextApiHandler {\n  return async (req, res) => {\n    const token = req.headers.authorization?.replace('Bearer ', '')\n\n    if (!token) {\n      return res.status(401).json({ error: 'Unauthorized' })\n    }\n\n    try {\n      const user = await verifyToken(token)\n      req.user = user\n      return handler(req, res)\n    } catch (error) {\n      return res.status(401).json({ error: 'Invalid token' })\n    }\n  }\n}\n\n\u002F\u002F Usage\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler has access to req.user\n})\n```\n\n## Database Patterns\n\n### Query Optimization\n\n```typescript\n\u002F\u002F PASS: GOOD: Select only needed columns\nconst { data } = await supabase\n  .from('markets')\n  .select('id, name, status, volume')\n  .eq('status', 'active')\n  .order('volume', { ascending: false })\n  .limit(10)\n\n\u002F\u002F FAIL: BAD: Select everything\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Query Prevention\n\n```typescript\n\u002F\u002F FAIL: BAD: N+1 query problem\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N queries\n}\n\n\u002F\u002F PASS: GOOD: Batch fetch\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 query\nconst creatorMap = new Map(creators.map(c => [c.id, c]))\n\nmarkets.forEach(market => {\n  market.creator = creatorMap.get(market.creator_id)\n})\n```\n\n### Transaction Pattern\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Use Supabase transaction\n  const { data, error } = await supabase.rpc('create_market_with_position', {\n    market_data: marketData,\n    position_data: positionData\n  })\n\n  if (error) throw new Error('Transaction failed')\n  return data\n}\n\n\u002F\u002F SQL function in Supabase\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Start transaction automatically\n  INSERT INTO markets VALUES (market_data);\n  INSERT INTO positions VALUES (position_data);\n  RETURN jsonb_build_object('success', true);\nEXCEPTION\n  WHEN OTHERS THEN\n    -- Rollback happens automatically\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Caching Strategies\n\n### Redis Caching Layer\n\n```typescript\nclass CachedMarketRepository implements MarketRepository {\n  constructor(\n    private baseRepo: MarketRepository,\n    private redis: RedisClient\n  ) {}\n\n  async findById(id: string): Promise\u003CMarket | null> {\n    \u002F\u002F Check cache first\n    const cached = await this.redis.get(`market:${id}`)\n\n    if (cached) {\n      return JSON.parse(cached)\n    }\n\n    \u002F\u002F Cache miss - fetch from database\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F Cache for 5 minutes\n      await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))\n    }\n\n    return market\n  }\n\n  async invalidateCache(id: string): Promise\u003Cvoid> {\n    await this.redis.del(`market:${id}`)\n  }\n}\n```\n\n### Cache-Aside Pattern\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Try cache\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - fetch from DB\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Update cache\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Error Handling Patterns\n\n### Centralized Error Handler\n\n```typescript\nclass ApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public message: string,\n    public isOperational = true\n  ) {\n    super(message)\n    Object.setPrototypeOf(this, ApiError.prototype)\n  }\n}\n\nexport function errorHandler(error: unknown, req: Request): Response {\n  if (error instanceof ApiError) {\n    return NextResponse.json({\n      success: false,\n      error: error.message\n    }, { status: error.statusCode })\n  }\n\n  if (error instanceof z.ZodError) {\n    return NextResponse.json({\n      success: false,\n      error: 'Validation failed',\n      details: error.errors\n    }, { status: 400 })\n  }\n\n  \u002F\u002F Log unexpected errors\n  console.error('Unexpected error:', error)\n\n  return NextResponse.json({\n    success: false,\n    error: 'Internal server error'\n  }, { status: 500 })\n}\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  try {\n    const data = await fetchData()\n    return NextResponse.json({ success: true, data })\n  } catch (error) {\n    return errorHandler(error, request)\n  }\n}\n```\n\n### Retry with Exponential Backoff\n\n```typescript\nasync function fetchWithRetry\u003CT>(\n  fn: () => Promise\u003CT>,\n  maxRetries = 3\n): Promise\u003CT> {\n  let lastError: Error\n\n  for (let i = 0; i \u003C maxRetries; i++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error as Error\n\n      if (i \u003C maxRetries - 1) {\n        \u002F\u002F Exponential backoff: 1s, 2s, 4s\n        const delay = Math.pow(2, i) * 1000\n        await new Promise(resolve => setTimeout(resolve, delay))\n      }\n    }\n  }\n\n  throw lastError!\n}\n\n\u002F\u002F Usage\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Authentication & Authorization\n\n### JWT Token Validation\n\n```typescript\nimport jwt from 'jsonwebtoken'\n\ninterface JWTPayload {\n  userId: string\n  email: string\n  role: 'admin' | 'user'\n}\n\nexport function verifyToken(token: string): JWTPayload {\n  try {\n    const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload\n    return payload\n  } catch (error) {\n    throw new ApiError(401, 'Invalid token')\n  }\n}\n\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get('authorization')?.replace('Bearer ', '')\n\n  if (!token) {\n    throw new ApiError(401, 'Missing authorization token')\n  }\n\n  return verifyToken(token)\n}\n\n\u002F\u002F Usage in API route\nexport async function GET(request: Request) {\n  const user = await requireAuth(request)\n\n  const data = await getDataForUser(user.userId)\n\n  return NextResponse.json({ success: true, data })\n}\n```\n\n### Role-Based Access Control\n\n```typescript\ntype Permission = 'read' | 'write' | 'delete' | 'admin'\n\ninterface User {\n  id: string\n  role: 'admin' | 'moderator' | 'user'\n}\n\nconst rolePermissions: Record\u003CUser['role'], Permission[]> = {\n  admin: ['read', 'write', 'delete', 'admin'],\n  moderator: ['read', 'write', 'delete'],\n  user: ['read', 'write']\n}\n\nexport function hasPermission(user: User, permission: Permission): boolean {\n  return rolePermissions[user.role].includes(permission)\n}\n\nexport function requirePermission(permission: Permission) {\n  return (handler: (request: Request, user: User) => Promise\u003CResponse>) => {\n    return async (request: Request) => {\n      const user = await requireAuth(request)\n\n      if (!hasPermission(user, permission)) {\n        throw new ApiError(403, 'Insufficient permissions')\n      }\n\n      return handler(request, user)\n    }\n  }\n}\n\n\u002F\u002F Usage - HOF wraps the handler\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler receives authenticated user with verified permission\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Simple In-Memory Rate Limiter\n\n```typescript\nclass RateLimiter {\n  private requests = new Map\u003Cstring, number[]>()\n\n  async checkLimit(\n    identifier: string,\n    maxRequests: number,\n    windowMs: number\n  ): Promise\u003Cboolean> {\n    const now = Date.now()\n    const requests = this.requests.get(identifier) || []\n\n    \u002F\u002F Remove old requests outside window\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit exceeded\n    }\n\n    \u002F\u002F Add current request\n    recentRequests.push(now)\n    this.requests.set(identifier, recentRequests)\n\n    return true\n  }\n}\n\nconst limiter = new RateLimiter()\n\nexport async function GET(request: Request) {\n  const ip = request.headers.get('x-forwarded-for') || 'unknown'\n\n  const allowed = await limiter.checkLimit(ip, 100, 60000)  \u002F\u002F 100 req\u002Fmin\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F Continue with request\n}\n```\n\n## Background Jobs & Queues\n\n### Simple Queue Pattern\n\n```typescript\nclass JobQueue\u003CT> {\n  private queue: T[] = []\n  private processing = false\n\n  async add(job: T): Promise\u003Cvoid> {\n    this.queue.push(job)\n\n    if (!this.processing) {\n      this.process()\n    }\n  }\n\n  private async process(): Promise\u003Cvoid> {\n    this.processing = true\n\n    while (this.queue.length > 0) {\n      const job = this.queue.shift()!\n\n      try {\n        await this.execute(job)\n      } catch (error) {\n        console.error('Job failed:', error)\n      }\n    }\n\n    this.processing = false\n  }\n\n  private async execute(job: T): Promise\u003Cvoid> {\n    \u002F\u002F Job execution logic\n  }\n}\n\n\u002F\u002F Usage for indexing markets\ninterface IndexJob {\n  marketId: string\n}\n\nconst indexQueue = new JobQueue\u003CIndexJob>()\n\nexport async function POST(request: Request) {\n  const { marketId } = await request.json()\n\n  \u002F\u002F Add to queue instead of blocking\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Logging & Monitoring\n\n### Structured Logging\n\n```typescript\ninterface LogContext {\n  userId?: string\n  requestId?: string\n  method?: string\n  path?: string\n  [key: string]: unknown\n}\n\nclass Logger {\n  log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {\n    const entry = {\n      timestamp: new Date().toISOString(),\n      level,\n      message,\n      ...context\n    }\n\n    console.log(JSON.stringify(entry))\n  }\n\n  info(message: string, context?: LogContext) {\n    this.log('info', message, context)\n  }\n\n  warn(message: string, context?: LogContext) {\n    this.log('warn', message, context)\n  }\n\n  error(message: string, error: Error, context?: LogContext) {\n    this.log('error', message, {\n      ...context,\n      error: error.message,\n      stack: error.stack\n    })\n  }\n}\n\nconst logger = new Logger()\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  const requestId = crypto.randomUUID()\n\n  logger.info('Fetching markets', {\n    requestId,\n    method: 'GET',\n    path: '\u002Fapi\u002Fmarkets'\n  })\n\n  try {\n    const markets = await fetchMarkets()\n    return NextResponse.json({ success: true, data: markets })\n  } catch (error) {\n    logger.error('Failed to fetch markets', error as Error, { requestId })\n    return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n  }\n}\n```\n\n**Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.\n",{"name":5,"license":14,"description":7},"main","4c174e06a831864e98c30f630a7aa6c04738b094","skills\u002F_intake\u002Fgithub\u002Faffaan-m\u002FECC\u002Fbackend-patterns","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules","https:\u002F\u002Fgithub.com\u002Fmhyahya854","2026-11-06 02:03:37",{"source":8,"skillName":5,"commands":30,"prompt":40,"zipAvailable":41},[31,34,37],{"tool":32,"command":33},"npx","npx skills add mhyahya854\u002FAI-Second-Brain_Universal-Rules --skill backend-patterns",{"tool":35,"command":36},"bunx","bunx skills add mhyahya854\u002FAI-Second-Brain_Universal-Rules --skill backend-patterns",{"tool":38,"command":39},"pnpm","pnpm dlx skills add mhyahya854\u002FAI-Second-Brain_Universal-Rules --skill backend-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Faffaan-m\u002FECC\u002Fbackend-patterns\u002FSKILL.md",true,[43],{"path":44,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":47,"sourceHtmlUrl":48},"agents\u002Fopenai.yaml","REFERENCE","参考文档",266,"https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Faffaan-m\u002FECC\u002Fbackend-patterns\u002Fagents\u002Fopenai.yaml",[50,58,66,74,81,88],{"skillNo":51,"name":52,"nameZh":6,"description":53,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":54,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":18},"01M7EX4T721AAH60R0239P8WBZ","frontend-slides","Create stunning, animation-rich HTML presentations from scratch or by converting PowerPoint files. Use when the user wants to build a presentation, convert a PPT\u002FPPTX to web, or create slides for a talk\u002Fpitch. Helps non-designers discover their aesthetic through visual exploration rather than abstract choices.","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fzarazhangrui\u002Ffrontend-slides\u002Ffrontend-slides\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fzarazhangrui\u002Ffrontend-slides\u002Ffrontend-slides\u002FSKILL.md",[],[],{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":62,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":18},"01M7EX495RSHTTCEJVX7C83FA3","design-dna","Extract, define, and apply design DNA across three dimensions: design system (tokens), design style (qualitative feel), and visual effects (Canvas, WebGL, 3D, particles, shaders, scroll effects, etc.). Use this skill when: (1) a user wants to see the full 3-dimension design structure\u002Fschema, (2) a user provides images, screenshots, or URLs of reference designs and wants them analyzed into a structured JSON profile covering all three dimensions, (3) a user has a Design DNA JSON and content and wants a design generated from it, or (4) any combination of these phases. Triggers on \"design DNA\", \"extract design style\", \"analyze design\", \"design tokens from reference\", \"generate design from JSON\", \"design system from screenshot\", \"design profile\", \"style guide JSON\", \"visual effects analysis\", \"design with effects\", \"3d design analysis\".","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fzanwei\u002Fdesign-dna\u002Fdesign-dna\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fzanwei\u002Fdesign-dna\u002Fdesign-dna\u002FSKILL.md",[],[],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":70,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":18},"01M7EX45RF2XZKRC3KDJDTT1PH","wireframe","Generate JSON wireframe with HTML preview","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fyhassy\u002Fwireframe-skill\u002Fwireframe-skill\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fyhassy\u002Fwireframe-skill\u002Fwireframe-skill\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":18},"01M7EWZEM3MHD48AYSYFR2C9JP","social-publishing","Schedule and publish social media posts across 13 platforms (X, LinkedIn, Instagram, Facebook Pages, TikTok, Discord, Telegram, YouTube, Reddit, WordPress, Pinterest) via the SocialClaw API. Use when the user wants to publish, schedule, or manage social media content programmatically. Requires SOCIALCLAW_API_KEY.","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fwshobson\u002Fagents\u002Fsocial-publishing\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":18},"01M7EWKDEK9840C728VXT78EQ9","hermes-tweet","Install and operate Hermes Tweet, a Hermes Agent plugin for X\u002FTwitter research, timeline reading, tweet analysis, and approval-gated private or state-changing operations. Use this skill when installing Hermes Tweet, researching X\u002FTwitter accounts, monitoring launch signals, investigating mentions, auditing giveaways, or preparing gated X operations. Use proactively when a Hermes Agent workflow needs current X\u002FTwitter context. Requires XQUIK_API_KEY for read and action tools.","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fwshobson\u002Fagents\u002Fhermes-tweet\u002FSKILL.md",[],[],{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":18},"01M7EWASXP3NZWW95CJPT2CRWN","refactoring-ui","Audit and fix visual hierarchy, spacing, color, and depth in web UIs. Use when the user mentions \"my UI looks off\" (or amateur\u002Funprofessional), \"fix the design\", \"Tailwind styling\", \"color palette\", \"visual hierarchy\", \"design system\", \"spacing scale\", or \"component styling\". Also trigger when building consistent design tokens, creating dark mode themes, improving data-visualization clarity, or polishing UI details before launch. Covers grayscale-first workflow, constrained design scales, shadows, and component styling. For typeface selection, see web-typography. For usability audits, see ux-heuristics.","https:\u002F\u002Fgithub.com\u002Fmhyahya854\u002FAI-Second-Brain_Universal-Rules\u002Fblob\u002Fmain\u002Fskills\u002F_intake\u002Fgithub\u002Fwondelai\u002Fskills\u002Frefactoring-ui\u002FSKILL.md",[],[]]