Skip to content
Content
Skill

/api-architect

The hub skill for all API/backend architecture in Webiny. Covers architecture overview, Services vs UseCases, feature naming and organization, feature structure templates, DI decision tree, anti-patterns, createFeature, createAbstraction, container registration, domain errors,

BOOST
From plugin
webiny-js
8k76 skills3 MCP
Install
$ npx -y skills add webiny/webiny-js --skill api-architect --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/api-architect

Context preview

The summary Claude sees to decide when to auto-load this skill.

The hub skill for all API/backend architecture in Webiny. Covers architecture overview, Services vs UseCases, feature naming and organization, feature structure templates, DI decision tree, anti-patterns, createFeature, createAbstraction, container registration, domain errors,

SKILL.md

api-architect.SKILL.md
name: webiny-api-architect
description: >
  The hub skill for all API/backend architecture in Webiny. Covers architecture overview,
  Services vs UseCases, feature naming and organization, feature structure templates,
  DI decision tree, anti-patterns, createFeature, createAbstraction, container registration,
  domain errors, entity patterns, naming conventions, scoping rules, and code conventions.
  Use this skill for ANY backend API work — it references sub-skills for deep implementation details.

API Architecture Patterns

TL;DR

API extensions use `createFeature` to register features into the DI container. Each feature is a vertical slice with abstractions, implementations, and a `feature.ts` registration file. The key abstractions are **Services** (multi-method, singleton) and **UseCases** (single-method orchestrators, transient). Repositories handle persistence via CMS. Features are named by **business capability**, files inside by **technical responsibility**.

Working Context

This skill applies to both **extension developers** (working in `extensions/`) and **core developers** (working in `packages/`). The architecture patterns are identical — only imports and registration differ.

| | Extensions (`extensions/`) | Core (`packages/`) | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | | **Imports** | `webiny/api`, `webiny/api/cms/model`, etc. | `@webiny/feature/api`, `@webiny/api-headless-cms/...`, etc. | | **Catalog paths** | Use the `Import:` path | Use the `Source:` path | | **Entry point** | `export default createFeature(...)` in a file targeted by `<Api.Extension src={...}>` | `createFeature` registered by the package initializer | | **GraphQL schemas** | `export default GraphQLSchemaFactory.createImplementation(...)` — registered via `container.register()` inside the entry point's `createFeature` | Same pattern, but imported from `@webiny/handler-graphql` |

Detect which context you're in by checking the file path: `extensions/` → extension mode, `packages/` → core mode.

Architecture Overview

Extension (root) ── registers ──> Features + GraphQL Schemas + Models
    Feature ── registers ──> UseCase | Service | EventHandler + Repository
        UseCase ── depends on ──> Service | Repository (+ EventPublisher)
            Repository ── depends on ──> CMS Use Cases (GetModel, CreateEntry, etc.)
        Service ── depends on ──> external APIs, other Services
  • **Extension**: Top-level entry point. Registers all features, GraphQL schemas, and CMS models.
  • **Feature**: A vertical slice. Registers its use cases, services, repositories, and event handlers.
  • **UseCase**: Single-method orchestrator (`execute()`). Coordinates services, repositories, and events. Transient scope.
  • **Service**: Multi-method abstraction for external API calls or cohesive domain logic. Singleton scope.
  • **Repository**: Persistence layer using CMS as storage. Singleton scope.
  • **EventHandler**: Thin orchestrator reacting to domain events. Delegates to services/use cases.
  • **GraphQL Schema**: Defines types, inputs, queries, and mutations. Resolvers delegate to use cases.
  • **CMS Model**: Defines the data schema stored in headless CMS.

---

Services vs UseCases

Services

Multi-method abstractions for **external API calls** or **cohesive domain logic**. A service groups related operations that belong together.

// abstractions.ts
export interface ILingotekService {
  translate(documentId: string, targetLocale: string): Promise<Result<void, Error>>;
  getTranslationStatus(documentId: string): Promise<Result<TranslationStatus, Error>>;
  deleteProject(projectId: string): Promise<Result<void, Error>>;
}

export const LingotekService = createAbstraction<ILingotekService>("MyExt/LingotekService");

export namespace LingotekService {
  export type Interface = ILingotekService;
}
  • Registered in **singleton scope** (`.inSingletonScope()`)
  • Located in: `features/{serviceName}/` or `features/services/{serviceName}/`
  • One service per external system or cohesive domain area
  • **If async bootstrap is needed** (loading settings from CMS, fetching remote config): use the **ServiceProvider pattern** — a provider abstraction with `async getService()` that lazily initializes and caches the service. Consumers inject the provider, not the service directly. See the ServiceProvider section below.

UseCases

Single-method orchestrators with an `execute()` method. They coordinate services, repositories, and events.

export interface ISyncProjectUseCase {
  execute(input: SyncProjectInput): Promise<Result<Project, SyncProjectError>>;
}
  • Registered in **transient scope** (default)
  • Located in: `features/{ActionEntity}/`
  • One use case per business operation

When to Create a UseCase

  • GraphQL mutations need the same logic as event handlers
  • Need to coordinate multiple services or repositories
  • Business logic must be reusable across entry points (GraphQL, events, CLI)

When NOT to Create a UseCase

  • Simple event handler that calls one service method — inject the service directly
  • Simple read queries — inject the service or repository directly into the GraphQL resolver
  • Logic that only exists in one place and is unlikely to be reused

ServiceProvider Patte

Read more
Ships withwebiny-js

Open-source content platform. Self-hosted on AWS serverless. Built as a TypeScript framework you extend with code, not a closed product you configure through a UI. Runs on Lambda, DynamoDB, S3, and CloudFront inside your own AWS account. Scales automatically.

Get the whole plugin
Stats
8,048
Stars
682
Forks
Active
Maintenance
TypeScript
Language
2h ago
Last commit
8y ago
Created
9h ago
Added

Repo: webiny/webiny-js

Other skills on webiny-js.