> This page is for Designer API.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.webflow.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.webflow.com/_mcp/server.

# Create a prop (Beta)

> Creates a new prop on a component

## `component.createProp(options)`

Creates a new prop on a component.
This mirrors the "Create new prop" action in the component props panel in the Webflow Designer.

If a prop with the same name already exists in the same group, the name is automatically incremented.
For example, `Heading` becomes `Heading 2`.

To create multiple props at one time, use [`component.createProps()`](/designer/reference/managing-components/create-props).

> **Beta**
>
> These methods are in public beta and may change with future releases.

### Syntax

```typescript
component.createProp(options: CreatePropOptions): Promise<Prop>
```

The `CreatePropOptions` type is a discriminated union on the `type` field:

```typescript
interface CreatePropCommon {
  /** Display name for the prop. Auto-incremented on name conflicts within the same group. */
  name: string;
  /** Group name. Props with the same group appear together in the props panel. */
  group?: string;
  /** Tooltip text shown on hover in the props panel. */
  tooltip?: string;
}

interface CreateTextContentProp extends CreatePropCommon {
  type: 'textContent';
  /** Whether the text input supports multiple lines. */
  multiline?: boolean;
  defaultValue?: string;
}

interface CreateStringProp extends CreatePropCommon {
  type: 'string';
  defaultValue?: string;
}

interface CreateRichTextProp extends CreatePropCommon {
  type: 'richText';
  defaultValue?: { innerText: string };
}

interface CreateLinkProp extends CreatePropCommon {
  type: 'link';
  defaultValue?:
    | { mode: 'url' | 'phone'; to?: string; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' }
    | { mode: 'page'; to?: { pageId: string }; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' }
    | { mode: 'pageSection'; to?: { fullElementId: { element: string; component: string } }; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' }
    | { mode: 'email'; to?: string; emailSubject?: string; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' }
    | { mode: 'file'; to?: { assetId: string }; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' }
    | { mode: 'collectionPage'; to?: { pageSlug: string }; openInNewTab?: boolean; rel?: 'preload' | 'prefetch' | 'prerender' };
}

interface CreateImageAssetProp extends CreatePropCommon {
  type: 'imageAsset';
  /** Default asset ID. */
  defaultValue?: string;
}

interface CreateVideoProp extends CreatePropCommon {
  type: 'video';
  defaultValue?: {
    src?: string;
    title?: string;
  };
}

interface CreateNumberProp extends CreatePropCommon {
  type: 'number';
  min?: number;
  max?: number;
  /** Number of decimal places allowed. */
  decimals?: number;
  defaultValue?: number;
}

interface CreateBooleanProp extends CreatePropCommon {
  type: 'boolean';
  /** Label shown when the value is true. */
  trueLabel?: string;
  /** Label shown when the value is false. */
  falseLabel?: string;
  defaultValue?: boolean;
}

interface CreateIdProp extends CreatePropCommon {
  type: 'id';
  /**
   * Default ID value. Normalized on the host side: invalid characters are stripped,
   * spaces become hyphens, and the result is lowercased.
   * The response returns the normalized value.
   */
  defaultValue?: string;
}

interface CreateAltTextProp extends CreatePropCommon {
  type: 'altText';
  /**
   * Default alt text value. Accepts a custom string, null, or the special strings
   * "decorative" (marks the image as decorative) and "inherit" (inherits alt text from the asset).
   */
  defaultValue?: string | null;
}

type CreatePropOptions =
  | CreateTextContentProp
  | CreateStringProp
  | CreateRichTextProp
  | CreateLinkProp
  | CreateImageAssetProp
  | CreateVideoProp
  | CreateNumberProp
  | CreateBooleanProp
  | CreateIdProp
  | CreateAltTextProp;
```

### Parameters

