All skills
wix avatar

/wix-app

@dc6f1fa official
by Wix.comwix/skills33 stars
33

Build and review Wix CLI app extensions — dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, backend APIs, backend events, service plugins, data collections, and App Market readiness. Use when building ANY feature or extension for a Wix CLI app or preparing a Wix app for App Market review. Triggers on: add, build, create, implement, help me, dashboard, widget, plugin, backend, API, event, collection, embedded script, service plugin, Editor React component, checkout, shipping, tax, discount, SPI, CMS, schema, tracking, popup, admin panel, menu item, modal, validate, test, verify, register extension, App Market, app review, submission readiness.

Use this Skill: https://skilld.dev/gh/wix/skills/wix-app

This session only. Nothing lands on disk.

referencesservice-pluginBOOKINGS-VALIDATION.md

≈2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Bookings Validation Service Plugin Reference

Overview

The Bookings Validation SPI lets you implement custom validation logic for booking operations. When a customer creates, cancels, or reschedules a booking (single-service or multi-service), Wix calls the handler matching that operation before it executes. Return valid: true to allow the operation or valid: false to block it with a customer-facing message.

bookingsValidation.provideHandlers requires all six handlers in the object literal — TypeScript rejects a partial object even though you may only care about one or two targets. For the ones you don't have real logic for, provide a no-op that returns an empty results/singleServiceBookingResults array (an empty array is a no-op: "Omitting an item's result treats it as valid," and an empty results array omits every item's result). Confirmed live: wix generate itself scaffolds all six handlers by default — that's not incidental boilerplate you can trim.

Handlers

Handler Validation target On error/timeout
validateBeforeCreate CREATE Blocked (fail-closed)
validateBeforeCancel CANCEL Blocked (fail-closed)
validateBeforeReschedule RESCHEDULE Continues (fail-open)
validateBeforeCreateMultiService CREATE_MULTI_SERVICE Blocked (fail-closed)
validateBeforeCancelMultiService CANCEL_MULTI_SERVICE Blocked (fail-closed)
validateBeforeRescheduleMultiService RESCHEDULE_MULTI_SERVICE Continues (fail-open)

Request and Response Schema

Before implementing, call ReadFullDocsMethodSchema on each docs URL to get the full request/response types.

Handler Docs URL
validateBeforeCreate https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-create?apiView=SDK
validateBeforeCancel https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-cancel?apiView=SDK
validateBeforeReschedule https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-reschedule?apiView=SDK
validateBeforeCreateMultiService https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-create-multi-service?apiView=SDK
validateBeforeCancelMultiService https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-cancel-multi-service?apiView=SDK
validateBeforeRescheduleMultiService https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-validation-service-plugin/validate-before-reschedule-multi-service?apiView=SDK

Correlation differs by handler — this is easy to get wrong, and doing so fails tsc, not just at runtime:

Handler(s) Item shape Max items Result correlates by
validateBeforeCreate, validateBeforeCreateMultiService { itemIndex, booking } 40 itemIndex
validateBeforeCancel, validateBeforeReschedule, and their multi-service equivalents { booking } — no itemIndex field at all 8 bookingId (from booking._id)

Only the create family carries itemIndex; cancel and reschedule items don't have one, so their results key on the booking's own ID instead. The single-service response field is results; the multi-service response field is singleServiceBookingResults — same per-item shape either way. Omitting an item's result treats it as valid. contactDetails and resource name/email fields are redacted before reaching your handler.

Example: Membership Limit and Cancellation Fee

This example enforces a pricing-plan booking limit on create, and blocks late cancellations.

import { bookingsValidation } from "@wix/bookings/service-plugins";
import { auth } from "@wix/essentials";
import { orders } from "@wix/pricing-plans";

