Skip to content
Content
Skill

/admin-architect

Admin-side architecture patterns for Webiny extensions. Use this skill when building frontend features with headless features (UseCase/Repository/Gateway), presentation features (Presenter/ViewModel/hooks/components), MobX-based presenters, RegisterFeature, and Admin

BOOST
From plugin
webiny-js
8k76 skills3 MCP
Install
$ npx -y skills add webiny/webiny-js --skill admin-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/admin-architect

Context preview

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

Admin-side architecture patterns for Webiny extensions. Use this skill when building frontend features with headless features (UseCase/Repository/Gateway), presentation features (Presenter/ViewModel/hooks/components), MobX-based presenters, RegisterFeature, and Admin

SKILL.md

admin-architect.SKILL.md
name: webiny-admin-architect
description: >
  Admin-side architecture patterns for Webiny extensions. Use this skill when building
  frontend features with headless features (UseCase/Repository/Gateway), presentation
  features (Presenter/ViewModel/hooks/components), MobX-based presenters, RegisterFeature,
  and Admin BuildParams. Covers the admin/ directory structure for both features/ and
  presentation/ layers.

Admin Architecture Patterns

TL;DR

Admin extensions are React components that register headless features (business logic with no UI) and presentation features (MobX presenters, React hooks, components). Headless features live in `admin/features/` and follow **UseCase → Repository → Gateway** layering. Presentation features live in `admin/presentation/` and add a **Presenter** (MobX view model) layer on top. Both use `createFeature` and `createAbstraction` from `webiny/admin`.

**All features — both headless and presentation — MUST provide a `resolve` function** in `createFeature`. This is how the `useFeature` hook accesses resolved instances from the DI container. Without `resolve`, the feature cannot be consumed from React.

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 differ.

| | Extensions (`extensions/`) | Core (`packages/`) | | ----------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Imports** | `webiny/admin`, `webiny/admin/ui`, `webiny/admin/cms/entry/editor` | `@webiny/app`, `@webiny/admin-ui`, `@webiny/app-headless-cms/...` | | **Catalog paths** | Use the `Import:` path | Use the `Source:` path | | **MobX wrapper** | `createReactiveComponent` from `webiny/admin` | `createReactiveComponent` from `@webiny/app-admin` (never import `observer` from `mobx-react-lite` directly — the only exception is `@webiny/app-admin` itself, which is the source of the re-export) | | **Entry point** | React component as `export default` in a file targeted by `<Admin.Extension src={...}>` | React component registered by the package initializer |

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

Admin Directory Structure

admin/
├── Extension.tsx         # Admin entry point (React component)
├── features/             # Headless features (business logic, no UI)
│   └── EnableThing/
│       ├── abstractions.ts
│       ├── EnableThingUseCase.ts
│       ├── EnableThingRepository.ts
│       ├── EnableThingGateway.ts
│       └── feature.ts
└── presentation/         # Presentation layer (hooks, components, presenters)
    └── CurrentThing/
        ├── abstractions.ts   # Presenter + ViewModel interfaces
        ├── CurrentThingPresenter.ts    # MobX-based view model
        ├── useCurrentThing.ts          # React hook for consumers
        ├── feature.ts                  # createFeature registration
        └── components/                 # React UI components

Admin Extension Entry Point

The Admin entry point is a React component that registers features, providers, UI decorators, and config:

// src/admin/Extension.tsx
import React from "react";
import { AdminConfig, RegisterFeature } from "webiny/admin";
import { CurrentThingFeature } from "./presentation/CurrentThing/feature.js";
import { EnableThingFeature } from "./features/EnableThing/index.js";
import { CurrentThingProvider } from "./presentation/CurrentThing/CurrentThingProvider.js";
import { ThingListView } from "./presentation/ThingListView/ThingListView.js";

export const Extension = () => {
  return (
    <>
      {/* Register headless features (use cases, repositories, gateways) */}
      <RegisterFeature feature={EnableThingFeature} />

      {/* Register presentation features (presenters, view models) */}
      <RegisterFeature feature={CurrentThingFeature} />

      {/* Providers and UI components */}
      <CurrentThingProvider />
      <ThingListView />

      {/* Admin config (menus, routes, etc.) */}
      <AdminConfig>{/* Menu items, route definitions, etc. */}</AdminConfig>
    </>
  );
};

Headless Features (`features/`)

Headless features contain business logic with no UI — use cases, repositories, and gateways. They follow the same layering as API features but use `webiny/admin` imports.

Abstractions

// src/admin/features/EnableThing/abstractions.ts
import { createAbstraction } from "webiny/admin";

export interface IEnableThingUseCase {
  execute(id: string): Promise<void>;
}

export const EnableThingUseCase = createAbstraction<IEnableThingUseCase>("EnableThingUseCase");

export namespace EnableThingUseCase {
  export type Interface = IEnableThingUseCase;
}

export interface IEnableThingRepository {
  execute(id: string): Promise<void>;
}

export const EnableThingR
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.