* **`options`** : *CreatePropOptions* — An object specifying the new prop. The shape varies by `type`:

  **Common fields (all types):**

  * **`type`**: *string* — The prop type. Supported values: `'textContent'`, `'string'`, `'richText'`, `'imageAsset'`, `'link'`, `'video'`, `'number'`, `'boolean'`, `'id'`, `'altText'`.
  * **`name`**: *string* — The display name for the prop.
  * **`group`**: *string* — (optional) The group name. Props with the same group appear together in the props panel. Props without a group appear before grouped props.
  * **`tooltip`**: *string* — (optional) Tooltip text shown on hover in the props panel.
  * **`defaultValue`**: varies by type — (optional) The default value for the prop. The shape depends on the prop type (see type-specific fields below).

  **Type-specific fields:**

  * **`multiline`**: *boolean* — (`'textContent'` only, optional) Whether the text input supports multiple lines.
  * **`min`**: *number* — (`'number'` only, optional) Minimum allowed value.
  * **`max`**: *number* — (`'number'` only, optional) Maximum allowed value.
  * **`decimals`**: *number* — (`'number'` only, optional) Number of decimal places allowed.
  * **`trueLabel`**: *string* — (`'boolean'` only, optional) Label shown when the value is `true`.
  * **`falseLabel`**: *string* — (`'boolean'` only, optional) Label shown when the value is `false`.

  **`link` prop `defaultValue` fields:**

  The `defaultValue` for a `'link'` prop is a discriminated union on the `mode` field.
  The shape of `to` depends on the `mode`:

  | `mode`               | `to` shape                                                  |
  | :------------------- | :---------------------------------------------------------- |
  | `'url'` \| `'phone'` | `string`                                                    |
  | `'page'`             | `{ pageId: string }`                                        |
  | `'pageSection'`      | `{ fullElementId: { element: string; component: string } }` |
  | `'email'`            | `string`                                                    |
  | `'file'`             | `{ assetId: string }`                                       |
  | `'collectionPage'`   | `{ pageSlug: string }`                                      |

  Additional fields available on all `mode` values:

  * **`openInNewTab`**: *boolean* — (optional) Whether the link opens in a new tab.
  * **`rel`**: *string* — (optional) Resource hint. Supported values: `'preload'`, `'prefetch'`, `'prerender'`.

  The `'email'` mode also supports:

  * **`emailSubject`**: *string* — (optional) The subject line for the email link.

### Returns

**Promise\<*Prop*>**

A Promise that resolves to the newly created `Prop` object with computed binding metadata.

```typescript
interface Prop {
  /** Unique prop ID. */
  id: string;
  /** The prop type. */
  type: 'textContent' | 'string' | 'richText' | 'imageAsset' | 'link' | 'video' | 'number' | 'boolean' | 'id' | 'altText';
  /** The binding value type, derived from the prop type. */
  valueType: BindableValueType;
  /** Value types that this prop can bind to. */
  bindableTo: readonly BindableValueType[];
  /** Display name (may be auto-incremented if there was a name conflict). */
  name: string;
  /** Group name, or null if ungrouped. */
  group: string | null;
  /** Tooltip text, or null if not set. */
  tooltip: string | null;
  /** Default value, or null if not set. */
  defaultValue: unknown | null;
  // Type-specific settings, included when applicable:
  multiline?: boolean;   // textContent
  min?: number;          // number
  max?: number;          // number
  decimals?: number;     // number
  trueLabel?: string;    // boolean
  falseLabel?: string;   // boolean
}
```

The following table shows how each prop type maps to `valueType` and `bindableTo`:

| `type`        | `valueType`   | `bindableTo`                                           |
| :------------ | :------------ | :----------------------------------------------------- |
| `textContent` | `textContent` | `['string', 'textContent', 'altText', 'id']`           |
| `string`      | `string`      | `['string', 'textContent', 'altText', 'id']`           |
| `richText`    | `richText`    | `['richText']`                                         |
| `link`        | `link`        | `['link']`                                             |
| `imageAsset`  | `imageAsset`  | `['image']`                                            |
| `video`       | `video`       | `['video']`                                            |
| `number`      | `number`      | `['number', 'string', 'textContent', 'altText', 'id']` |
| `boolean`     | `boolean`     | `['boolean', 'string', 'altText', 'id']`               |
| `id`          | `id`          | `['id']`                                               |
| `altText`     | `altText`     | `['altText']`                                          |

