# Editing Published Widgets

## Overview

This guide explains how to edit widgets that are already published and used on pages. Understanding the relationship between widget definitions and custom widgets is crucial for successful editing.

## Key Concepts

### Widget Definitions vs Custom Widgets

**Widget Definitions** (`/widget_definitions`):
- Editable versions of widgets
- Accessed via `widget-definitions-list` and `widget-definition-get` tools
- Can be in draft or published state
- Have a unique `id` that may change after publishing
- Have a stable `uuid` (OID) that never changes

**Custom Widgets** (`/custom_widgets`):
- Published, read-only versions (deprecated endpoint name)
- Previously thought to be read-only, but actually editable through widget definitions
- Appear in `widget-get-custom-widgets` tool
- Used when adding widgets to pages via `page-add-widgets`

### Important: Widget IDs Change After Publishing

When you publish a widget:
1. The `id` field changes because Modyo creates a new version
2. The `uuid` (OID) remains constant
3. Previous versions are archived

**Example:**
```
Widget Definition ID: 86745
UUID: bee3ee40972ffa9d8b44cabac65aaa618549e356
Status: published

After editing and republishing:
Widget Definition ID: 86750 (NEW ID!)
UUID: bee3ee40972ffa9d8b44cabac65aaa618549e356 (SAME)
Status: published
```

## How to Edit a Widget Used on a Page

### Step 1: Find the Widget's UUID

Get the UUID from the page where the widget is used:

```typescript
// Get the page
const page = await page-get({
  platformSlug: "fed-team",
  siteId: 4605,
  pageId: 175272
});

// Find the widget in page.widgets array
const widget = page.widgets.find(w => w.label === "Product Showcase API MiBanco");
const widgetUuid = widget.definition_uuid;
// Result: "bee3ee40972ffa9d8b44cabac65aaa618549e356"
```

### Step 2: List Widget Definitions to Find Current ID

**CRITICAL:** Use `widget-definitions-list`, NOT `widget-get-custom-widgets`:

```typescript
// ✅ CORRECT - Lists editable widget definitions
const definitions = await widget-definitions-list({
  platformSlug: "fed-team",
  siteId: 4605,
  query: ""  // Empty to get all, or search term
});

// Find widget by UUID
const widget = definitions.widget_definitions.find(
  w => w.uuid === "bee3ee40972ffa9d8b44cabac65aaa618549e356"
);

const currentId = widget.id;  // This is the ID to use for editing
```

**Response structure:**
```json
{
  "widget_definitions": [
    {
      "id": 86745,  // Current editable ID
      "uuid": "bee3ee40972ffa9d8b44cabac65aaa618549e356",
      "name": "Product Showcase API MiBanco",
      "status": "published",
      "read_only": false,
      "referenced": true  // Used on pages
    }
  ]
}
```

### Step 3: Get Widget Code

```typescript
const widget = await widget-definition-get({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: 86745  // Use ID from Step 2
});

// Access current code
const html = widget.html_widget_template.body;
const css = widget.css_widget_template.body;
const js = widget.js_widget_template.body;
```

### Step 4: Update Widget Code

```typescript
await widget-definition-update({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: 86745,  // Use ID from Step 2
  html: "<div>Updated HTML with Liquid...</div>",
  css: ".my-widget { color: red; }",
  js: "console.log('Updated JS');"
});
```

**After update:**
- Status changes to `"pending_changes"`
- Widget is in draft mode
- Changes are NOT visible on pages yet

### Step 5: Publish Changes

```typescript
// Get publishable elements
const elements = await release-get-elements-to-publish({
  platformSlug: "fed-team",
  siteId: 4605
});

// Find the widget in widgetDefinition array
const widgetToPublish = elements.widgetDefinition.find(
  w => w.oid === "bee3ee40972ffa9d8b44cabac65aaa618549e356"
);

// Publish
await release-create({
  platformSlug: "fed-team",
  siteId: 4605,
  data: {
    widgetDefinition: [
      { id: widgetToPublish.id, selected: true }
    ],
    page: [],
    template: [],
    menu: []
  }
});
```

