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
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
required | boolean | false | Makes the field required in the schema and admin UI | |
readOnly | boolean | false | Renders the editor as non-editable | |
placeholder | string | Placeholder text shown when the editor is empty | ||
label | string | function | Field name | Custom label for the admin UI | |
description | string | Help text displayed below the field label | ||
condition | FieldCondition | Condition for showing or hiding this field | ||
sidebar | boolean | false | Place this field in the document sidebar | |
sidebarSection | string | Group under a named sidebar section | ||
listColumn | boolean | false | Show 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",
})