{
  "title": "Window Sticker",
  "version": 1,
  "presets_enabled": true,
  "fields": [
    { "id": "year", "type": "number", "label": "Year", "required": true, "min": 1900 },
    { "id": "make", "type": "text", "label": "Make", "required": true, "autocomplete_key": "make" },
    { "id": "sale_price", "type": "currency", "label": "Sale Price", "required": true, "min": 0 },
    { "id": "condition", "type": "dropdown", "label": "Condition", "options": ["New", "Used", "CPO"] },
    {
      "id": "features", "type": "repeating-group", "label": "Key Features",
      "fields": [ { "id": "feature_text", "type": "text", "label": "Feature" } ]
    }
  ]
}

Top-level keys

Key Required Type Meaning
title yes string Form display name.
version no int Unused by the app; freeform.
fields yes array of object Field definitions, in display order.
presets_enabled no bool Default true.

Field keys

Key Applies to Type Meaning
id every field string Unique, snake_case.
type every field string text | number | currency | date | dropdown | checkbox | image | signature | drawing | repeating-group | label | color.
label every field string Display label - for label type, this is the displayed text.
required every field except label bool Default false.
min / max number, currency number Value range.
min_length / max_length text-like int Character count range.
regex text-like string Pattern the value must match.
options dropdown array of string Choice list.
autocomplete_key text-like string Key into autocomplete.json.
fields repeating-group array of object See Repeating Groups.
min_items / max_items repeating-group int Row-count bounds.
font_size / color label number / hex string Optional.
background_asset drawing string Project-relative reference image to draw over. Optional - omit for a blank canvas.
draw_size_px drawing [int, int] Capture resolution, [width, height].
draw_color drawing hex string "#RRGGBBAA" - ink RGB and alpha, baked into the captured PNG. Optional, default opaque black.
default_value date, color string For date: a JS expression (e.g. "Date.now()"), evaluated fresh each time the form opens. For color: a literal "#RRGGBB" hex string, used as-is - no evaluation. Optional either way.
hidden every field bool Default false. Skipped by the Input Form's own rendering entirely, but still fully participates in inputs/validation/presets - the only way a preset can drive a value the pipeline knows about without exposing a control for it. required is silently ignored when combined with this.

label fields never appear in the submitted data - not even as null. A drawing field's submitted value is a captured PNG file path, same shape as image/ signature. A color field's value is a plain "#RRGGBB" string, same convention used everywhere else in this app. See Input Form for what the user sees, and overlay.json for compositing a drawing field's own background_asset onto the page.