---
title: SDK extensions
description: Add server behavior and keep field conversion explicit.
---

A `BacklitExtension` is a function that registers server behavior and returns
`{ name, version }`. Import the type from `@backlit/sdk/types`. Pass extension
functions to `defineApp({ extensions, areas })`.

An app runs each function identity once. A second app can run the same function
again. Registries and factory macros are process-wide, so extension changes
affect all apps in that process. Later registrations replace earlier ones.
Two functions with the same extension name both run and produce a warning.

## Factories and macros

`FieldsFactory`, `FiltersFactory`, `WidgetsFactory`, and `ChartsFactory` extend
`Macroable`. Use their static `macro` API to add factory methods. Declare the
new method through TypeScript module augmentation. Extend the matching open
protocol registry in `@backlit/contract`, then install a matching client
renderer. Runtime registration and type augmentation are both required.

## Remappers

`remappers` is the process-wide `FieldRemappers` instance. Use
`registerRole(role, map)` for a complete role map. Use
`registerRemappers(role, partialMap)` to replace entries in an existing role.
Registering replacements for an unknown role throws.

A `FieldRemapper` receives `(value, field, record, parent, report)`. Return the
converted value. Call `report(reason)` when conversion fails. The returned
`undefined` causes the value to be omitted. Preserve `null` when it is a valid
empty value. The remapper converts data; the client formats its display.

Built-in maps cover text, number, boolean, date, enum, and group fields for
`display` and `input`. Relation builders handle related records themselves.
A missing role handler reports a defect and uses the requested fallback role.
A missing fallback handler throws `E_MISSING_FIELD_REMAPPER`.

## Defect reporters

Use `.onDefect(reporter)` on a data block or form. A defect has a `reason` and
can include `field`, `kind`, `value`, and row `index`. The default
`warnOnDefect` writes a warning. A custom reporter can throw `new Error(defect.reason)` to stop on invalid
data during development.

An invalid declaration, duplicate name, missing required position, or invalid
target argument is an authoring error. These errors throw. A failed data
conversion is a defect. The block can keep its other valid values.

## Builder contracts

Import `TO_NODE`, `RESOLVE`, `RESOLVE_FOR`, `TO_RESPONSE`, `FIELD_NAME`,
`FIELD_VALUE`, `FIELD_ROW`, `VALUE_FOR`, `KEYWORD`, and `PARSE` from
`@backlit/sdk/symbols`. Import contract types from `@backlit/sdk/types`.
`Nodeable` creates a node synchronously. `Resolvable` creates it asynchronously
and can locate a zone. `Respondable` creates a response. Field builders carry
their field name and value type and convert record values through `VALUE_FOR`.

The generated [SDK API](/reference/api/sdk), [types](/reference/api/types), and
[symbols](/reference/api/symbols) include all exported declarations and helper
functions. Prefer public factories when you author an application.
See [Field roles](/advanced/field-roles) for a complete custom role.
