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

# Define where apps render

> Define where UI can appear.

A slot is a named place for UI. It might be a side panel, part of a navbar, or a whole page. The green areas below are two slots:

<img src="https://mintcdn.com/tailorkit/1BWoeeBwHAUlM9Uc/images/slots-wireframe.svg?fit=max&auto=format&n=1BWoeeBwHAUlM9Uc&q=85&s=5f1129631499f7daa13c8de97d072081" alt="An app wireframe with a navbar slot and a side panel slot highlighted in green." width="760" height="400" data-path="images/slots-wireframe.svg" />

## Define slots

Give each area a name in your contract. This defines the two slots in the picture:

<Tabs>
  <Tab title="Zod">
    ```ts title="patchsmith.ts" theme={null}
    import { defineContract } from "patchsmith";
    import { z } from "zod";

    export const contract = defineContract({
      views: { "/": z.object({}) },
      slots: {
        navbar: { views: ["/"] },
        panel: { views: ["/"] },
      },
    });
    ```
  </Tab>

  <Tab title="ArkType">
    ```ts title="patchsmith.ts" theme={null}
    import { defineContract } from "patchsmith";
    import { type } from "arktype";

    export const contract = defineContract({
      views: { "/": type({}) },
      slots: {
        navbar: { views: ["/"] },
        panel: { views: ["/"] },
      },
    });
    ```
  </Tab>

  <Tab title="Valibot">
    ```ts title="patchsmith.ts" theme={null}
    import { defineContract } from "patchsmith";
    import * as v from "valibot";

    export const contract = defineContract({
      views: { "/": v.object({}) },
      slots: {
        navbar: { views: ["/"] },
        panel: { views: ["/"] },
      },
    });
    ```
  </Tab>
</Tabs>

<Tip>
  Include `/` in a slot's [views](/docs/concepts/views) so apps can provide default
  UI when no more specific view matches.
</Tip>

## Describe the space

Use `description` to tell app authors and agents where a slot appears:

```ts title="Inside your contract's slots" theme={null}
panel: {
  views: ["/"],
  description: "Right-hand side panel with independently scrolling content.",
},
page: {
  views: ["/"],
  description: "Main content area beside the host navigation.",
},
```

Agents read descriptions in the generated slot documentation while building apps. Your host controls the actual layout and dimensions.

<Tip>
  Describe the slot’s usable width and height at each breakpoint, including any
  padding or scrolling behavior. For example: “360 px wide on desktop, full
  width below 768 px, with independent scrolling.” This helps agents choose
  layouts that fit the available space.
</Tip>

## Allow multiple slot instances

By default, a slot has one instance per app, showing one view at a time. Set `multiple: true` when you want separate instances that can appear together.

Use multiple instances for tiles or pages that need separate metadata:

| Slot | Instances | Metadata could describe |
| - | - | - |
| Dashboard tile | A chart, a task list, and a summary | Each tile's position and size |
| Page | Reports, activity, and settings pages | A label and icon for each page's sidebar link |

One app can supply all of these instances. Each has its own key, metadata, and data. Tiles can appear together; page instances can each have a link and open separately.

```ts title="Inside your contract's slots" theme={null}
tile: { views: ["/"], multiple: true },
page: { views: ["/"], multiple: true },
```

For example, two page instances could have this metadata:

```json title="Page instances" theme={null}
[
  {
    "key": "reports",
    "metadata": { "label": "Reports", "icon": "chart" },
    "data": {}
  },
  {
    "key": "activity",
    "metadata": { "label": "Activity", "icon": "clock" },
    "data": {}
  }
]
```

Metadata lets you decide how to arrange tiles or build links. Patchsmith doesn't automatically position tiles or create routes from it.

## Context chooses the view

A panel can show an overview on a members list and details when a member is open. The slot selects the closest available [view](/docs/concepts/views) for the current context. Views change the UI inside an instance. The `multiple` option lets an app supply separate instances.

To supply UI and instances from an app, see [Write app UI](/docs/writing-apps/ui).

## SDK reference

Slots live in `defineContract({ slots })`, keyed by the names you choose.

| Field | Type | Meaning |
| - | - | - |
| `views` | `readonly string[]` | Required. Context paths declared in the contract's `views`. |
| `description` | `string` | Optional. Layout and sizing guidance for app authors and agents. Does not enforce dimensions. |
| `multiple` | `boolean` | Defaults to `false`. Set to `true` to allow independent instances from one app. |

```ts theme={null}
export type SlotDefinitions<TPath extends string = string> = Record<
  string,
  { views: readonly TPath[]; multiple?: boolean; description?: string }
>;
```

Each repeated instance has a stable, non-empty `key` unique within its view, a `metadata` object, and schema-validated `data`. See [Write app UI](/docs/writing-apps/ui#supply-several-instances) for the implementation.

## Frequently asked questions

Use views to adapt an instance to page context and metadata to describe its placement or label.

<AccordionGroup>
  <Accordion title="Do I need multiple instances to change UI between pages?">
    No. Views let one instance change with the current context. Enable
    `multiple` when you need distinct tiles, pages, or other entries from the
    same app.
  </Accordion>

  <Accordion title="Does metadata have a fixed format?">
    It's an object with the fields you agree to use, such as `label`, `icon`, or
    `position`. Your UI decides what those fields mean.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.