AviatoAviato
DeveloperPlugins

Configuration Fields

How a plugin declares user-editable settings, the input vocabulary, and how saved values reach the plugin process at runtime.

configuration is how a plugin asks the user for values it can't hardcode: API keys, regional preferences, glob exclusions, feature flags. The admin UI renders the declared fields as a form, persists the user's input against the plugin's row, and passes them into the plugin process through an environment variable on every start.

Declaring fields

configuration lives at the top level of plugin.json:

"configuration": [
  { "key": "tmdbApiKey", "label": "TMDb API Key", "input": "text", "required": false,
    "description": "Personal API key for The Movie Database; uses Aviato's shared key when blank" },
  { "key": "language",   "label": "Metadata language", "input": "text", "default": "en-US" },
  { "key": "extractGps", "label": "Extract GPS data",  "input": "toggle", "default": true }
]

Each entry is a ConfigurationField:

FieldTypeNotes
keystringThe field name. Must be unique within the array. The user's saved value lands at this key in the runtime config object.
labelstringDisplay label in the admin form.
inputFormFieldInput (optional)Widget type. See below. Defaults to text.
requiredboolean (optional)When true, the form refuses to save with the field empty.
defaultunknown (optional)Initial value when the user has not yet saved the form.
optionsunknown[] (optional)Choices for select and multi-select.
min / maxnumber (optional)Bounds for number and slider.
descriptionstring (optional)Helper text shown below the input.

Input vocabulary

The same enum drives library plugin form schemas via UI views and the manifest's configuration block (FormFieldInputSchema, exported from @aviato/plugin-sdk):

inputRenders asSaved value type
textSingle-line textstring
numberNumeric spinnernumber
toggleSwitchboolean
selectSingle-choice dropdownone of options[]
multi-selectMulti-choice dropdownoptions[] subset
string-listEditable list of free-form stringsstring[]
file-pathPath picker (rendered as text)string
colorColor swatchstring (hex)
sliderRange slider with min/maxnumber

A field with options should also set input: 'select' or 'multi-select'. The renderer falls back to a text input otherwise.

What the user sees

Every plugin's configuration is rendered as a form on its admin page (/admin/plugins/<id>). Saving the form persists the values, restarts the plugin process, and surfaces a "configuration changed" entry in the plugin event log.

For the user-facing copy:

  • Keep label short and noun-phrase-shaped: "TMDb API Key", "Metadata language".
  • Use description for the why: when to set it, what happens when it's blank, how to obtain a credential.
  • Mark fields required only when the plugin genuinely cannot run without them. A required field that has a default is a contradiction.

How values reach the plugin

Aviato serializes the saved configuration as JSON and injects it into the plugin process's environment as AVIATO_PLUGIN_CONFIG when spawning the process:

env: {
  ...process.env,
  AVIATO_PLUGIN_CONFIG: JSON.stringify(pluginConfig),
}

Inside the plugin you parse it once at startup:

function parseJsonConfig (value: string | undefined): Record<string, unknown> {
  if (!value) return {}
  try { return JSON.parse(value) as Record<string, unknown> } catch { return {} }
}

const config = parseJsonConfig(process.env.AVIATO_PLUGIN_CONFIG)
const tmdbApiKey = (config.tmdbApiKey as string | undefined) ?? DEFAULT_TMDB_API_KEY
const language   = (config.language as string)               ?? 'en-US'

Patterns to follow:

  • Read once, at module top. The config never changes during a single plugin process's lifetime; when the user saves new values, Aviato restarts the plugin, which means re-importing your module with the new env var. Don't rebuild the config object on every RPC.
  • Treat the parsed value as untrusted. Even though it came from Aviato, a downgrade or a hand-edited DB row could include shapes you don't expect. Use Zod or simple typeof guards.
  • Provide sensible defaults. Unset is the common case for optional fields (required: false with no default). Default in the plugin, not in the manifest, when the right value depends on plugin logic.
  • Treat sensitive values like secrets. Aviato stores them as plain text in the database today. Don't log them, don't echo them back in events, and don't return them from getSchema().

Capability-handler config

Some capability handlers also receive the live config as a parameter. For example, filesystem.scan(config, ...) is called with the same JSON object you'd see in AVIATO_PLUGIN_CONFIG. Prefer the parameter when it's available, since it lets Aviato (in theory) re-call the method with a different config without restarting the process. For all other code paths, the env-var form is canonical.

Validation

ConfigurationFieldSchema is intentionally loose. It does not validate that default, options, min, and max are coherent with the chosen input. It's the plugin author's job to keep them consistent, and Aviato's job to render the form sensibly when they are not. This loose typing also keeps the schema forward-compatible: adding new input types to the SDK doesn't break existing plugins, since the manifest accepts any string and unrecognized inputs fall through to a text field.

Worked examples

Simple text and toggle

"configuration": [
  { "key": "extractGps", "label": "Extract GPS data", "description": "Read GPS coordinates from EXIF data", "input": "toggle", "default": true },
  { "key": "extractCameraInfo", "label": "Extract camera info", "input": "toggle", "default": true }
]

Multi-select language preference

"configuration": [
  {
    "key": "preferredLanguages",
    "label": "Preferred subtitle languages",
    "input": "multi-select",
    "options": ["en", "ja", "es", "fr", "de"],
    "default": ["en"]
  }
]

Glob exclusions

"configuration": [
  {
    "key": "excludePatterns",
    "label": "Exclude patterns",
    "description": "Glob patterns to exclude from scanning",
    "input": "string-list"
  }
]

See also

  • Plugin manifest
  • UI schemas reuses the same field vocabulary for per-library forms emitted via the ui view system.
  • aviato-tmdb and aviato-indexer-photos are reference plugins that parse AVIATO_PLUGIN_CONFIG.

On this page