The designer is built around your layer types. Once you define those layer types, TypeScript can use them to narrow `Layer`, validate layer values, and catch invalid layer names before they reach the canvas.

The goal is to write the shape of each layer once, in your `layerTypes` array, and let the rest of the designer infer from it.

## Registering Your Layer Types

Layer type registration has two parts:

1. Create and export the `layerTypes` array that you pass to `<Designer />`.
2. Augment the `DesignerLayerTypes` interface with the inferred type map.

For example, if your app defines custom layers in `src/layers`, export the final array from a barrel file:

```ts
import { DEFAULT_LAYER_TYPES } from "@shadcn/designer";
import { shapeLayer } from "./shape";

export const layerTypes = [...DEFAULT_LAYER_TYPES, shapeLayer];
```

Then add a declaration file that connects that runtime array to the designer's TypeScript registry:

```tsx
import type { InferLayerTypes } from "@shadcn/designer";
import type { layerTypes } from "./layers";

declare module "@shadcn/designer" {
  interface DesignerLayerTypes extends InferLayerTypes<typeof layerTypes> {}
}
```

This follows a common TypeScript library pattern: your app augments a registry interface, and the library reads from that registry everywhere else.

  `declare module` requires an `interface` — type aliases can't be merged into an existing module. If your linter flags this as an empty interface, configure `@typescript-eslint/no-empty-object-type` with `allowInterfaces: "with-single-extends"` for declaration files.

Make sure the declaration file is included by your `tsconfig.json`. In most Vite, Next.js, and TypeScript apps, a `src/designer.d.ts` file is picked up automatically.

## Registering Keybindings

The same registry pattern is available for custom keybindings. Define your app's keybindings with the `Keybinding` type:

```ts
import { DEFAULT_KEYBINDINGS, type Keybinding } from "@shadcn/designer";

export const keybindings = {
  ...DEFAULT_KEYBINDINGS,
  TOGGLE_PANEL_LEFT: {
    key: "meta+b",
    label: "Ctrl B",
    labelMac: "⌘ B",
    description: "Toggle Left Panel",
    group: "Panels",
  },
} satisfies Record<string, Keybinding>;
```

Then add those names to the designer registry with `InferKeybindings`:

```tsx
import type { InferKeybindings, InferLayerTypes } from "@shadcn/designer";
import type { keybindings } from "./keybindings";
import type { layerTypes } from "./layers";

declare module "@shadcn/designer" {
  interface DesignerLayerTypes extends InferLayerTypes<typeof layerTypes> {}

  interface DesignerKeybindings extends InferKeybindings<typeof keybindings> {}
}
```

After that, APIs like `useShortcut` and `<Shortcut />` accept your custom keybinding names:

```tsx
useShortcut("TOGGLE_PANEL_LEFT", () => {
  setLeftPanelOpen((open) => !open);
});
```

Layer keybindings are also typed automatically. If you register a `shape` layer, `ADD_LAYER_SHAPE` becomes a valid `KeybindingName`.

## What You Get

After registration, APIs in `@shadcn/designer` use your layer map:

- **`Layer.type`** becomes a union of literal strings, like `"frame" | "group" | "text" | "image" | "shape"`.
- **`Layer.value`** narrows based on `type` — TypeScript can discriminate values in `switch`/`if` statements.
- **`Layer.meta`** narrows based on `type` (when defined in `defaultValues`).
- **`showForLayerTypes`** only accepts valid type names — typos are caught at compile time.
- **`defaultLayers`** validates that each layer's `value` matches its `type`.
- **`KeybindingName`** includes built-in names, registered custom keybinding names, and `ADD_LAYER_*` names for registered layers.

For example, if your `shape` layer uses `value: { type: "square" }`, a simple type guard gives you the typed value:

```tsx
const layer = selectedLayers[0];

if (layer.type !== "shape") {
  return null;
}

// layer.value is now typed as { type: string }.
console.log(layer.value.type);
```

The same registration also protects layer-specific UI:

```tsx
<DesignerPane showForLayerTypes={["shape"]}>
  <DesignerPaneTitle>Shape</DesignerPaneTitle>
  <DesignerPaneContent>
    <ActionShapeType />
  </DesignerPaneContent>
</DesignerPane>
```

If you mistype `"shape"` here, TypeScript reports it instead of silently hiding the pane at runtime.

Layer value and meta setters use the same registry. If you pass narrowed layer
objects, the new value is checked against those layers:

```tsx
const shapeLayers = selectedLayers.filter((layer) => layer.type === "shape");

setLayersValue(shapeLayers, { type: "circle" });
```

If you only have IDs, pass the layer type as a generic:

```tsx
setLayersValue<"shape">(selectedLayerIds, { type: "square" });
setLayersMeta<"shape">(selectedLayerIds, { source: "toolbar" });
```

## InferLayerTypes

`InferLayerTypes<T>` walks your `layerTypes` array and produces the registry map the designer needs:

```ts
type AppLayerTypes = InferLayerTypes<typeof layerTypes>;
```

Conceptually, that becomes:

```ts
type AppLayerTypes = {
  shape: {
    value: {
      type: string;
    };
  };
};
```

You typically don't need to use it directly — the snippet above is the only place it appears in most apps.

## Common Issues

- If `Layer.type` is still `string`, check that `src/designer.d.ts` is included by TypeScript and restart your editor's TypeScript server.
- If custom layer names are missing from the union, make sure the same `layerTypes` array is exported from `src/layers` and passed to `<Designer layerTypes={layerTypes}>`.
- Avoid annotating `layerTypes` as a wide `LayerType[]`; let TypeScript infer the array so literal `type` names are preserved.

## Performance Tip

If your project has a large number of layer types, prefer narrowing with type guards (`if (layer.type !== "shape") return`) over wide unions in function signatures. Narrowing early gives TypeScript less work to do and keeps editor performance snappy as your project grows.

## Next Steps

- See [Layers](/docs/concepts/layers) for the full walkthrough of creating a custom layer with type-safe values.
- Learn how to [use the unit system](/docs/concepts/unit-system).
- Browse the [type reference](/docs/reference/types) for `Layer`, `LayerType`, and related types.