---
title: "image"
image: "https://adonia.pages.dev/og.png"
version: "next"
---

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

# image

<!-- Generated by `pnpm docs:fields` from packages/core/src/schema/fields/image.ts. Edit the TSDoc, not this file. -->

Drive-backed image upload.

| | |
| --- | --- |
| Builder | `F.image(attribute: string): ImageField` |
| Wire type key | `image` |
| Class chain | `ImageField` → `FileField` → `Field` |
| Detail projection | `image-entry` |
| Column counterpart | `image` cell, i.e. `C.image(attribute)` |

## Example

```ts
import { F } from '@adonia/core'

F.image('cover')
  .disk('s3').directory('covers').visibility('private')
  .dimensions({ minWidth: 1200, ratio: '16:9' })
  .previewWidths([320, 640, 1280])
  .imageEditor()
```

## Props

Beyond the shared [field DSL](/reference/fields#the-shared-field-dsl):

| Prop | Declared on | Behaviour |
| --- | --- | --- |
| `dimensions(spec: DimensionSpec): this` | `ImageField` | Declares the accepted pixel geometry, enforced server-side after the upload is stored (§19). |
| `imageEditor(): this` | `ImageField` | Enables the client-side crop/rotate editor (§7.3). A lazily imported chunk (§18): the flag exists so the base bundle does not carry an editor every panel would pay for and few would use. |
| `previewWidths(widths: readonly number[]): this` | `ImageField` | Candidate widths for the responsive preview (`srcSet`). |
| `disk(name: string): this` | `FileField` | Drive disk to store on; defaults to `config.uploads.disk`, and through that to the app's default disk (§4). |
| `directory(path: string): this` | `FileField` | Key prefix promoted objects land under, e.g. `contracts`. |
| `visibility(value: UploadVisibility): this` | `FileField` | Object visibility (§7.3). `'private'` is the safe choice and the only one a `Field.sensitive` field may take: a private object is only ever reachable through a short-lived signed URL minted for a live panel session (uploads/urls.ts). |
| `sensitive(): this` | `FileField` | Marks the value a secret (§19), refusing the combination the other declaration order would otherwise smuggle through. |
| `acceptedTypes(types: readonly string[]): this` | `FileField` | Media types the upload endpoint will accept, checked against the file's MAGIC BYTES (§19). Names, not extensions: `['image/png', 'image/webp']`. |
| `maxSize(megabytes: number): this` | `FileField` | Per-field size ceiling in megabytes. The effective limit is the SMALLER of this and `config.uploads.maxSizeMb` — a field can tighten the global cap, never lift it. |
| `multiple(): this` | `FileField` | Accepts several files; the form state becomes a key ARRAY (§7.3). |
| `preserveFilename(): this` | `FileField` | Stores the promoted object under a readable key derived from the sanitized uploaded filename instead of an opaque UUID alone. |
| `urlTtl(seconds: number): this` | `FileField` | Lifetime of the signed URLs this field's objects are served through, in seconds (default `SIGNED_URL_TTL_SECONDS` = 300). Only meaningful on a private disk; a public object's URL never expires. |

### Introspection

Read-only members this type adds — used by the compiler, the table derivation and
tests rather than by a schema author.

| Member | Declared on | Behaviour |
| --- | --- | --- |
| `get acceptedMediaTypes(): readonly string[]` | `ImageField` | Accepted types; the image set rather than `file`'s image-plus-PDF set. |
| `get dimensionRules(): DimensionRules \| undefined` | `ImageField` | Declared dimension rules, enforced by `verifyUpload` (§19). |
| `get responsiveWidths(): readonly number[]` | `ImageField` | Declared responsive candidate widths, ascending. |
| `get capabilities(): readonly string[]` | `FileField` | Protocol §4: `upload`, always — plus whatever the base declares. |
| `detailProps(): JsonObject` | `FileField` | Chrome plus the storage props an `image-entry`/`file-entry` is defined to read (protocol §8). |
| `get diskName(): string \| undefined` | `FileField` | Declared disk name, or `undefined` to fall back to `config.uploads.disk`. |
| `get directoryName(): string \| undefined` | `FileField` | Declared key prefix for promoted objects. |
| `get visibilityMode(): UploadVisibility` | `FileField` | Effective visibility. A `Field.sensitive` field is private even when nothing was declared — the flag is the stronger statement, and defaulting the other way would make secrecy depend on remembering a second call. |
| `get maxSizeMb(): number \| undefined` | `FileField` | Declared per-field size ceiling in megabytes, when any. |
| `get isMultiple(): boolean` | `FileField` | Whether the state is a key ARRAY (§7.3 `multiple()`). |
| `get preservesFilename(): boolean` | `FileField` | Whether promoted objects keep the sanitized uploaded filename. |
| `get signedUrlTtl(): number` | `FileField` | Signed-URL lifetime in seconds for this field's objects. |
| `uploadRules(globalMaxSizeMb: number): UploadRules` | `FileField` | The verification contract for one upload to this field (§19), resolving the field's own limits against the global `config.uploads.maxSizeMb`. |

## Validation

Vine base: `vine.string()`.

§11.1 mapping: `vine.string()` holding a Drive key, or
`vine.array(vine.string())` under `multiple()`. The bytes were verified
server-side at upload time; what the validator sees is a reference, and
the reference's provenance is checked in `FileField.defaultDehydrate`.

Contributed by `FileField.vineSchema()` in `packages/core/src/schema/fields/file.ts`. The shared modifiers (`required`, `nullable`, `requiredWhen`, `unique`, optionality) are applied on top by `Field.buildValidation`, and a `rules()` override replaces the base entirely — the validator compiler never branches on the field class.

## Declared in

- `packages/core/src/schema/fields/image.ts` — `ImageField`
- `packages/core/src/schema/fields/file.ts` — `FileField`

Source: https://adonia.pages.dev/reference/fields/image/index.mdx
