[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D87W4GT4SWRBS9T6RAKMXJ":3,"skill-same:01M6D87W4GT4SWRBS9T6RAKMXJ":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":53,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":56,"ownerDescription":57,"updatedAt":58,"install":59,"resources":72},"01M6D87W4GT4SWRBS9T6RAKMXJ","springboot-patterns",null,"Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging. Use for Java Spring Boot backend work.","oabdelmaksoud\u002FSuperClaw","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D5CW1RHNSKCJR85GJACBFT",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fspringboot-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"patterns","springboot patterns","rest api","design","caching","java spring","async","backend","use","work","spring","access","api","REST","data","services","spring boot","java","boot","architecture","2026-11-10 10:12:30",false,"---\nname: springboot-patterns\ndescription: Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging. Use for Java Spring Boot backend work.\norigin: ECC\n---\n\n# Spring Boot Development Patterns\n\nSpring Boot architecture and API patterns for scalable, production-grade services.\n\n## When to Activate\n\n- Building REST APIs with Spring MVC or WebFlux\n- Structuring controller → service → repository layers\n- Configuring Spring Data JPA, caching, or async processing\n- Adding validation, exception handling, or pagination\n- Setting up profiles for dev\u002Fstaging\u002Fproduction environments\n- Implementing event-driven patterns with Spring Events or Kafka\n\n## REST API Structure\n\n```java\n@RestController\n@RequestMapping(\"\u002Fapi\u002Fmarkets\")\n@Validated\nclass MarketController {\n  private final MarketService marketService;\n\n  MarketController(MarketService marketService) {\n    this.marketService = marketService;\n  }\n\n  @GetMapping\n  ResponseEntity\u003CPage\u003CMarketResponse>> list(\n      @RequestParam(defaultValue = \"0\") int page,\n      @RequestParam(defaultValue = \"20\") int size) {\n    Page\u003CMarket> markets = marketService.list(PageRequest.of(page, size));\n    return ResponseEntity.ok(markets.map(MarketResponse::from));\n  }\n\n  @PostMapping\n  ResponseEntity\u003CMarketResponse> create(@Valid @RequestBody CreateMarketRequest request) {\n    Market market = marketService.create(request);\n    return ResponseEntity.status(HttpStatus.CREATED).body(MarketResponse.from(market));\n  }\n}\n```\n\n## Repository Pattern (Spring Data JPA)\n\n```java\npublic interface MarketRepository extends JpaRepository\u003CMarketEntity, Long> {\n  @Query(\"select m from MarketEntity m where m.status = :status order by m.volume desc\")\n  List\u003CMarketEntity> findActive(@Param(\"status\") MarketStatus status, Pageable pageable);\n}\n```\n\n## Service Layer with Transactions\n\n```java\n@Service\npublic class MarketService {\n  private final MarketRepository repo;\n\n  public MarketService(MarketRepository repo) {\n    this.repo = repo;\n  }\n\n  @Transactional\n  public Market create(CreateMarketRequest request) {\n    MarketEntity entity = MarketEntity.from(request);\n    MarketEntity saved = repo.save(entity);\n    return Market.from(saved);\n  }\n}\n```\n\n## DTOs and Validation\n\n```java\npublic record CreateMarketRequest(\n    @NotBlank @Size(max = 200) String name,\n    @NotBlank @Size(max = 2000) String description,\n    @NotNull @FutureOrPresent Instant endDate,\n    @NotEmpty List\u003C@NotBlank String> categories) {}\n\npublic record MarketResponse(Long id, String name, MarketStatus status) {\n  static MarketResponse from(Market market) {\n    return new MarketResponse(market.id(), market.name(), market.status());\n  }\n}\n```\n\n## Exception Handling\n\n```java\n@ControllerAdvice\nclass GlobalExceptionHandler {\n  @ExceptionHandler(MethodArgumentNotValidException.class)\n  ResponseEntity\u003CApiError> handleValidation(MethodArgumentNotValidException ex) {\n    String message = ex.getBindingResult().getFieldErrors().stream()\n        .map(e -> e.getField() + \": \" + e.getDefaultMessage())\n        .collect(Collectors.joining(\", \"));\n    return ResponseEntity.badRequest().body(ApiError.validation(message));\n  }\n\n  @ExceptionHandler(AccessDeniedException.class)\n  ResponseEntity\u003CApiError> handleAccessDenied() {\n    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ApiError.of(\"Forbidden\"));\n  }\n\n  @ExceptionHandler(Exception.class)\n  ResponseEntity\u003CApiError> handleGeneric(Exception ex) {\n    \u002F\u002F Log unexpected errors with stack traces\n    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)\n        .body(ApiError.of(\"Internal server error\"));\n  }\n}\n```\n\n## Caching\n\nRequires `@EnableCaching` on a configuration class.\n\n```java\n@Service\npublic class MarketCacheService {\n  private final MarketRepository repo;\n\n  public MarketCacheService(MarketRepository repo) {\n    this.repo = repo;\n  }\n\n  @Cacheable(value = \"market\", key = \"#id\")\n  public Market getById(Long id) {\n    return repo.findById(id)\n        .map(Market::from)\n        .orElseThrow(() -> new EntityNotFoundException(\"Market not found\"));\n  }\n\n  @CacheEvict(value = \"market\", key = \"#id\")\n  public void evict(Long id) {}\n}\n```\n\n## Async Processing\n\nRequires `@EnableAsync` on a configuration class.\n\n```java\n@Service\npublic class NotificationService {\n  @Async\n  public CompletableFuture\u003CVoid> sendAsync(Notification notification) {\n    \u002F\u002F send email\u002FSMS\n    return CompletableFuture.completedFuture(null);\n  }\n}\n```\n\n## Logging (SLF4J)\n\n```java\n@Service\npublic class ReportService {\n  private static final Logger log = LoggerFactory.getLogger(ReportService.class);\n\n  public Report generate(Long marketId) {\n    log.info(\"generate_report marketId={}\", marketId);\n    try {\n      \u002F\u002F logic\n    } catch (Exception ex) {\n      log.error(\"generate_report_failed marketId={}\", marketId, ex);\n      throw ex;\n    }\n    return new Report();\n  }\n}\n```\n\n## Middleware \u002F Filters\n\n```java\n@Component\npublic class RequestLoggingFilter extends OncePerRequestFilter {\n  private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);\n\n  @Override\n  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,\n      FilterChain filterChain) throws ServletException, IOException {\n    long start = System.currentTimeMillis();\n    try {\n      filterChain.doFilter(request, response);\n    } finally {\n      long duration = System.currentTimeMillis() - start;\n      log.info(\"req method={} uri={} status={} durationMs={}\",\n          request.getMethod(), request.getRequestURI(), response.getStatus(), duration);\n    }\n  }\n}\n```\n\n## Pagination and Sorting\n\n```java\nPageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by(\"createdAt\").descending());\nPage\u003CMarket> results = marketService.list(page);\n```\n\n## Error-Resilient External Calls\n\n```java\npublic \u003CT> T withRetry(Supplier\u003CT> supplier, int maxRetries) {\n  int attempts = 0;\n  while (true) {\n    try {\n      return supplier.get();\n    } catch (Exception ex) {\n      attempts++;\n      if (attempts >= maxRetries) {\n        throw ex;\n      }\n      try {\n        Thread.sleep((long) Math.pow(2, attempts) * 100L);\n      } catch (InterruptedException ie) {\n        Thread.currentThread().interrupt();\n        throw ex;\n      }\n    }\n  }\n}\n```\n\n## Rate Limiting (Filter + Bucket4j)\n\n**Security Note**: The `X-Forwarded-For` header is untrusted by default because clients can spoof it.\nOnly use forwarded headers when:\n1. Your app is behind a trusted reverse proxy (nginx, AWS ALB, etc.)\n2. You have registered `ForwardedHeaderFilter` as a bean\n3. You have configured `server.forward-headers-strategy=NATIVE` or `FRAMEWORK` in application properties\n4. Your proxy is configured to overwrite (not append to) the `X-Forwarded-For` header\n\nWhen `ForwardedHeaderFilter` is properly configured, `request.getRemoteAddr()` will automatically\nreturn the correct client IP from the forwarded headers. Without this configuration, use\n`request.getRemoteAddr()` directly—it returns the immediate connection IP, which is the only\ntrustworthy value.\n\n```java\n@Component\npublic class RateLimitFilter extends OncePerRequestFilter {\n  private final Map\u003CString, Bucket> buckets = new ConcurrentHashMap\u003C>();\n\n  \u002F*\n   * SECURITY: This filter uses request.getRemoteAddr() to identify clients for rate limiting.\n   *\n   * If your application is behind a reverse proxy (nginx, AWS ALB, etc.), you MUST configure\n   * Spring to handle forwarded headers properly for accurate client IP detection:\n   *\n   * 1. Set server.forward-headers-strategy=NATIVE (for cloud platforms) or FRAMEWORK in\n   *    application.properties\u002Fyaml\n   * 2. If using FRAMEWORK strategy, register ForwardedHeaderFilter:\n   *\n   *    @Bean\n   *    ForwardedHeaderFilter forwardedHeaderFilter() {\n   *        return new ForwardedHeaderFilter();\n   *    }\n   *\n   * 3. Ensure your proxy overwrites (not appends) the X-Forwarded-For header to prevent spoofing\n   * 4. Configure server.tomcat.remoteip.trusted-proxies or equivalent for your container\n   *\n   * Without this configuration, request.getRemoteAddr() returns the proxy IP, not the client IP.\n   * Do NOT read X-Forwarded-For directly—it is trivially spoofable without trusted proxy handling.\n   *\u002F\n  @Override\n  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,\n      FilterChain filterChain) throws ServletException, IOException {\n    \u002F\u002F Use getRemoteAddr() which returns the correct client IP when ForwardedHeaderFilter\n    \u002F\u002F is configured, or the direct connection IP otherwise. Never trust X-Forwarded-For\n    \u002F\u002F headers directly without proper proxy configuration.\n    String clientIp = request.getRemoteAddr();\n\n    Bucket bucket = buckets.computeIfAbsent(clientIp,\n        k -> Bucket.builder()\n            .addLimit(Bandwidth.classic(100, Refill.greedy(100, Duration.ofMinutes(1))))\n            .build());\n\n    if (bucket.tryConsume(1)) {\n      filterChain.doFilter(request, response);\n    } else {\n      response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());\n    }\n  }\n}\n```\n\n## Background Jobs\n\nUse Spring’s `@Scheduled` or integrate with queues (e.g., Kafka, SQS, RabbitMQ). Keep handlers idempotent and observable.\n\n## Observability\n\n- Structured logging (JSON) via Logback encoder\n- Metrics: Micrometer + Prometheus\u002FOTel\n- Tracing: Micrometer Tracing with OpenTelemetry or Brave backend\n\n## Production Defaults\n\n- Prefer constructor injection, avoid field injection\n- Enable `spring.mvc.problemdetails.enabled=true` for RFC 7807 errors (Spring Boot 3+)\n- Configure HikariCP pool sizes for workload, set timeouts\n- Use `@Transactional(readOnly = true)` for queries\n- Enforce null-safety via `@NonNull` and `Optional` where appropriate\n\n**Remember**: Keep controllers thin, services focused, repositories simple, and errors handled centrally. Optimize for maintainability and testability.\n","# Spring Boot Development Patterns\n\nSpring Boot architecture and API patterns for scalable, production-grade services.\n\n## When to Activate\n\n- Building REST APIs with Spring MVC or WebFlux\n- Structuring controller → service → repository layers\n- Configuring Spring Data JPA, caching, or async processing\n- Adding validation, exception handling, or pagination\n- Setting up profiles for dev\u002Fstaging\u002Fproduction environments\n- Implementing event-driven patterns with Spring Events or Kafka\n\n## REST API Structure\n\n```java\n@RestController\n@RequestMapping(\"\u002Fapi\u002Fmarkets\")\n@Validated\nclass MarketController {\n  private final MarketService marketService;\n\n  MarketController(MarketService marketService) {\n    this.marketService = marketService;\n  }\n\n  @GetMapping\n  ResponseEntity\u003CPage\u003CMarketResponse>> list(\n      @RequestParam(defaultValue = \"0\") int page,\n      @RequestParam(defaultValue = \"20\") int size) {\n    Page\u003CMarket> markets = marketService.list(PageRequest.of(page, size));\n    return ResponseEntity.ok(markets.map(MarketResponse::from));\n  }\n\n  @PostMapping\n  ResponseEntity\u003CMarketResponse> create(@Valid @RequestBody CreateMarketRequest request) {\n    Market market = marketService.create(request);\n    return ResponseEntity.status(HttpStatus.CREATED).body(MarketResponse.from(market));\n  }\n}\n```\n\n## Repository Pattern (Spring Data JPA)\n\n```java\npublic interface MarketRepository extends JpaRepository\u003CMarketEntity, Long> {\n  @Query(\"select m from MarketEntity m where m.status = :status order by m.volume desc\")\n  List\u003CMarketEntity> findActive(@Param(\"status\") MarketStatus status, Pageable pageable);\n}\n```\n\n## Service Layer with Transactions\n\n```java\n@Service\npublic class MarketService {\n  private final MarketRepository repo;\n\n  public MarketService(MarketRepository repo) {\n    this.repo = repo;\n  }\n\n  @Transactional\n  public Market create(CreateMarketRequest request) {\n    MarketEntity entity = MarketEntity.from(request);\n    MarketEntity saved = repo.save(entity);\n    return Market.from(saved);\n  }\n}\n```\n\n## DTOs and Validation\n\n```java\npublic record CreateMarketRequest(\n    @NotBlank @Size(max = 200) String name,\n    @NotBlank @Size(max = 2000) String description,\n    @NotNull @FutureOrPresent Instant endDate,\n    @NotEmpty List\u003C@NotBlank String> categories) {}\n\npublic record MarketResponse(Long id, String name, MarketStatus status) {\n  static MarketResponse from(Market market) {\n    return new MarketResponse(market.id(), market.name(), market.status());\n  }\n}\n```\n\n## Exception Handling\n\n```java\n@ControllerAdvice\nclass GlobalExceptionHandler {\n  @ExceptionHandler(MethodArgumentNotValidException.class)\n  ResponseEntity\u003CApiError> handleValidation(MethodArgumentNotValidException ex) {\n    String message = ex.getBindingResult().getFieldErrors().stream()\n        .map(e -> e.getField() + \": \" + e.getDefaultMessage())\n        .collect(Collectors.joining(\", \"));\n    return ResponseEntity.badRequest().body(ApiError.validation(message));\n  }\n\n  @ExceptionHandler(AccessDeniedException.class)\n  ResponseEntity\u003CApiError> handleAccessDenied() {\n    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ApiError.of(\"Forbidden\"));\n  }\n\n  @ExceptionHandler(Exception.class)\n  ResponseEntity\u003CApiError> handleGeneric(Exception ex) {\n    \u002F\u002F Log unexpected errors with stack traces\n    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)\n        .body(ApiError.of(\"Internal server error\"));\n  }\n}\n```\n\n## Caching\n\nRequires `@EnableCaching` on a configuration class.\n\n```java\n@Service\npublic class MarketCacheService {\n  private final MarketRepository repo;\n\n  public MarketCacheService(MarketRepository repo) {\n    this.repo = repo;\n  }\n\n  @Cacheable(value = \"market\", key = \"#id\")\n  public Market getById(Long id) {\n    return repo.findById(id)\n        .map(Market::from)\n        .orElseThrow(() -> new EntityNotFoundException(\"Market not found\"));\n  }\n\n  @CacheEvict(value = \"market\", key = \"#id\")\n  public void evict(Long id) {}\n}\n```\n\n## Async Processing\n\nRequires `@EnableAsync` on a configuration class.\n\n```java\n@Service\npublic class NotificationService {\n  @Async\n  public CompletableFuture\u003CVoid> sendAsync(Notification notification) {\n    \u002F\u002F send email\u002FSMS\n    return CompletableFuture.completedFuture(null);\n  }\n}\n```\n\n## Logging (SLF4J)\n\n```java\n@Service\npublic class ReportService {\n  private static final Logger log = LoggerFactory.getLogger(ReportService.class);\n\n  public Report generate(Long marketId) {\n    log.info(\"generate_report marketId={}\", marketId);\n    try {\n      \u002F\u002F logic\n    } catch (Exception ex) {\n      log.error(\"generate_report_failed marketId={}\", marketId, ex);\n      throw ex;\n    }\n    return new Report();\n  }\n}\n```\n\n## Middleware \u002F Filters\n\n```java\n@Component\npublic class RequestLoggingFilter extends OncePerRequestFilter {\n  private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);\n\n  @Override\n  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,\n      FilterChain filterChain) throws ServletException, IOException {\n    long start = System.currentTimeMillis();\n    try {\n      filterChain.doFilter(request, response);\n    } finally {\n      long duration = System.currentTimeMillis() - start;\n      log.info(\"req method={} uri={} status={} durationMs={}\",\n          request.getMethod(), request.getRequestURI(), response.getStatus(), duration);\n    }\n  }\n}\n```\n\n## Pagination and Sorting\n\n```java\nPageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by(\"createdAt\").descending());\nPage\u003CMarket> results = marketService.list(page);\n```\n\n## Error-Resilient External Calls\n\n```java\npublic \u003CT> T withRetry(Supplier\u003CT> supplier, int maxRetries) {\n  int attempts = 0;\n  while (true) {\n    try {\n      return supplier.get();\n    } catch (Exception ex) {\n      attempts++;\n      if (attempts >= maxRetries) {\n        throw ex;\n      }\n      try {\n        Thread.sleep((long) Math.pow(2, attempts) * 100L);\n      } catch (InterruptedException ie) {\n        Thread.currentThread().interrupt();\n        throw ex;\n      }\n    }\n  }\n}\n```\n\n## Rate Limiting (Filter + Bucket4j)\n\n**Security Note**: The `X-Forwarded-For` header is untrusted by default because clients can spoof it.\nOnly use forwarded headers when:\n1. Your app is behind a trusted reverse proxy (nginx, AWS ALB, etc.)\n2. You have registered `ForwardedHeaderFilter` as a bean\n3. You have configured `server.forward-headers-strategy=NATIVE` or `FRAMEWORK` in application properties\n4. Your proxy is configured to overwrite (not append to) the `X-Forwarded-For` header\n\nWhen `ForwardedHeaderFilter` is properly configured, `request.getRemoteAddr()` will automatically\nreturn the correct client IP from the forwarded headers. Without this configuration, use\n`request.getRemoteAddr()` directly—it returns the immediate connection IP, which is the only\ntrustworthy value.\n\n```java\n@Component\npublic class RateLimitFilter extends OncePerRequestFilter {\n  private final Map\u003CString, Bucket> buckets = new ConcurrentHashMap\u003C>();\n\n  \u002F*\n   * SECURITY: This filter uses request.getRemoteAddr() to identify clients for rate limiting.\n   *\n   * If your application is behind a reverse proxy (nginx, AWS ALB, etc.), you MUST configure\n   * Spring to handle forwarded headers properly for accurate client IP detection:\n   *\n   * 1. Set server.forward-headers-strategy=NATIVE (for cloud platforms) or FRAMEWORK in\n   *    application.properties\u002Fyaml\n   * 2. If using FRAMEWORK strategy, register ForwardedHeaderFilter:\n   *\n   *    @Bean\n   *    ForwardedHeaderFilter forwardedHeaderFilter() {\n   *        return new ForwardedHeaderFilter();\n   *    }\n   *\n   * 3. Ensure your proxy overwrites (not appends) the X-Forwarded-For header to prevent spoofing\n   * 4. Configure server.tomcat.remoteip.trusted-proxies or equivalent for your container\n   *\n   * Without this configuration, request.getRemoteAddr() returns the proxy IP, not the client IP.\n   * Do NOT read X-Forwarded-For directly—it is trivially spoofable without trusted proxy handling.\n   *\u002F\n  @Override\n  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,\n      FilterChain filterChain) throws ServletException, IOException {\n    \u002F\u002F Use getRemoteAddr() which returns the correct client IP when ForwardedHeaderFilter\n    \u002F\u002F is configured, or the direct connection IP otherwise. Never trust X-Forwarded-For\n    \u002F\u002F headers directly without proper proxy configuration.\n    String clientIp = request.getRemoteAddr();\n\n    Bucket bucket = buckets.computeIfAbsent(clientIp,\n        k -> Bucket.builder()\n            .addLimit(Bandwidth.classic(100, Refill.greedy(100, Duration.ofMinutes(1))))\n            .build());\n\n    if (bucket.tryConsume(1)) {\n      filterChain.doFilter(request, response);\n    } else {\n      response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());\n    }\n  }\n}\n```\n\n## Background Jobs\n\nUse Spring’s `@Scheduled` or integrate with queues (e.g., Kafka, SQS, RabbitMQ). Keep handlers idempotent and observable.\n\n## Observability\n\n- Structured logging (JSON) via Logback encoder\n- Metrics: Micrometer + Prometheus\u002FOTel\n- Tracing: Micrometer Tracing with OpenTelemetry or Brave backend\n\n## Production Defaults\n\n- Prefer constructor injection, avoid field injection\n- Enable `spring.mvc.problemdetails.enabled=true` for RFC 7807 errors (Spring Boot 3+)\n- Configure HikariCP pool sizes for workload, set timeouts\n- Use `@Transactional(readOnly = true)` for queries\n- Enforce null-safety via `@NonNull` and `Optional` where appropriate\n\n**Remember**: Keep controllers thin, services focused, repositories simple, and errors handled centrally. Optimize for maintainability and testability.\n",{"name":5,"origin":49,"description":7},"ECC","main","7b610356e36623652299fa2acb477ff821b1d920","upstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fspringboot-patterns",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:12:53",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add oabdelmaksoud\u002FSuperClaw --skill springboot-patterns",{"tool":65,"command":66},"bunx","bunx skills add oabdelmaksoud\u002FSuperClaw --skill springboot-patterns",{"tool":68,"command":69},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FSuperClaw --skill springboot-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fspringboot-patterns\u002FSKILL.md",true,[73],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"agents\u002Fopenai.yaml","REFERENCE","参考文档",82,"https:\u002F\u002Fgithub.com\u002Fnexuslinkproductions\u002Fyuri-os\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fcodebase-to-course\u002Fagents\u002Fopenai.yaml",[80,99,113,143,167,186],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":89,"publishedAt":44},"01M6D88QCPTBZVCRED0NZ1Y8K8","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[86],{"categoryNo":87,"categoryName":88,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[90,91,92,93,94,95,96,97,98],"translate","doc","visa doc translate","translation","application","create","images","PDF","documents",{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":44},"01M6D88NBM95T3TFM50CYYAP65","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[106,107,108,109,110,111,112],"verification","loop","verification loop","sessions","code","claude code sessions","system",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":130,"publishedAt":44},"01M6D88JFZ2P996GVRHJNSZSTM","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[119,122,125],{"categoryNo":120,"categoryName":121,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":123,"categoryName":124,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":126,"categoryName":127,"taxonomyType":128,"taxonomyTypeDesc":129},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[131,132,133,134,135,136,110,137,32,138,139,140,141,142],"tdd","workflow","tdd workflow","e2e tests","e2e","integration","development","test","refactoring","coverage","tests","writing",{"skillNo":144,"name":145,"nameZh":6,"description":146,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":149,"publishedAt":44},"01M6D88FTHRRSVJMXF2G7MQAK3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[24,150,151,43,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166],"swiftui","swiftui patterns","macos","performance","state management","best practices","state","ui","Optimization","ios","architecture patterns","Composition","performance optimization","view","management","swiftui architecture","navigation",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":174,"publishedAt":44},"01M6D88D527QTQT9DKHTRFN6EA","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[173],{"categoryNo":120,"categoryName":121,"taxonomyType":21,"taxonomyTypeDesc":22},[175,176,177,178,110,179,180,181,182,112,183,184,185],"swift protocol di testing","protocol","swift","testing","protocols","file","network","injection","dependency","swift testing","dependency injection",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":192,"publishedAt":44},"01M6D88AJW8H2QNWSW5ZY82R43","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[193,194,177,195,196,50],"concurrency","swift concurrency","swift concurrency 6 2","default"]