Fields

JSON Field

The JSON field renders a code editor with JSON syntax highlighting in the admin UI. It stores any valid JSON value -- objects, arrays, strings, numbers, booleans, or null. Use this field for metadata, configuration blobs, API response snapshots, or any unstructured data that does not fit a fixed schema.

The underlying Convex validator is v.any(), wrapped in v.optional() unless marked as required.

Config options

OptionTypeRequiredDefaultDescription
requiredbooleanfalseMakes the field required in the schema and admin UI
readOnlybooleanfalseRenders the editor as non-editable
placeholderstringPlaceholder text shown when the editor is empty
labelstring | functionField nameCustom label for the admin UI
descriptionstringHelp text displayed below the field label
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 settings = defineVextroCollection({
  slug: "settings",
  label: "Settings",
  collectionType: "singleton",
  tableName: "settings",
  fields: {
    siteName: f.text({ required: true }),
    metadata: f.json({
      label: "Site Metadata",
      description: "Arbitrary key-value metadata for the site",
    }),
    apiConfig: f.json({
      label: "API Configuration",
      description: "Third-party API settings stored as JSON",
    }),
    rawResponse: f.json({
      readOnly: true,
      label: "Last API Response",
      description: "Read-only snapshot of the last webhook payload",
    }),
  },
});

Admin options

The JSON field editor validates that the entered content is valid JSON before saving. Invalid JSON is rejected with an inline error message. When readOnly is true, the editor displays the formatted JSON with syntax highlighting but prevents editing.

Tip

For structured JSON where you know the shape of the data, consider using f.group() or f.array() instead. These provide typed fields with individual labels, validation, and a better editing experience. Reserve f.json() for truly dynamic or unknown data structures.

Conditional display

advancedConfig: f.json({
  label: "Advanced Configuration",
  condition: { field: "showAdvanced", equals: true },
  description: "Raw JSON configuration for power users",
})
Previous
Rich Text
Next
Code