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.

referenceseditor-react-componentACCESSIBILITY.md

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

Accessibility Implementation and Review

Use while authoring; run the review after JSX is complete.

Contents

Implementation Contract

Own Accessibility per Part

Use the platform A11y type instead of individual public props such as ariaLabel, ariaDescribedBy, or role. For each part:

  • Prefer a native element.
  • Keep roles, heading levels, keyboard and focus behavior, relationships, live regions, and widget state in component code.
  • Read a11y.ariaLabel only when a control has no visible name.

Every a11y field that reaches the DOM becomes an editor control. Read only the field the part needs and write it as its HTML attribute, aria-label={a11y?.ariaLabel}. Never spread the whole object.

import type { A11y } from '@wix/editor-react-types';

type ToggleProps = {
  elementProps?: { toggle?: { className?: string; a11y?: A11y } };
};

function Toggle({ elementProps }: ToggleProps) {
  const { a11y: toggleA11y, ...toggleProps } = elementProps?.toggle ?? {};

  return (
    <button {...toggleProps} aria-label={toggleA11y?.ariaLabel ?? ARIA_LABELS.toggle}>
      <svg aria-hidden="true" viewBox="0 0 16 16">
        <path d="m3 6 5 5 5-5" fill="none" stroke="currentColor" />
      </svg>
    </button>
  );
}

Keep the root's typed a11y?: A11y prop even when it reads no field. Destructure a11y out of an elementProps entry before spreading the entry; a spread entry records the nested object as a whole. Image alt text comes from the Image type's alt field, not from a11y.

Provide Accessible Names

Use this priority order:

  1. Prefer visible text that already names the control.
  2. Use user-configurable a11y when the name depends on site-owner content.
  3. Use the project's translation mechanism or a constants.ts value only for a stable system-owned label required by the component contract.

Never hardcode an aria-label string directly in JSX.

// constants.ts
export const ARIA_LABELS = {
  toggle: 'Toggle details',
  playButton: 'Play animation',
  pauseButton: 'Pause animation',
} as const;

// component JSX
<button
  aria-label={isPlaying ? ARIA_LABELS.pauseButton : ARIA_LABELS.playButton}
>
  {isPlaying ? <PauseIcon /> : <PlayIcon />}
</button>;

Icon-only controls require an accessible name. Controls with visible text, including an icon plus visible text, usually do not need another ARIA label.

Preserve Semantic Ownership

  • Put roles, labels, descriptions, keyboard handling, and focusability on the element that owns the behavior, not on a layout wrapper.
  • Prefer native elements over recreating their semantics with role.
  • Hide decorative-only output with aria-hidden="true" when appropriate.
  • Preserve heading, list, navigation, and landmark semantics through wrappers.
  • Keep hidden or collapsed state consistent across visuals, focusability, and the accessibility tree.

Review Scope

Run this review once the JSX is complete and again after each fix pass, at most two passes. Do not rerun after a clean result unless JSX changed.

Request Pass to the command
Specific file That file; its component folder is rendered
A component name or "this component" The component folder
Full audit src/extensions/site/components/

*.generated.ts is regenerated from JSX and CSS and is never scanned. Imported shared components are inspection context, not automatic edit scope. Report a confirmed shared-component issue instead of changing a broadly reused primitive unless the requested fix requires that shared change and its impact is understood.

Automated Review

<SKILL_ROOT> is the absolute directory containing the active SKILL.md. Run from the consumer Wix package so dependencies resolve from that project.

node <SKILL_ROOT>/scripts/scan-a11y-review.cjs <component-dir | files...>

One command, one report. It runs the jsx-a11y ESLint rules, a semantic scanner that follows imports and checks the per-part a11y contract, and a render audit: the component is rendered with defaultProps in Node (an SSR check), loaded into jsdom with its CSS Modules, and audited with axe-core. component.preview.tsx must render without falling back to the placeholder.

