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.

referencesdashboard-pageDYNAMIC_PARAMETERS.md

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

Dynamic Parameters Management

Complete guide for managing dynamic parameters for embedded scripts in dashboard pages.

Description

This dashboard page manages dynamic parameters for an embedded script. The parameters are configurable values that site owners can set through this dashboard interface, and they will be passed to the embedded script as template variables.

IMPORTANT: Only implement UI for parameters that are relevant to your current use case. Ignore parameters that don't apply to the functionality you're building. It's perfectly fine to not use all parameters if they're not applicable.

Implementation Requirements

1. Import embeddedScripts

  • Import embeddedScripts directly from '@wix/app-management'
  • Use embeddedScripts.getEmbeddedScript() to load parameters
  • Use embeddedScripts.embedScript({ parameters }) to save parameters
  • Example:
    import { embeddedScripts } from '@wix/app-management';

2. Type Definition

  • Create a TypeScript type/interface that includes all the dynamic parameters
  • Example:
    export type MyScriptOptions = {
      headline: string;
      text: string;
      imageUrl: string;
      activationMode: 'active' | 'timed' | 'disabled';
      startDate?: string;
      endDate?: string;
    };

3. State Management

  • Use React useState to manage the parameter values locally
  • Initialize with default values for all parameters
  • Add separate state for isLoading and isSaving
  • Use useEffect to load parameters on mount
  • IMPORTANT: Parameters are returned as strings from the API, so you must handle type conversions:
    • BOOLEAN parameters: Convert from string 'true'/'false' to boolean
    • NUMBER parameters: Convert from string to number using Number()
    • Other types: Use as-is
  • Example:
    const [options, setOptions] = useState<MyScriptOptions>(defaultOptions);
    const [isLoading, setIsLoading] = useState(true);
    const [isSaving, setIsSaving] = useState(false);
    
    useEffect(() => {
      const loadSettings = async () => {
        try {
          const embeddedScript = await embeddedScripts.getEmbeddedScript();
          const data = embeddedScript.parameters as Partial<Record<keyof MyScriptOptions, string>> || {};
    
          setOptions((prev) => ({
            ...prev,
            textField: data?.textField || prev.textField,
            booleanField: data?.booleanField === 'true' ? true : data?.booleanField === 'false' ? false : prev.booleanField,
            numberField: Number(data?.numberField) || prev.numberField,
          }));
        } catch (error) {
          console.error('Failed to load settings:', error);
        } finally {
          setIsLoading(false);
        }
      };
    
      loadSettings();
    }, []);

4. Loading State

  • Show a Loader component while isLoading is true
  • Example:
    {isLoading ? (
      <Box align="center" verticalAlign="middle" height="50vh">
        <Loader text="Loading..." />
      </Box>
    ) : (
      // ... form content
    )}

5. Form Components

  • IMPORTANT: Only create form fields for parameters relevant to your use case
  • Skip parameters that don't apply to the functionality being built
  • Create appropriate WDS form fields based on parameter types:
    • TEXT → Input component with FormField
    • NUMBER → Input component with type="number"
    • BOOLEAN → Checkbox or ToggleSwitch
    • IMAGE → Custom ImagePicker component (see components/image-picker.tsx)
    • DATE → DatePicker component
    • SELECT → Dropdown component with options
    • URL → Input with URL validation
  • Use FormField wrapper for labels and validation messages
  • Set required validation based on parameter.required flag
  • Show validation errors using FormField status and statusMessage props

6. Save Functionality

  • Add a Save button in the Page.Header actionsBar
  • Make handleSave an async function
  • CRITICAL: All parameters must be passed as STRING values because they are used as template variables in the embedded script
  • Convert all values to strings before saving:
    • BOOLEAN: Use String(value) or value.toString()
    • NUMBER: Use String(value) or value.toString()
    • Other types: Already strings, use as-is
  • Disable the Save button if required fields are missing or while saving
  • Add proper error handling

7. Form Validation

  • Implement validation for required fields
  • Show error states on FormField components
  • Display clear error messages

8. Layout and Organization

  • Use Card components to group related fields
  • Use Box with direction="vertical" for form layout
  • Add appropriate spacing with gap props
  • Include helpful descriptions using Card subtitle or FormField infoContent
  • Consider creating a separate settings component for complex forms

