Custom appconnect Extension Not Showing as component

Why are my extension components not showing up in Wappler's component picker when I've followed all documentation steps correctly?

What I've done:

Step 1: Created Extension Using Wappler UI

  • Used Project Settings > Extensions > Add Extension
  • Created extension at: src/@my-company/example-extension
  • Extension appears in Extensions panel :white_check_mark:

Step 2: Added Official Documentation Example

I used the EXACT example from the official docs:

File: src/@my-company/example-extension/app_connect/components.hjson

  • Extension appears in main package.json devDependencies: :white_check_mark:
  • Extension shows in Wappler Extensions panel: :white_check_mark:
    I can see this in project.json:
  },
  "extensions": [
    {
      "name": "@my-company/wappler-tiptap"
    },
    {
      "name": "@my-company/wappler-video-url-input"
    },
    {
      "name": "file:src/@my-company/wappler-sweetalert2"
    },
    {
      "name": "file:src/@my-company/example-extension"
    }
  ],

Step 4: What I've Tried

  • :white_check_mark: Full Wappler quit and restart (multiple times)
  • :white_check_mark: npm install in project root
  • :white_check_mark: npm install in extension folder
  • :white_check_mark: "Check for project updates" in Extensions panel
  • :white_check_mark: Save project (Cmd+S) after changes
  • :white_check_mark: Manually copied JS files to public/js folder
  • :white_check_mark: Tested different groupTitle values ("Components", "Forms")

CURRENT RESULT

  • :x: "Example Component" does NOT appear in Components group when adding components to page
  • :white_check_mark: Extension is registered and visible in Extensions panel

ENVIRONMENT

  • Wappler: Latest beta
  • Project Type: Node.js
  • Extension Type: App Connect Component

Note: I've tried this with both the official example component and my own custom extension - same result for both. The extension registration works fine, but the components themselves never appear in the UI.

Can someone please help identify what I'm missing? :pray:

What is your components.hjson ?

Do you have the anyParent on to have the component always available or does it have to be under specific parent component?

Hey George, AI found the issue for me... Can you confirm that this is what's needed to get it working? (It does work now but I'm not certain what are the key factors to have it recognised by wappler)

1. Extension Registration in project.json

The extension name must NOT use the file: prefix:

json

{
  "extensions": [
    "@my-company/wappler-sweetalert2"  // ✅ CORRECT: No "file:" prefix
    // NOT: "file:src/@my-company/wappler-sweetalert2" ❌ WRONG
  ]
}

2. Package.json Registration

The extension must ALSO be registered in the main package.json as a devDependency (this time WITH the file: prefix):

json

{
  "devDependencies": {
    "@my-company/wappler-sweetalert2": "file:src/@my-company/wappler-sweetalert2"
  }
}

3. Complete Extension Folder Structure

Here's the exact structure that works:

src/
└── @my-company/
    └── wappler-sweetalert2/
        ├── package.json              # Must have "wappler-extension" keyword
        ├── app_connect/
        │   └── components.hjson      # HJSON format (no quotes!)
        └── includes/                 # ⚠️ REQUIRED folder name
            ├── dmxSweetAlert.js      # Component JavaScript
            └── dmxSweetAlert.css     # Component styles

Critical: The JavaScript and CSS files MUST be in an includes/ folder, not at the extension root!

4. Extension package.json

json

{
  "name": "@my-company/wappler-sweetalert2",
  "version": "1.0.0",
  "description": "SweetAlert2 integration for Wappler",
  "main": "dmxSweetAlert.js",
  "keywords": ["wappler-extension"],  // ⚠️ REQUIRED
  "license": "MIT"
}

5. Complete components.hjson Structure

The file must use proper HJSON format (no quotes around keys) and include several required fields:

hjson

{
  components: [
    {
      // Basic component definition
      type: 'dmx-sweet-alert',
      selector: 'dmx-sweet-alert, [is=dmx-sweet-alert]',
      
      // UI grouping in Wappler
      groupTitle: 'Forms',                    // Use existing group or create new
      groupIcon: 'fa fa-lg fa-bell',
      title: 'SweetAlert2: @@id@@',          // @@id@@ is replaced with actual ID
      icon: 'fa fa-lg fa-exclamation-circle',
      
      // Required fields 
      state: 'opened',                        // ⚠️ REQUIRED
      anyParent: true,                        // ⚠️ REQUIRED
      dataPick: true,                         // ⚠️ REQUIRED
      dataScheme: [                           // ⚠️ REQUIRED - component data structure
        {name: 'isOpen', type: 'boolean'},
        {name: 'lastResult', type: 'object'}
      ],
      outputType: 'object',                   // ⚠️ REQUIRED
      children: [],                           // ⚠️ REQUIRED (even if empty)
      allowed_children: {},                   // ⚠️ REQUIRED (even if empty)
      cssOrder: [],                           // ⚠️ REQUIRED (even if empty)
      jsOrder: [],                            // ⚠️ REQUIRED (even if empty)
      
      // Component template
      template: '<dmx-sweet-alert id="@@id@@"></dmx-sweet-alert>',
      baseName: 'sweetAlert',
      help: 'SweetAlert2 notification component',
      
      // Properties shown in Wappler UI
      properties: [
        {
          group: 'Settings',
          variables: [
            {
              name: 'componentId',
              attribute: 'id',
              title: 'ID',
              type: 'text',
              required: true,
              defaultValue: ''
            }
          ]
        }
      ],
      
      // Actions available in Wappler
      actionsScheme: [
        {
          addTitle: 'Show Alert',
          title: 'Show Alert',
          name: 'show',
          icon: 'fa fa-lg fa-eye',
          state: 'opened',
          help: 'Show alert dialog',
          properties: [
            {
              group: 'Alert Options',
              variables: [
                {
                  name: '1',              // Parameter position
                  optionName: '1',        // Must match name
                  title: 'Title',
                  type: 'text',
                  dataBindings: true,     // Allow dynamic values
                  defaultValue: ''
                }
              ]
            }
          ]
        }
      ],
      
      // File management
      copyFiles: [
        {src: 'includes/dmxSweetAlert.js', dst: 'js/dmxSweetAlert.js'},
        {src: 'includes/dmxSweetAlert.css', dst: 'css/dmxSweetAlert.css'}
      ],
      linkFiles: [
        {src: 'https://cdn.jsdelivr.net/npm/sweetalert2@11', type: 'js'},
        {src: 'js/dmxSweetAlert.js', type: 'js', defer: true},
        {src: 'css/dmxSweetAlert.css', type: 'css'}
      ]
    }
  ],
  
  // Custom attributes (if any)
  attributes: [],
  
  // Custom events
  events: [
    {
      name: 'dmx-sweet-alert-confirmed',
      attributeStartsWith: 'dmx-on',
      attribute: 'confirmed',
      title: 'Confirmed',
      icon: 'fa fa-lg fa-check',
      groupTitle: 'SweetAlert2 Events',
      allowedOn: {
        'dmx-sweet-alert': true
      },
      help: 'Triggered when user confirms'
    }
  ]
}