--- name: webflow-designer-extension description: Build Webflow Designer Extensions that run inside the Webflow Designer. Use when creating, debugging, or modifying Designer Extensions (iframes that interact with Webflow's Designer API). Covers CLI usage, element manipulation, styles, components, pages, variables, assets, error handling, and UI design patterns for Webflow's design system. license: MIT compatibility: "create-webflow-extension" metadata: author: "[Ben Sabic](https://bensabic.dev)" role: "Fractional CTO" version: "1.0.0" --- # Webflow Designer Extension Development Build extensions that run inside Webflow's Designer as iframes, interacting with the Designer API to manipulate elements, styles, pages, and more. ## Quick Start Workflow > **Prerequisite:** Register your app in Webflow first — see [references/register-app.md](references/register-app.md). You'll need a Workspace with Admin permissions. 1. **Scaffold**: `npx create-webflow-extension@latest` (interactive prompts for project name, package manager, linter) 2. **Develop**: `cd && pnpm dev` (serves at localhost:1337; also works with npm/yarn/bun) 3. **Test**: Install app on test site via Workspace Settings > Apps & Integrations > Develop 4. **Open**: Press "E" in Designer to open app panel, launch extension 5. **Build**: `pnpm build` for deployment ### CLI Options ```bash npx create-webflow-extension@latest [project-name] [options] Options: --pm Package manager to use (default: pnpm) --linter Linter to use --skip-git Skip git initialization --skip-install Skip dependency installation --quiet Suppress output ``` ## Core API Patterns ### Getting and Setting Elements ```typescript // Get selected element const el = await webflow.getSelectedElement(); // Get all elements const elements = await webflow.getAllElements(); // Select element programmatically await webflow.setSelectedElement(element); ``` ### Inserting Elements ```typescript const selected = await webflow.getSelectedElement(); if (selected) { // Insert siblings await selected.after(webflow.elementPresets.DivBlock); await selected.before(webflow.elementPresets.Paragraph); // Insert children (if element supports children) if (selected.children) { await selected.append(webflow.elementPresets.Image); await selected.prepend(webflow.elementPresets.Heading); } } ``` ### Styling Elements ```typescript // Create and apply style const style = await webflow.createStyle("MyStyle"); await style.setProperty("background-color", "blue"); await style.setProperty("font-size", "16px"); await element.setStyles([style]); // Responsive styling await style.setProperties( { "font-size": "14px" }, { breakpoint: "medium", pseudo: "hover" } ); ``` ### User Notifications ```typescript await webflow.notify({ type: 'Success', message: 'Element created!' }); await webflow.notify({ type: 'Error', message: 'Please select an element.' }); ``` ## Element Presets Common presets via `webflow.elementPresets`: - Layout: `DivBlock`, `Section`, `Container`, `Grid`, `VFlex`, `HFlex` - Text: `Paragraph`, `Heading`, `TextBlock`, `RichText` - Media: `Image`, `Video` - Forms: `FormForm`, `FormInput`, `FormButton` - Navigation: `Link`, `LinkBlock`, `NavBar` - Custom: `DOM` (for custom HTML tags) For elements without presets, use DOM element: ```typescript const custom = webflow.elementBuilder(webflow.elementPresets.DOM); custom.setTag("section"); custom.setAttribute("class", "custom-section"); ``` ## Breakpoints and Pseudo-States **Breakpoints**: `"xxl"` | `"xl"` | `"large"` | `"main"` | `"medium"` | `"small"` | `"tiny"` **Pseudo-states**: `"hover"` | `"active"` | `"pressed"` | `"visited"` | `"focus"` | `"focus-visible"` | `"placeholder"` | `"first-child"` | `"last-child"` | `"nth-child(odd)"` | `"nth-child(even)"` ## Error Handling ```typescript try { const el = await webflow.getSelectedElement(); await el.remove(); } catch (err) { switch (err.cause?.tag) { case 'ResourceMissing': await webflow.notify({ type: 'Error', message: 'Element not found' }); break; case 'InvalidElementPlacement': await webflow.notify({ type: 'Error', message: 'Cannot place element here' }); break; default: await webflow.notify({ type: 'Error', message: 'An error occurred' }); } } ``` Common error tags: `DuplicateValue`, `Forbidden`, `InternalError`, `InvalidElementPlacement`, `InvalidRequest`, `InvalidStyle`, `ResourceMissing`, `VariableInvalid` ## Project Structure Generated by `create-webflow-extension` (React 19 + TypeScript + Rspack): ``` my-extension/ ├── public/ │ └── index.html # Entry point ├── src/ │ ├── App.tsx # Main React component │ ├── main.tsx # React entry point │ └── index.css # Styles ├── webflow.json # Extension settings ├── rspack.config.ts # Rspack bundler configuration ├── package.json └── tsconfig.json ``` ## Reference Documentation Each reference file includes YAML frontmatter with `name`, `description`, and `tags` for searchability. Use the search script to find relevant references quickly: ```bash # List all references with metadata python scripts/search_references.py --list # Search by tag (exact match) python scripts/search_references.py --tag # Search by keyword (across name, description, tags, and content) python scripts/search_references.py --search ``` ### Quick Lookup - **[references/designer-apis-reference.md](references/designer-apis-reference.md)**: All APIs and methods in one place (start here) ### Detailed Guides - **[references/create-webflow-extension-reference.md](references/create-webflow-extension-reference.md)**: `create-webflow-extension` scaffolding CLI - **[references/webflow-cli-reference.md](references/webflow-cli-reference.md)**: Webflow CLI for serving, bundling, and listing extensions - **[references/elements-api.md](references/elements-api.md)**: Element manipulation and presets - **[references/styles-api.md](references/styles-api.md)**: Styling, breakpoints, pseudo-states - **[references/components-api.md](references/components-api.md)**: Component definitions and instances - **[references/pages-api.md](references/pages-api.md)**: Page and folder management - **[references/variables-api.md](references/variables-api.md)**: Design variables and collections - **[references/assets-api.md](references/assets-api.md)**: Asset upload and management - **[references/extension-utilities.md](references/extension-utilities.md)**: Site info, events, notifications, app discovery, authentication - **[references/error-handling.md](references/error-handling.md)**: Error codes and handling patterns - **[references/design-guidelines.md](references/design-guidelines.md)**: UI design for native Webflow look - **[references/register-app.md](references/register-app.md)**: Registering a Webflow App and configuring capabilities - **[references/marketplace-guidelines.md](references/marketplace-guidelines.md)**: Marketplace review criteria (safety, technical, design, branding) - **[references/app-submission-and-listing.md](references/app-submission-and-listing.md)**: Submitting your app and creating an effective listing - **[references/faq.md](references/faq.md)**: FAQ and troubleshooting for extensions, marketplace, and common issues ## Scripts - **`scripts/init-extension.sh`**: Quick project initialization wrapper around `create-webflow-extension` - **`scripts/validate-extension.py`**: Validate extension structure before bundling - **`scripts/search_references.py`**: Search reference files by tag, keyword, or list all with metadata ## Assets - **`assets/webflow-variables.css`**: CSS variables for Webflow's design system colors, typography, and shadows ## Best Practices 1. **Check element capabilities**: Always verify `element.children` before append/prepend, `element.textContent` before text operations 2. **Handle errors gracefully**: Use try/catch with `webflow.notify()` for user feedback 3. **Responsive design**: Test on multiple breakpoints when setting styles 4. **Use variables**: Leverage Webflow's CSS variables for consistent theming 5. **Subscribe to events**: Use Designer events to keep extension state in sync 6. **Appropriate sizing**: Use `webflow.resizeExtension()` for proper panel dimensions