The JSON report has summary.line, then findings grouped by rule with a count, locations or DOM target, the scanner message, and the axe help link, then notChecked. Exit 0 means every scanner ran and found nothing, 1 means findings, 2 means the review is inconclusive; never treat 2 as clean. Exit 2 with render FAILED (missing-deps) means jsdom or axe-core is not installed: install them (SKILL.md step 2) and rerun. Exit 2 with render FAILED (loader) means the audit could not load a module the component imports; that is a scanner limit, not a component defect. Change the import only if tsc also rejects it; otherwise stop and report the loader limit in the final summary as a check that could not run. Color contrast, target size, and keyboard behavior need a browser and remain manual.

Finding Triage

For every finding:

  1. Trace the rendered semantic element through local and shared components.
  2. Deduplicate findings for the same issue and location; keep the finding with stronger evidence.
  3. Assign confirmed, false-positive, or not-relevant.
  4. Fix only confirmed findings.

Scanner output is a lead, not permission to edit blindly.

Confidence and Action

Confidence Evidence Action
High The rendered element and static props directly establish the issue. Confirm and fix when the change is safe and local.
Medium Props or partial component resolution strongly imply the semantics. Inspect surrounding code, then confirm or discard.
Low Heuristics or unresolved runtime spreads are the main evidence. Trace further and fix only after confirmation.
Unknown The semantic target cannot be resolved. Leave unchanged and report the ambiguity when material.

Confidence establishes whether a finding is real, not whether its fix is safe. Apply confirmed local, behavior-preserving fixes. Leave a confirmed issue unchanged only when product intent is unknowable or the fix requires risky, non-local behavior changes.

Semantic Resolution Order

Resolve rendered behavior in this order:

  1. Flagged JSX element and static props
  2. Explicit polymorphic props such as as="a" or component="button"
  3. Local component implementation
  4. Installed package source or declarations
  5. Prop evidence such as href, to, src, alt, and role
  6. Component-name heuristics

Follow local imports to their rendered root. For package imports, inspect the resolved package entry when available. Do not assign more confidence than the evidence supports.

Manual Review

In the default rendered state the command checks names, alt text, ARIA validity, nesting, list and heading structure, hidden-but-focusable content, the a11y contract, and SSR safety. Verify what it cannot see:

  • Every meaningful non-default state (expanded, selected, playing, error, empty, hover/focus) keeps correct names, focusability, hidden state, and structure; the command audits only the default render.

  • Wrappers and polymorphic components preserve their documented semantics; extension overrides preserve generated accessibility fields.

  • Accessible names describe the action, and visually hidden text that carries meaning stays in the accessibility tree.

  • State hidden through --display or transforms agrees with focusability and the accessibility tree; disabled and inert states behave consistently.

  • Custom widgets (tabs, menus, dialogs, sliders) implement their full APG keyboard pattern (arrow keys, Home/End, Escape, roving tabIndex) and structural relationships, or use a plain native element instead of borrowing the role.

  • Interactive controls have a hit area of at least 24×24 CSS px and visible focus.

  • The root implements the direction contract, and every ReactNode slot isolates nested content with dir="ltr".

  • An auto-rotating set of readable parallel items uses aria-live="off" while it is rotating and aria-live="polite" while it is stopped.

Pre-Fix Checks for Non-Interactive Controls

Before adding role="button", tabIndex, and keyboard handlers to a non-native control, verify:

  1. Interactive children: it cannot contain a link, button, input, or another interactive component in the active branch.
  2. Focus ownership: existing tabIndex or accessibility spreads have a clear merge order and one authoritative source.
  3. Interaction condition: the same condition gates pointer, focus, and keyboard behavior and excludes disabled or editor-controlled states when needed.
  4. Accessible-name scope: the label intentionally names the component or action and persists in every state where it is needed.

Prefer a native element when it preserves product behavior.

Completion Criteria

The accessibility review is complete only when:

  • the last run exited 0 or 1; exit 2 is acceptable only for a reported loader limit;
  • every finding is triaged and confirmed issues are fixed when safe;
  • the command was rerun after the last fix pass; and
  • the manual review is complete.

After two fix passes, stop and report the remaining findings with their triage. Preserve visual and runtime behavior. Fix the semantic owner: root, named inner part, shared primitive, or call site. Then return to the main workflow for the Wix build, manifest generation, TypeScript check, and relevant project tests.

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