bookingsValidation.provideHandlers({
  validateBeforeCreate: async (payload) => {
    const { request } = payload;

    const results = await Promise.all(
      (request.items ?? []).map(async (item) => {
        const memberId = item.booking?.contactDetails?.contactId;
        if (!memberId) {
          return { itemIndex: item.itemIndex, result: { valid: true } };
        }

        // Not orders.listOrders — that method doesn't exist on @wix/pricing-plans.
        // managementListOrders takes flat buyerIds/orderStatuses, not a nested filter.
        const elevatedListOrders = auth.elevate(orders.managementListOrders);
        const { orders: activeOrders } = await elevatedListOrders({
          buyerIds: [memberId],
          orderStatuses: ["ACTIVE"],
        });

        if ((activeOrders ?? []).length === 0) {
          return {
            itemIndex: item.itemIndex,
            result: {
              valid: false,
              invalidReason: {
                message: "An active membership is required to book this service.",
                fieldViolations: [
                  { field: "booking.contactDetails", description: "No active membership found.", code: "PLAN_EXPIRED" },
                ],
              },
            },
          };
        }

        return { itemIndex: item.itemIndex, result: { valid: true } };
      })
    );

    return { results };
  },

  validateBeforeCancel: async (payload) => {
    const { request } = payload;

    // Cancel items carry no itemIndex — correlate results by the booking's own _id.
    const results = (request.items ?? []).map((item) => {
      const bookingId = item.booking?._id ?? undefined;
      const startDate = item.booking?.bookedEntity?.slot?.startDate;
      const hoursUntilStart = startDate
        ? (new Date(startDate).getTime() - Date.now()) / (1000 * 60 * 60)
        : Infinity;

      if (hoursUntilStart < 24) {
        return {
          bookingId,
          result: {
            valid: false,
            invalidReason: { message: "Cancellations within 24 hours of the appointment aren't allowed." },
          },
        };
      }

      return { bookingId, result: { valid: true } };
    });

    return { results };
  },

  // Unimplemented targets still need a handler — see the note above the example.
  validateBeforeReschedule: async () => ({ results: [] }),
  validateBeforeCreateMultiService: async () => ({ singleServiceBookingResults: [] }),
  validateBeforeCancelMultiService: async () => ({ singleServiceBookingResults: [] }),
  validateBeforeRescheduleMultiService: async () => ({ singleServiceBookingResults: [] }),
});

Manual Setup Required

None — confirmed live via the real Cancel Booking API: a cancellation under 24h was correctly blocked with a structured 428 VALIDATION_FAILED, and one over 24h correctly succeeded. Wix calls this plugin automatically on the relevant booking operations once the app is installed and released.

Key Implementation Notes

  1. Bulk requests, per-item results — return a result for every item you received (keyed by itemIndex on create, by bookingId on cancel/reschedule — see the correlation table above); a missing entry is treated as valid, not rejected.
  2. Respond fast — validateBeforeCreate, validateBeforeCancel, and their multi-service equivalents fail-closed (block the operation) on error or timeout; validateBeforeReschedule and its multi-service equivalent fail-open (allow it).
  3. Multiple providers run concurrently — if other apps also register validators for the same target, any single rejection blocks the operation.
  4. Write customer-facing messages — invalidReason.message and fieldViolations[].description are shown to the customer; keep them clear and free of internal jargon. fieldViolations[].code is for your own programmatic handling, not display.
  5. Elevate permissions — use auth.elevate when querying Wix APIs (e.g., pricing plan orders) from the handler.

Source: SKILL.md on GitHub

1 warningtoday4 checks · Risk SAFE
  • Gen Agent Trust Hubtoday

    This skill is a specialized development toolkit for building extensions on the Wix platform. It provides comprehensive instructions for creating dashboard pages, backend APIs, and site plugins using the Wix CLI and SDKs. No malicious patterns were detected; the skill's behaviors, such as dependency management, command execution for builds, and local script execution for code reviews, are entirely consistent with its purpose as a developer productivity tool for the Wix ecosystem.

  • Sockettoday

    1 alert: gptAnomaly

  • Snyktoday

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at dc6f1fa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 days ago
compatibility
requires `@wix/cli` >= 1.1.192.

README badge

README badge for wix/skills/wix-app

Builds dashboard pages, modals, plugins, custom widgets, Editor React components, backend APIs, events, service plugins, and data collections for Wix CLI apps. Provides decision logic, API patterns, and validation workflows; scaffolding is owned by the Wix CLI via `wix generate --params`.

Generated from the current SKILL.md.

What extension types does this skill cover?
All Wix CLI app extension types: dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, backend APIs, backend events, service plugins, and data collections.
Does this skill scaffold the extension files for me?
The Wix CLI owns scaffolding via `wix generate --params` for all extension types except Backend API. This skill provides decision logic, API guidance, and business-logic patterns to fill in the generated stubs. Backend API files must be created manually.
What Wix CLI version is required?
The skill requires @wix/cli >= 1.1.192.
Do I need to create a Data Collection extension for app-specific data?
Yes, if you're saving or persisting app-specific data, managing domain entities in a dashboard, or running a service plugin that reads app-configured data. The skill infers this automatically—you don't need to explicitly request it.
Does this skill cover Wix Stores API usage?
Yes. When using any Wix Stores API (products, inventory, orders), the skill requires dual V1/V3 catalog support and references the Stores Versioning guide for module selection and field mapping.

Generated from the current SKILL.md. These answers refresh after source changes.