> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frontic.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Value Composer

The Value Composer transforms data by chaining together operations. Below is the full catalogue of available operations, grouped by category.

<Frame caption="Value Composer in the Data Feed merge step">
  <img src="https://mintcdn.com/frontic/34vlQbUxJTTktEkF/images/essentials/value-composer/composer-sync-merge-dark.png?fit=max&auto=format&n=34vlQbUxJTTktEkF&q=85&s=37436055737172531cec0a0da4a63da2" className="dark:block hidden max-w-md" alt="Value Composer" width="1430" height="1308" data-path="images/essentials/value-composer/composer-sync-merge-dark.png" />

  <img src="https://mintcdn.com/frontic/34vlQbUxJTTktEkF/images/essentials/value-composer/composer-sync-merge-light.png?fit=max&auto=format&n=34vlQbUxJTTktEkF&q=85&s=b82e9c2c0c2735c96805829d64191db2" className="dark:hidden block max-w-md" alt="Value Composer" width="1430" height="1308" data-path="images/essentials/value-composer/composer-sync-merge-light.png" />
</Frame>

## How operations are configured

A composer slot is a JSON object with a `source` discriminator. There are three sources you'll work with:

| Source       | Shape                                                                                 | Use for                                                                                        |
| ------------ | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `static`     | `{ "source": "static", "value": <literal>, "outputType": "<type>" }`                  | A fixed value baked into the configuration.                                                    |
| `data-field` | `{ "source": "data-field", "field": "path.to.field" }`                                | A reference to a field on the incoming feed record. Use `$item` / `$parent` inside iterations. |
| `composed`   | `{ "source": "composed", "composition": { "type": "<op>", "<param>": <slot>, ... } }` | An operation. Each parameter is itself a slot, so operations nest arbitrarily.                 |

Putting it together — a `concat` of `vendor.name` + `-` + `name`, the JSON the admin UI emits:

```json theme={"theme":"css-variables"}
{
  "source": "composed",
  "composition": {
    "type": "concat",
    "value1": { "source": "data-field", "field": "vendor.name" },
    "value2": { "source": "data-field", "field": "name" },
    "separator": { "source": "static", "value": " - " }
  }
}
```

The same recursion shows up everywhere: an `if` whose `then` is a `concat` of two static values, a `map` whose `mapFunction` is a `get` on `$item`, and so on. The catalogue below documents the parameter names and types each operation expects.

## Type compatibility

Every slot has a known output type, and operations declare what they accept:

* **Concrete types** (`number`, `string`, `boolean`, `array`, `object`) — the input slot must produce that exact type, or the configuration is invalid.
* **Type markers** (`T`, `K`, `V`) — polymorphic placeholders. The first input that fills a marker fixes the type for every other slot using the same marker. For example, `equals(value: T, compare: T)` accepts any type as long as `value` and `compare` agree — fill `value` with a string and `compare` is constrained to strings too.

