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

# Upload Field

> Select one or more records from FrogBot file collections with Upload fields.

The Upload field selects a record from a file collection and displays its preview in the admin panel. Use it for featured images, downloadable documents, audio, video, or other assets.

FrogBot adds no file collection, so declare one first. The smallest configuration marks a `files` collection with `file: true`:

```ts theme={"theme":"tokyo-night"}
import type { CollectionConfig } from 'frogbot'

export const Files: CollectionConfig = {
  slug: 'files',
  file: true,
  fields: [],
}
```

Then point an Upload field at it:

```ts theme={"theme":"tokyo-night"}
import type { Field } from 'frogbot'

export const FeaturedImageField: Field = {
  name: 'featuredImage',
  type: 'upload',
  relationTo: 'files',
}
```

Every slug in `relationTo` must identify a file collection. See [Files and
uploads](https://docs.frogbot.ai/upload/files.md).

## Config options

| Option | Type | Default | Description |
| - | - | - | - |
| `name` | `string` | Required | Property name used in stored records and APIs. See [field names](https://docs.frogbot.ai/fields/overview.md#field-names). |
| `type` | `'upload'` | Required | Selects the Upload field. |
| `relationTo` | `string \| string[]` | Required | Slug of the file collection. See [Polymorphic uploads](#polymorphic-uploads). |
| `filterOptions` | `Where \| (args) => boolean \| Where \| Promise<boolean \| Where>` | — | Limits selectable files and validates submitted values. See [Filtering upload options](#filtering-upload-options). |
| `hasMany` | `boolean` | `false` | Stores an ordered array of files instead of one. |
| `minRows` | `number` | — | Minimum number of files when a value is present. Only with `hasMany: true`. |
| `maxRows` | `number` | — | Maximum number of files when a value is present. Only with `hasMany: true`. |
| `maxDepth` | `number` | Request depth | Maximum population depth for this field, regardless of the remaining request depth. See [depth](https://docs.frogbot.ai/queries/depth.md#max-depth). |
| `displayPreview` | `boolean` | The file collection's setting | Whether the field shows a file preview. See [File collection options](https://docs.frogbot.ai/upload/overview.md#collection-upload-options). |
| `graphQL` | `{ complexity?: number }` | `{ complexity: 10 }` | Query complexity used only when an application mounts its own GraphQL executor. FrogBot does not ship a GraphQL request handler. |
| `label` | `string \| Record<string, string> \| (({ i18n, t }) => string) \| false` | Generated from `name` | Label shown in the admin panel. Use an object keyed by language code for translations, or `false` to hide the label. |
| `required` | `boolean` | `false` | Rejects an empty value in the default validation. |
| `unique` | `boolean` | `false` | Creates a unique database index for the field path. See [indexes](https://docs.frogbot.ai/database/indexes.md). |
| `index` | `boolean` | `false` | Creates a database index for faster queries. `unique` already creates one. |
| `localized` | `boolean` | `false` | Stores one value per configured locale. Ignored without [localization](https://docs.frogbot.ai/configuration/localization.md) or inside a localized parent. |
| `defaultValue` | `string \| number \| (string \| number)[]` or `({ locale, req, user }) => value` | — | Value used when the field has no value. See [default values](https://docs.frogbot.ai/fields/overview.md#default-values). |
| `validate` | `Validate` | Built-in validator | Replaces the built-in validator. See [validation](https://docs.frogbot.ai/fields/overview.md#validation). |
| `hooks` | `{ beforeValidate, beforeChange, afterChange, afterRead, beforeDuplicate }` | — | Arrays of `FieldHook` functions for each phase. See [field hooks](https://docs.frogbot.ai/hooks/fields.md). |
| `access` | `{ create, read, update }` | Allowed | `FieldAccess` functions for each operation. See [field access control](https://docs.frogbot.ai/access-control/fields.md). |
| `hidden` | `boolean` | `false` | Removes the field from API responses and the admin panel while keeping stored data. |
| `saveToJWT` | `boolean \| string` | `false` | In an auth-enabled collection, copies the value into the user's token. A string sets the token key. See [token data](https://docs.frogbot.ai/authentication/token-data.md). |
| `virtual` | `boolean \| string` | `false` | `true` skips database storage; a string reads a value through a relationship path. Virtual fields are read-only in the admin panel unless `admin.readOnly` is `false`. See [linking virtual fields](https://docs.frogbot.ai/fields/relationship.md#linking-virtual-fields-with-relationships). |
| `disableDuplicate` | `boolean` | `false` | Leaves the value out when a document is duplicated, so the copy uses `defaultValue`. |
| `admin` | `object` | — | Admin-panel options. See [Admin options](#admin-options). |
| `custom` | `Record<string, any>` | — | Server-only metadata for your own code and plugins. Use `admin.custom` for data the browser also needs. |
| `jsonSchema` | `Array<({ jsonSchema }) => JSONSchema4>` | — | Functions that modify the JSON Schema used by [type generation](https://docs.frogbot.ai/typescript/generating-types.md). |

## Admin options

Upload fields support the standard [field admin options](https://docs.frogbot.ai/fields/overview.md#admin-options), plus these options:

| Option | Type | Default | Description |
| - | - | - | - |
| `allowCreate` | `boolean` | `true` | Lets editors upload a new file from the field. |
| `isSortable` | `boolean` | `true` | Lets editors reorder files when `hasMany` is `true`. |
| `sortOptions` | `string \| Record<string, string>` | — | Accepted for parity with Relationship fields, but the upload selector currently ignores it. |

## Custom file collection

To use a slug other than `files`, mark one collection with `file: true`. FrogBot enables its required upload behavior while preserving your fields and settings:

```ts theme={"theme":"tokyo-night"}
import type { CollectionConfig } from 'frogbot'

export const Media: CollectionConfig = {
  slug: 'media',
  file: true,
  fields: [
    {
      name: 'alt',
      type: 'text',
    },
  ],
}

export const Pages: CollectionConfig = {
  slug: 'pages',
  fields: [
    {
      name: 'backgroundImage',
      type: 'upload',
      relationTo: 'media',
      required: true,
    },
  ],
}
```

Mark exactly one collection with `file: true`. FrogBot merges its required upload configuration into that collection. Without a marked collection, FrogBot adds none, and an Upload field whose `relationTo` names a missing collection stops startup.

Do not use `upload: true` to select the FrogBot file collection. If the marked collection also sets `upload: false`, configuration fails.

## Filtering upload options

Use `filterOptions` to limit files in the selector and validate submitted relationships. It accepts a [query constraint](https://docs.frogbot.ai/queries/overview.md), or a callback that returns a constraint, `true` to allow every record, or `false` to allow none.

The callback receives:

| Option | Type | Default | Description |
| - | - | - | - |
| `relationTo` | `string` | — | File collection slug currently being filtered. |
| `data` | `any` | — | Full data for the record being edited. It is an empty object in a list-view filter. |
| `siblingData` | `unknown` | — | Data from fields under the same parent. It is an empty object in a list-view filter. |
| `blockData` | `any` | — | Data for the nearest parent block. It is `undefined` outside a block and in a list-view filter. |
| `id` | `string \| number` | — | Current record ID, or `undefined` during creation and in a list-view filter. |
| `user` | `Partial<User> \| null` | — | Current authenticated user. |
| `req` | `FrogBotRequest` | — | Current request, including `req.frogbot`, `req.user`, `req.locale`, and request context. |

For example, limit the default file collection to images:

```ts theme={"theme":"tokyo-night"}
import type { Field } from 'frogbot'

export const ImageField: Field = {
  name: 'image',
  type: 'upload',
  relationTo: 'files',
  filterOptions: {
    mimeType: { contains: 'image' },
  },
}
```

When combining `filterOptions` with custom validation, make the validation
enforce every constraint your application requires. The selector filter alone
is not a replacement for custom validation logic.

## Bidirectional relationships

An Upload field stores the connection on the record containing it. The file record does not automatically list every record that uses it.

Add a [Join field](https://docs.frogbot.ai/fields/join.md) to the file collection when editors or API consumers need to traverse the relationship in both directions.

## Polymorphic uploads

The underlying field shape accepts an array in `relationTo`, but every target must be an active file collection. FrogBot has exactly one file collection, so polymorphic Upload fields are not supported. Use separate Upload fields when records need distinct asset roles.

Use `hasMany` to select multiple records from the active file collection:

```ts theme={"theme":"tokyo-night"}
import type { Field } from 'frogbot'

export const MediaField: Field = {
  name: 'media',
  type: 'upload',
  relationTo: 'files',
  hasMany: true,
}
```

For a custom file collection, replace `files` with the slug of the collection marked `file: true`.

## Custom components

Override the field through `admin.components`. A custom component can wrap FrogBot's default upload control:

### Server component

```tsx theme={"theme":"tokyo-night"}
import { UploadField } from '@frogbotai/ui/admin'
import type { UploadFieldServerProps } from 'frogbot'

export const CustomUploadFieldServer = ({
  clientField,
  path,
  permissions,
  schemaPath,
}: UploadFieldServerProps) => (
  <UploadField
    field={clientField}
    path={path}
    permissions={permissions}
    schemaPath={schemaPath}
  />
)
```

### Client component

```tsx theme={"theme":"tokyo-night"}
'use client'

import { UploadField } from '@frogbotai/ui/admin'
import type { UploadFieldClientProps } from 'frogbot'

export const CustomUploadFieldClient = (props: UploadFieldClientProps) => (
  <UploadField {...props} />
)
```


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