### Examples

Create a text content prop:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  const headingProp = await component.createProp({
    type: 'textContent',
    name: 'Heading',
    group: 'Content',
    defaultValue: 'Welcome to our site',
    tooltip: 'The main heading displayed in the hero section',
  })
  console.log(headingProp)
  /*
  {
    id: 'prop_1',
    type: 'textContent',
    valueType: 'textContent',
    bindableTo: ['string', 'textContent', 'altText', 'id'],
    name: 'Heading',
    group: 'Content',
    defaultValue: 'Welcome to our site',
    tooltip: 'The main heading displayed in the hero section'
  }
  */
}
```

Create a number prop with constraints:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  const opacityProp = await component.createProp({
    type: 'number',
    name: 'Overlay Opacity',
    group: 'Settings',
    min: 0,
    max: 100,
    decimals: 0,
    defaultValue: 50,
  })
  console.log(opacityProp)
  /*
  {
    id: 'prop_2',
    type: 'number',
    valueType: 'number',
    bindableTo: ['number', 'string', 'textContent', 'altText', 'id'],
    name: 'Overlay Opacity',
    group: 'Settings',
    defaultValue: 50,
    tooltip: null,
    min: 0,
    max: 100,
    decimals: 0
  }
  */
}
```

Create a boolean prop with labels:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  const showCtaProp = await component.createProp({
    type: 'boolean',
    name: 'Show CTA',
    group: 'Settings',
    trueLabel: 'Visible',
    falseLabel: 'Hidden',
    defaultValue: true,
  })
  console.log(showCtaProp)
  /*
  {
    id: 'prop_3',
    type: 'boolean',
    valueType: 'boolean',
    bindableTo: ['boolean', 'string', 'altText', 'id'],
    name: 'Show CTA',
    group: 'Settings',
    defaultValue: true,
    tooltip: null,
    trueLabel: 'Visible',
    falseLabel: 'Hidden'
  }
  */
}
```

Create a link prop:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  const ctaProp = await component.createProp({
    type: 'link',
    name: 'CTA Link',
    group: 'Content',
    defaultValue: {
      mode: 'url',
      to: 'https://example.com/signup',
      openInNewTab: true,
    },
  })
}
```

Create an `id` prop (the default value is normalized automatically):

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  const sectionIdProp = await component.createProp({
    type: 'id',
    name: 'Section ID',
    defaultValue: 'Hero Section',
  })
  console.log(sectionIdProp.defaultValue) // 'hero-section'
}
```

Create an `altText` prop using a special value:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  // 'decorative' marks the image as decorative (empty alt attribute)
  const decorativeAlt = await component.createProp({
    type: 'altText',
    name: 'Image Alt',
    defaultValue: 'decorative',
  })

  // 'inherit' inherits alt text from the asset
  const inheritAlt = await component.createProp({
    type: 'altText',
    name: 'Image Alt',
    defaultValue: 'inherit',
  })
}
```

Name conflicts auto-increment within the same group:

```typescript
const component = await webflow.getCurrentComponent()

if (component) {
  // 'Heading' already exists in group 'Content'
  const heading2 = await component.createProp({
    type: 'textContent',
    name: 'Heading',
    group: 'Content',
  })
  console.log(heading2.name) // 'Heading 2'
}
```

[Try this example](https://webflow.com/oauth/authorize?response_type=code\&client_id=19511de1ec410f9228d8dcbc9420e67916dea80d86d18f0c9a533eb475ea0f62)

### Designer Ability

| Designer Ability        | Permission | Locale | Branch | Workflow | Sitemode |
| :---------------------- | :--------- | :----- | :----- | :------- | :------- |
| **canModifyComponents** | any        | any    | any    | Canvas   | Design   |