**After publishing:**
- Changes are live on all pages using this widget
- Widget ID may change (but UUID stays the same)
- Status returns to `"published"`

## Complete Workflow Example

### Scenario: Update "Nuestros Productos" Widget to Use Liquid

```typescript
// 1. Get page to find widget UUID
const page = await page-get({
  platformSlug: "fed-team",
  siteId: 4605,
  pageId: 175272
});

const productWidget = page.widgets.find(
  w => w.label.includes("Product Showcase")
);
const uuid = productWidget.definition_uuid;
// "bee3ee40972ffa9d8b44cabac65aaa618549e356"

// 2. List widget definitions to find current ID
const definitions = await widget-definitions-list({
  platformSlug: "fed-team",
  siteId: 4605,
  query: "Product Showcase"
});

const widget = definitions.widget_definitions.find(w => w.uuid === uuid);
const widgetId = widget.id;  // 86745

// 3. Get current widget code
const currentWidget = await widget-definition-get({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId
});

// 4. Update to use Liquid instead of JavaScript
// IMPORTANT: Use exact field names from Content Type (with accents, spaces, capitalization)
await widget-definition-update({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId,
  html: `
    <div class="product-showcase">
      {%- assign products = spaces['neobank-products'].types['product'].entries -%}
      {%- for product in products -%}
        <div class="product-card">
          <h3>{{ product.fields['Título'] }}</h3>
          <p>{{ product.fields['Descripción'] }}</p>
        </div>
      {%- endfor -%}
    </div>
  `,
  js: "// Simplified JS for tracking only"
});

// 5. Publish changes
const elements = await release-get-elements-to-publish({
  platformSlug: "fed-team",
  siteId: 4605
});

const widgetToPublish = elements.widgetDefinition.find(
  w => w.oid === uuid
);

await release-create({
  platformSlug: "fed-team",
  siteId: 4605,
  data: {
    widgetDefinition: [{ id: widgetToPublish.id, selected: true }]
  }
});
```

## Common Issues

### Issue 1: Widget ID Not Found (404 Error)

**Problem:** Using wrong ID from `widget-get-custom-widgets`

```typescript
// ❌ WRONG - This returns published custom widgets, not editable definitions
const customWidgets = await widget-get-custom-widgets({
  platformSlug: "fed-team",
  siteId: 4605
});

const widgetId = customWidgets.custom_widgets[0].id;  // 86740

// This fails with 404:
await widget-definition-get({
  widgetId: 86740  // ❌ Wrong endpoint/ID
});
```

**Solution:** Use `widget-definitions-list` instead

```typescript
// ✅ CORRECT - Get editable widget definitions
const definitions = await widget-definitions-list({
  platformSlug: "fed-team",
  siteId: 4605
});

const widgetId = definitions.widget_definitions[0].id;  // 86745

// This works:
await widget-definition-get({
  widgetId: 86745  // ✅ Correct ID
});
```

### Issue 2: Changes Not Visible on Page

**Problem:** Forgot to publish after updating

**Solution:** Always create a release after updating:

```typescript
// 1. Update widget
await widget-definition-update({ ... });

// 2. Get publishable elements
const elements = await release-get-elements-to-publish({ ... });

// 3. Publish
await release-create({
  data: {
    widgetDefinition: [{ id: widget.id, selected: true }]
  }
});
```

### Issue 3: Widget UUID vs Widget ID Confusion

**Problem:** Using wrong identifier

```typescript
// ❌ WRONG - Using UUID as ID
await widget-definition-get({
  widgetId: "bee3ee40972ffa9d8b44cabac65aaa618549e356"  // This is UUID, not ID
});
```

**Solution:** Always use numeric ID for get/update operations, UUID for finding widgets

```typescript
// ✅ CORRECT
// Use UUID to find widget
const widget = definitions.widget_definitions.find(
  w => w.uuid === "bee3ee40972ffa9d8b44cabac65aaa618549e356"
);

// Use ID for operations
await widget-definition-get({
  widgetId: widget.id  // Numeric ID: 86745
});
```

