Skills

Webiny Cms Bulk Actions

Authoring a custom Headless CMS bulk action (EntriesBulkAction) that Webiny runs as a...

Install

npx skills add webiny/webiny-js --skill webiny-cms-bulk-actions -g -a claude-code -y
Repository
webiny/webiny-js8.1k
Category
Design
Updated
5d ago
License
See repository
Context cost
Mediumabout 2,085 tokens
Runs scripts
No, instructions only

What it does

Authoring a custom Headless CMS bulk action (EntriesBulkAction) that Webiny runs as a background task, plus the Admin-side button that triggers it. Use this skill when the developer wants to add a bulk action to the content-entry list (e.g. apply a discount, generate content, bulk-transform entries), understand loadData/processData, make the task converge, filter by custom fields, or trigger the action from the Admin UI. Requires Webiny 6.5.0 or newer.

Custom Headless CMS bulk actions

TL;DR

A bulk action is a class implementing EntriesBulkAction.Interface with two methods, loadData (which entries) and processData (what to do to each). Register it with export default EntriesBulkAction.createImplementation({...}) via <Api.Extension src>. For every registered bulk action, Webiny automatically generates a list background task, a process background task, and a GraphQL mutation. On the Admin side, add a ContentEntryListConfig.Browser.BulkAction button that calls BulkActionFeature's useCase.execute({ model, action, where, data }).

Available from Webiny 6.5.0 (webiny/api/cms/entry).

Backend, the bulk action

// extensions/myBulkAction/api/MyBulkAction.ts
import {
  EntriesBulkAction,
  ListLatestEntriesUseCase,
  UpdateEntryUseCase
} from "webiny/api/cms/entry";

class MyBulkActionImpl implements EntriesBulkAction.Interface {
  // PascalCased into the task ids + GraphQL enum value, so "applyDiscount" →
  // tasks hcmsBulk(List|Process)ApplyDiscountEntries and frontend action "ApplyDiscount".
  readonly name = "applyDiscount";
  // Optional: restrict which models get the mutation/button.
  readonly modelIds = ["product"];
  // Optional: entries processed per batch (defaults to the configured batchSize).
  // readonly batchSize = 50;

  constructor(
    private listEntries: ListLatestEntriesUseCase.Interface,
    private updateEntry: UpdateEntryUseCase.Interface
  ) {}

  // Runs in the "list" task, with pagination (params.where/search/after/limit).
  async loadData(model, params) {
    const result = await this.listEntries.execute(model, params);
    return result.value; // { entries, meta }
  }

  // Runs in the "process" task, once per entry, in batches.
  async processData(model, params) {
    // params.id is a revision id ("<entryId>#0001"); params.data carries whatever the
    // Admin action sent.
    // ...update / transform the entry here...
  }
}
Read the whole SKILL.md on GitHub

More in Design