Fields

Image Field

The image field is a convenience wrapper around f.upload() that defaults to image MIME types. It renders an image-optimized upload widget with thumbnail previews. When used with relationTo, it integrates with the upload collection system for managed media. Without relationTo, it stores a plain string reference.

The underlying Convex validator is v.string() for single images or v.array(v.string()) for multiple, wrapped in v.optional() unless marked as required.

Config options

OptionTypeRequiredDefaultDescription
requiredbooleanfalseMakes the field required in the schema and admin UI
readOnlybooleanfalseRenders the field as non-editable
labelstring | functionField nameCustom label for the admin UI
descriptionstringHelp text displayed below the field label
relationTostringUpload collection to reference for managed media
acceptstring[]["image/*"]Accepted MIME types (e.g., ["image/jpeg", "image/png"])
maxSizenumberMaximum file size in bytes
displayPreviewbooleantrueShow a thumbnail preview of the uploaded image
hasManybooleanfalseAllow multiple image uploads
conditionFieldConditionCondition for showing or hiding this field
sidebarbooleanfalsePlace this field in the document sidebar
sidebarSectionstringGroup under a named sidebar section
listColumnbooleanfalseShow as a default column in list views

Example usage

import { f, defineVextroCollection } from "vextro";

export const products = defineVextroCollection({
  slug: "products",
  label: "Products",
  collectionType: "content",
  tableName: "products",
  fields: {
    name: f.text({ required: true }),
    thumbnail: f.image({
      relationTo: "media",
      required: true,
      label: "Product Image",
      accept: ["image/jpeg", "image/png", "image/webp"],
      maxSize: 5 * 1024 * 1024,
      listColumn: true,
      listColumnWidth: "small",
    }),
    gallery: f.image({
      relationTo: "media",
      hasMany: true,
      label: "Gallery Images",
      description: "Additional product photos",
    }),
    avatar: f.image({
      accept: ["image/jpeg", "image/png"],
      maxSize: 2 * 1024 * 1024,
      label: "Avatar",
      description: "Square image, max 2 MB",
    }),
  },
});

Admin options

The image field displays a thumbnail preview of the uploaded image by default. When relationTo is set, the field integrates with the upload collection, allowing editors to either upload a new image or select from previously uploaded media via a media browser.

When accept is configured, the file input restricts selectable file types. The default is ["image/*"], which accepts all image formats. Narrow this to specific formats like ["image/jpeg", "image/png"] when you need to enforce a particular format.

The maxSize option validates file size client-side before upload. Files exceeding the limit are rejected with an error message.

In list views with listColumn: true, the image renders as a small thumbnail for quick visual identification.

Conditional display

heroImage: f.image({
  relationTo: "media",
  label: "Hero Image",
  condition: { field: "layout", in: ["hero", "featured"] },
  description: "Large banner image for hero layouts",
})
Previous
Upload
Next
Array