9. Preview Component (Optional but Recommended)

  • If applicable, create a preview component that shows how the configuration will look
  • Display the preview alongside the settings form using Layout and Cell components
  • The preview should react to parameter changes in real-time

Files to Generate

When dynamic parameters are present, generate all of these — the two wrapper files are not optional:

File Role
dashboard/BusinessManagerTheme.tsx Theme wrapper — BUSINESS_MANAGER_THEME.md § 2
dashboard/withProviders.tsx Provider wrapper (below)
dashboard/pages/page.tsx The page, exported wrapped in withProviders
dashboard/types.ts Parameter type definitions
Component files Settings forms, previews

Parameters are saved as individual string fields, never as one JSON string, and converted back to their real types on load. Use embeddedScripts directly from @wix/app-management.

Provider Wrapper Implementation

Generate src/extensions/dashboard/withProviders.tsx:

import React from 'react';
import { i18n } from '@wix/essentials';
import { BusinessManagerTheme } from './BusinessManagerTheme';

export default function withProviders<P extends {} = {}>(Component: React.FC<P>) {
  return function DashboardProviders(props: P) {
    return (
      <BusinessManagerTheme locale={i18n.getLocale()}>
        <Component {...props} />
      </BusinessManagerTheme>
    );
  };
}

// Also export as named export for backwards compatibility
export { withProviders };

Business Manager passes none of the redesign through the extension's iframe, so a wrapper holding WixDesignSystemProvider alone renders the pre-redesign look while compiling and previewing cleanly. features={{ newColorsBranding: true }} predates the theme and does not substitute for it.

Using Provider Wrapper

In your dashboard page component (page.tsx):

  1. import withProviders from '../../withProviders';
  2. Import embeddedScripts from '@wix/app-management'
  3. Add no design-system providers in the page — withProviders owns them
  4. Export wrapped: export default withProviders(MyComponent);
  5. The component holds the Page and its content, not providers

Example structure:

import { useEffect, useState, type FC } from 'react';
import { dashboard } from '@wix/dashboard';
import { embeddedScripts } from '@wix/app-management';
import { Page, Card, Button, ... } from '@wix/design-system';
import withProviders from '../../withProviders'; // owns the stylesheets and providers

const MyDashboardPage: FC = () => {
  const [options, setOptions] = useState<MyScriptOptions>(defaultOptions);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);

  useEffect(() => {
    const loadSettings = async () => {
      try {
        const embeddedScript = await embeddedScripts.getEmbeddedScript();
        const data = embeddedScript.parameters || {};
        // ... update options with data
      } catch (error) {
        console.error('Failed to load settings:', error);
      } finally {
        setIsLoading(false);
      }
    };
    loadSettings();
  }, []);

  const handleSave = async () => {
    setIsSaving(true);
    try {
      await embeddedScripts.embedScript({ parameters: { /* ... */ } });
      dashboard.showToast({ message: 'Saved!', type: 'success' });
    } catch (error) {
      console.error('Failed to save:', error);
      dashboard.showToast({ message: 'Failed to save', type: 'error' });
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <Page height="100vh">
      {/* Page content - NO WixDesignSystemProvider here */}
    </Page>
  );
};

export default withProviders(MyDashboardPage);

Critical Notes

  • Only implement UI for parameters that are relevant to your specific use case - ignore parameters that don't apply
  • ALWAYS generate BusinessManagerTheme.tsx and withProviders.tsx, and wrap the page export with withProviders() — no design-system providers in the page itself
  • ALWAYS use embeddedScripts directly from '@wix/app-management'
  • ALWAYS convert parameter values to strings when saving (embeddedScripts.embedScript must receive all string values in the parameters object)
  • ALWAYS convert string parameters back to proper types when loading (e.g., 'true' -> true for booleans, string to number for numbers)
  • ALWAYS handle the loading state with isLoading state variable
  • ALWAYS handle the saving state with isSaving state variable
  • ALWAYS add try/catch blocks for async operations (loading and saving)
  • ALWAYS use async/await for embeddedScripts operations
  • ALWAYS merge parameter values correctly in useEffect with proper type conversions
  • ALWAYS validate required fields and show appropriate error states
  • The parameter keys MUST match exactly what is expected in the embedded script template variables
  • Each parameter is saved as a separate field, NOT as a JSON string

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.