### Issue 4: Field Names Not Matching Content Type

**Problem:** Using incorrect field names in Liquid that don't match the Content Type definition

```typescript
// ❌ WRONG - Field names don't match Content Type
{{ product.fields['titulo'] }}        // Missing accent
{{ product.fields['icono_svg'] }}     // Missing space, wrong case
{{ product.fields['url'] }}           // Wrong case
```

**CRITICAL RULE:** Field names in Liquid **must match exactly** as defined in the Content Type, including:
- ✅ Spaces: `'Icono SVG'` not `'icono_svg'`
- ✅ Accents: `'Título'` not `'titulo'`
- ✅ Capitalization: `'URL'` not `'url'`

**Solution:** Always check the Content Type schema first

```typescript
// 1. Get Content Type schema
const type = await type-get({
  platformSlug: "fed-team",
  spaceId: 2516,
  typeId: 5759
});

// 2. Check exact field names in type.fields
// Result:
// - "Título" (with accent)
// - "Descripción" (with accent)
// - "Icono SVG" (with space)
// - "URL" (uppercase)

// 3. Use EXACT field names in Liquid
// ✅ CORRECT
{{ product.fields['Título'] }}
{{ product.fields['Descripción'] }}
{{ product.fields['Icono SVG'] }}
{{ product.fields['URL'] }}
```

## Best Practices

### 1. Always Use UUID for Stable References

```typescript
// ✅ Store UUID in configs/scripts
const PRODUCT_WIDGET_UUID = "bee3ee40972ffa9d8b44cabac65aaa618549e356";

// Find current ID before operations
const widget = definitions.widget_definitions.find(
  w => w.uuid === PRODUCT_WIDGET_UUID
);
```

### 2. Check Widget Status Before Publishing

```typescript
const widget = await widget-definition-get({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId
});

if (widget.status === "pending_changes") {
  console.log("Widget has unpublished changes - ready to publish");
} else if (widget.status === "published") {
  console.log("Widget is already published - no changes pending");
}
```

### 3. Verify Widget is Used on Pages

```typescript
const widget = await widget-definition-get({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId
});

if (widget.used === true) {
  console.log("⚠️  Widget is used on pages - changes will affect live site");
  // Proceed with caution
}
```

### 4. Backup Current Code Before Updating

```typescript
const currentWidget = await widget-definition-get({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId
});

// Save current code
const backup = {
  html: currentWidget.html_widget_template.body,
  css: currentWidget.css_widget_template.body,
  js: currentWidget.js_widget_template.body,
  timestamp: new Date().toISOString()
};

// Now update
await widget-definition-update({
  platformSlug: "fed-team",
  siteId: 4605,
  widgetId: widgetId,
  html: newHtml,
  css: newCss,
  js: newJs
});
```

## Tool Reference

### Required Tools

1. **page-get** - Get page to find widget UUID
2. **widget-definitions-list** - List editable widget definitions (NOT `widget-get-custom-widgets`)
3. **widget-definition-get** - Get widget code by ID
4. **widget-definition-update** - Update widget code
5. **release-get-elements-to-publish** - Check what needs publishing
6. **release-create** - Publish widget changes

### Tool Flow Diagram

```
page-get
  ↓
Find widget.definition_uuid
  ↓
widget-definitions-list
  ↓
Find widget by UUID → Get widget.id
  ↓
widget-definition-get (using widget.id)
  ↓
widget-definition-update (using widget.id)
  ↓
release-get-elements-to-publish
  ↓
release-create
  ↓
Widget live on all pages!
```

## Related Documentation

- [Widget Tools](/docs/tools/WIDGET_TOOLS.md)
- [Page Widget Tools](/docs/tools/PAGE_WIDGET_TOOLS.md)
- [Release Tools](/docs/tools/RELEASE_TOOLS.md)
- [Modyo Snippets Architecture](../../channels/snippets/overview.md)

---

**Document Version**: 1.0.0
**Last Updated**: 2025-01-09
**Purpose**: Guide for editing published widgets used on pages