The admin UI surfaces type mismatches in the slot's validation state — slots that can't yet produce the required type stay highlighted as invalid and the configuration won't save. There's no implicit coercion at runtime: a string flowing into a number slot raises an explicit type error rather than getting cast silently. When you actually want a cast, use `toString` / `toNumber` / `toBoolean` so the conversion is part of the chain. See [Error handling](#error-handling) for what happens when something does slip through.

## Array Operations

### `count`

Return the number of elements in an array.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to count elements in.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The element count.
</ResponseField>

### `filter`

Return the elements of an array that satisfy a condition. Each element is exposed as `$item` inside the filter expression.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to filter.
  </ParamField>

  <ParamField path="filterFunction" type="boolean" required>
    Boolean expression evaluated per element. Reference the current element with `$item`.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array<T>">
  The elements that returned `true` from `filterFunction`.
</ResponseField>

```json filter $item.id == "color" theme={"theme":"css-variables"}
{
  "source": "composed",
  "composition": {
    "type": "filter",
    "array": { "source": "data-field", "field": "properties" },
    "filterFunction": {
      "source": "composed",
      "composition": {
        "type": "equals",
        "value": { "source": "data-field", "field": "$item.id" },
        "compare": { "source": "static", "value": "color" }
      }
    }
  }
}
```

### `findFirst`

Return the first element of an array that satisfies a condition. Each element is exposed as `$item` inside the filter expression.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to search.
  </ParamField>

  <ParamField path="filterFunction" type="boolean" required>
    Boolean expression evaluated per element. Reference the current element with `$item`.
  </ParamField>
</Expandable>

<ResponseField name="output" type="T">
  The first matching element, or `null` if none match.
</ResponseField>

### `first`

Return the first element of an array.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to take the first element from.
  </ParamField>
</Expandable>

<ResponseField name="output" type="T">
  The first element, or `null` if the array is empty.
</ResponseField>

### `flatMap`

Apply a function to each element of an array, then flatten the resulting arrays into a single array. Each element is exposed as `$item` inside the map expression.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to map over.
  </ParamField>

  <ParamField path="mapFunction" type="array" required>
    Expression that returns an array per element. The returned arrays are concatenated.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The flattened result of all per-element mappings.
</ResponseField>

### `join`

Join an array of strings into a single string.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array of strings to join.
  </ParamField>

  <ParamField path="separator" type="string">
    Separator inserted between strings.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The joined string.
</ResponseField>

### `map`

Apply a function to each element of an array and return the resulting array. Each element is exposed as `$item` inside the map expression.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to map over.
  </ParamField>

  <ParamField path="mapFunction" type="T" required>
    Expression applied to each element.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The mapped array.
</ResponseField>

```json map images[] -> { url, alt } theme={"theme":"css-variables"}
{
  "source": "composed",
  "composition": {
    "type": "map",
    "array": { "source": "data-field", "field": "images" },
    "mapFunction": {
      "source": "composed",
      "composition": {
        "type": "object",
        "properties": {
          "url": { "source": "data-field", "field": "$item.path" },
          "alt": { "source": "data-field", "field": "$item.alt" }
        }
      }
    }
  }
}
```

### `merge`

Merge two arrays of scalar values into one. Values in `additional` are appended to `base`.

<Expandable title="Inputs">
  <ParamField path="base" type="array" required>
    The base array of scalar values.
  </ParamField>

  <ParamField path="additional" type="array" required>
    Additional values appended to the base array.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The merged array.
</ResponseField>

### `slice`

Extract a portion of an array.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array to slice.
  </ParamField>

  <ParamField path="start" type="number" required>
    Starting position (zero-based index).
  </ParamField>

  <ParamField path="length" type="number" required>
    Number of elements to extract.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The sliced array.
</ResponseField>

### `split`

Split a string into an array of strings.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to split.
  </ParamField>

  <ParamField path="separator" type="string" required>
    The separator to split on.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The resulting array of substrings.
</ResponseField>

### `unique`

Remove duplicate values from a scalar array, preserving the order of first occurrence.

<Expandable title="Inputs">
  <ParamField path="array" type="array" required>
    The array of scalar values to deduplicate.
  </ParamField>
</Expandable>

<ResponseField name="output" type="array">
  The deduplicated array.
</ResponseField>

## Comparison Operations

### `equals`

Compare two values for equality.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The first value.
  </ParamField>

  <ParamField path="compare" type="T" required>
    The second value.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when the values are equal.
</ResponseField>

### `greaterThan`

Compare two numbers; `true` when the first is greater than the second.

<Expandable title="Inputs">
  <ParamField path="value" type="number" required>
    The first number.
  </ParamField>

  <ParamField path="compare" type="number" required>
    The number to compare against.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when `value > compare`.
</ResponseField>

### `isEmpty`

Return whether a value is empty. Empty strings (after trim), empty arrays, `null`, and similar are `true`; numbers and `false` are not considered empty.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to check.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when the value is empty.
</ResponseField>

### `isNull`

Return whether a value is `NULL`.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to check.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when the value is `NULL`.
</ResponseField>

### `isScalar`

Return whether a value is a scalar (not an object or array). `null` is also considered scalar.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to check.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when the value is a scalar or `null`.
</ResponseField>

## Logic Operations

### `and`

Return `true` when all values are `true`.

<Expandable title="Inputs">
  <ParamField path="value1" type="boolean" required>
    The first value.
  </ParamField>

  <ParamField path="value2" type="boolean" required>
    The second value.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when both values are `true`.
</ResponseField>

### `if`

Branch the execution flow based on a condition.

<Expandable title="Inputs">
  <ParamField path="condition" type="boolean" required>
    The condition to evaluate.
  </ParamField>

  <ParamField path="then" type="T" required>
    Returned when the condition is `true`.
  </ParamField>

  <ParamField path="else" type="T" required>
    Returned when the condition is `false`.
  </ParamField>
</Expandable>

<ResponseField name="output" type="T">
  Either the `then` or the `else` value.
</ResponseField>

```json availability based on stock > 10 theme={"theme":"css-variables"}
{
  "source": "composed",
  "composition": {
    "type": "if",
    "condition": {
      "source": "composed",
      "composition": {
        "type": "greaterThan",
        "value": { "source": "data-field", "field": "stock" },
        "compare": { "source": "static", "value": 10 }
      }
    },
    "then": { "source": "static", "value": "in-stock" },
    "else": { "source": "static", "value": "low" }
  }
}
```

### `not`

Negate a boolean. Non-boolean values are coerced to `false` before negation.

<Expandable title="Inputs">
  <ParamField path="value" type="boolean" required>
    The value to negate.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  The negated value.
</ResponseField>

### `or`

Return `true` when at least one value is `true`.

<Expandable title="Inputs">
  <ParamField path="value1" type="boolean" required>
    The first value.
  </ParamField>

  <ParamField path="value2" type="boolean" required>
    The second value.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when either value is `true`.
</ResponseField>

### `xor`

Return `true` when exactly one value is `true` (exclusive or).

<Expandable title="Inputs">
  <ParamField path="value1" type="boolean" required>
    The first value.
  </ParamField>

  <ParamField path="value2" type="boolean" required>
    The second value.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when exactly one of the values is `true`.
</ResponseField>

## Math Operations

### `divide`

Divide two numbers (`numerator / denominator`).

<Expandable title="Inputs">
  <ParamField path="numerator" type="number" required>
    The numerator.
  </ParamField>

  <ParamField path="denominator" type="number" required>
    The denominator.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The quotient.
</ResponseField>

### `exponent`

Raise a number to the power of another (`base^exponent`).

<Expandable title="Inputs">
  <ParamField path="base" type="number" required>
    The base.
  </ParamField>

  <ParamField path="exponent" type="number" required>
    The exponent.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The result of the exponentiation.
</ResponseField>

### `multiply`

Multiply two numbers.

<Expandable title="Inputs">
  <ParamField path="value1" type="number" required>
    The first number.
  </ParamField>

  <ParamField path="value2" type="number" required>
    The second number.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The product.
</ResponseField>

## Object Operations

### `get`

Read a value from an object by key.

<Expandable title="Inputs">
  <ParamField path="key" type="string" required>
    The key of the field to access.
  </ParamField>

  <ParamField path="object" type="object" required>
    The object containing the field.
  </ParamField>
</Expandable>

<ResponseField name="output" type="T">
  The value at the given key, or `null` if the key isn't present.
</ResponseField>

### `object`

Compose an object by resolving each property's expression.

<Expandable title="Inputs">
  <ParamField path="properties" type="object" required>
    A map of property names to value expressions.
  </ParamField>
</Expandable>

<ResponseField name="output" type="object">
  The composed object.
</ResponseField>

## Text Operations

### `concat`

Concatenate two strings.

<Expandable title="Inputs">
  <ParamField path="value1" type="string" required>
    The first string.
  </ParamField>

  <ParamField path="value2" type="string" required>
    The second string.
  </ParamField>

  <ParamField path="separator" type="string">
    Separator inserted between the two strings.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The concatenated string.
</ResponseField>

### `contains`

Check whether a string contains another string, with optional case-insensitive matching.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to search in.
  </ParamField>

  <ParamField path="reference" type="string" required>
    The substring to search for.
  </ParamField>

  <ParamField path="caseInsensitive" type="boolean" default="false">
    Whether to perform case-insensitive matching.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  `true` when `value` contains `reference`.
</ResponseField>

### `length`

Return the number of characters in a string.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to measure.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The character count.
</ResponseField>

### `md5`

Hash a string with the MD5 algorithm. Useful for stable identifiers derived from input data.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to hash.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The MD5 hash as a 32-character hexadecimal string.
</ResponseField>

### `padLeft`

Pad a string on the left to a target length.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to pad.
  </ParamField>

  <ParamField path="length" type="number" required>
    The target length. Negative values disable padding.
  </ParamField>

  <ParamField path="char" type="string" required>
    The character to pad with.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The padded string.
</ResponseField>

### `padRight`

Pad a string on the right to a target length.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to pad.
  </ParamField>

  <ParamField path="length" type="number" required>
    The target length. Negative values disable padding.
  </ParamField>

  <ParamField path="char" type="string" required>
    The character to pad with.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The padded string.
</ResponseField>

### `replace`

Replace occurrences of a substring within a string.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The original string.
  </ParamField>

  <ParamField path="searchValue" type="string" required>
    The substring to search for.
  </ParamField>

  <ParamField path="replaceValue" type="string" required>
    The replacement substring.
  </ParamField>

  <ParamField path="caseSensitive" type="boolean">
    Whether the search is case-sensitive.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The string with replacements applied.
</ResponseField>

### `slugify`

Convert a string to a slug — lowercase, no spaces or special characters.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to convert.
  </ParamField>

  <ParamField path="separator" type="string">
    Separator used to replace spaces and special characters.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The slugified string.
</ResponseField>

### `substring`

Extract a substring from a string.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The source string.
  </ParamField>

  <ParamField path="start" type="number" required>
    Starting position.
  </ParamField>

  <ParamField path="length" type="number" required>
    Substring length.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The extracted substring.
</ResponseField>

### `toLower`

Convert a string to lowercase.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to convert.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The lowercased string.
</ResponseField>

### `toUpper`

Convert a string to uppercase.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to convert.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The uppercased string.
</ResponseField>

### `trim`

Remove whitespace from the beginning and end of a string.

<Expandable title="Inputs">
  <ParamField path="value" type="string" required>
    The string to trim.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The trimmed string.
</ResponseField>

## Transform Operations

### `toBoolean`

Convert a value to a boolean. Falsy values like `"false"`, `"0"`, and `[]` evaluate to `false`.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to convert.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  The boolean result.
</ResponseField>

### `toNumber`

Convert a value to a number. `NULL` becomes `0`.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to convert.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  The numeric result.
</ResponseField>

### `toString`

Convert a value to a string. `NULL` becomes an empty string.

<Expandable title="Inputs">
  <ParamField path="value" type="T" required>
    The value to convert.
  </ParamField>
</Expandable>

<ResponseField name="output" type="string">
  The string result.
</ResponseField>

## Utilities Operations

### `randomBoolean`

Return a random boolean. The `probability` controls how often `true` is returned, on a 0–100 scale.

<Expandable title="Inputs">
  <ParamField path="probability" type="number" required>
    Chance of returning `true`, from `0` (never) to `100` (always). Values outside the range are clamped.
  </ParamField>
</Expandable>

<ResponseField name="output" type="boolean">
  A random boolean.
</ResponseField>

### `randomNumber`

Return a random number between `min` and `max` (both inclusive). Set `precision` to `0` for integers, or higher for decimals (e.g. `2` produces values like `3.14`).

<Expandable title="Inputs">
  <ParamField path="min" type="number" required>
    Minimum value (inclusive).
  </ParamField>

  <ParamField path="max" type="number" required>
    Maximum value (inclusive).
  </ParamField>

  <ParamField path="precision" type="number" required>
    Decimal places (0–10). `0` returns an integer.
  </ParamField>
</Expandable>

<ResponseField name="output" type="number">
  A random number in the requested range.
</ResponseField>

## Error handling

The composer is strict about types and forgiving about absence:

* **Missing fields and keys resolve to `null`.** A `data-field` slot pointing at a path that doesn't exist on the current record returns `null`. `get` against a missing key returns `null`. The chain continues with `null` flowing through.
* **`null` inputs are absorbed where it makes sense.** Per-operation handling, not a global rule:
  * `concat` coalesces `null` inputs to empty strings.
  * `filter`, `map`, and other array operations coalesce a `null` array input to `[]` and return an empty array.
  * `get` against a `null` object returns `null`.
  * `findFirst` against an empty array returns `null`.
* **Type mismatches throw.** Operations don't implicitly coerce — passing a number into a string slot, or a non-array into `filter`'s `array` parameter, raises a runtime error and fails the sync. Use explicit `toString` / `toNumber` / `toBoolean` when you need a cast, so the conversion is visible in the chain.
* **Math has guard rails.** `divide` raises a runtime error on a zero denominator instead of producing `Infinity` or `NaN`.
* **Iteration context has a limit.** `filter` and `map` populate `$item` (and `$parent` when nested one level). Three or more nesting levels aren't supported and raise a runtime error — flatten with `flatMap` instead.

The [field-level debugger](/data-integration/value-composer#field-level-debugger) shows node-wise output for the configuration: when a chain produces an unexpected `null` or fails outright, the debugger pinpoints which operation introduced it. Use it before the configuration runs against real sync data.

Configuration errors that the type system can catch — an invalid operation type, a slot whose output can't satisfy the parent's expected type, a missing required parameter — show as inline validation on the affected slot in the admin UI; the configuration won't save until they're resolved. Backend resolution carries equivalent runtime checks as a backstop, raising explicit exceptions if an invalid configuration somehow reaches it.
