Fields
Fields are how your tool exchanges data with the user. They're declared in artifuncs.json under fields.input, fields.output, and settings. Each field has a type plus optional options.
Common options
These apply to every field type unless noted:
| Option | Type | Description |
|---|---|---|
label | string | Human-readable label shown above the field. Defaults to the field name. |
subtext | string | Small helper text shown under the label. Keep it short (roughly one line) — long subtext wraps and pushes the layout around. |
topRightHint | string | Small muted hint pinned to the top-right of the label row (e.g. "png, jpg, webp"). Good for format/limit reminders. |
placeholder | string | Placeholder text inside empty inputs (text-like fields only). |
default | any | Initial value. Type must match the field. |
readonly | boolean | User can read but not edit. Used for outputs. |
disabled | boolean | Field is greyed out and inert. |
copiable | boolean | Shows a copy-to-clipboard button. Useful on outputs. |
clearable | boolean | Shows a clear (×) button to wipe the value. |
subtext vs topRightHint: subtext is helper text near the field; topRightHint is a compact reminder pinned to the right edge of the label row — ideal for accepted formats or limits. Keep both short — a phrase, not a sentence — so they render on one line and don't crowd the form. Put longer guidance in userInstructions instead.
"avatar": {
"type": "file",
"label": "Source image",
"topRightHint": "png, jpg, webp",
"accept": "image/*"
}
text-field
Single-line text.
"name": {
"type": "text-field",
"label": "Your name",
"placeholder": "Ada Lovelace",
"default": ""
}
password
Single-line text that's masked as you type — same options as text-field. An eye button sits inside the field on the right; hold it down to reveal the value, release to re-mask. While the field is focused it also warns if Caps Lock is on. Use it for secrets like API keys or tokens so they aren't shoulder-surfed.
"apiKey": {
"type": "password",
"label": "API key",
"placeholder": "sk-…"
}
textarea
Multi-line text. Same options as text-field.
"notes": {
"type": "textarea",
"label": "Notes",
"placeholder": "Long-form text…"
}
number
Numeric input. Accepts integers or floats.
"precision": {
"type": "number",
"label": "Precision",
"default": 2
}
slider
Numeric slider with a draggable thumb. Set min / max / step to define the scale and an
optional unit appended to the readout.
"volume": {
"type": "slider",
"label": "Volume",
"min": 0,
"max": 100,
"step": 1,
"default": 65,
"unit": "%"
}
Range mode — give it a tuple default and you get two thumbs, one per end. The value
stays an ordered [lo, hi] pair (the thumbs can't cross), and process() receives the array:
"heightRange": {
"type": "slider",
"label": "Height range",
"min": 0,
"max": 100,
"default": [40, 50]
}
slider adds: min (default 0), max (default 100), step (default 1; floats like
0.05 work), unit (readout suffix, e.g. "%").
checkbox
Boolean toggle.
"verbose": {
"type": "checkbox",
"label": "Verbose output",
"default": false
}
date
Date picker. Stored as YYYY-MM-DD.
"due": {
"type": "date",
"label": "Due date",
"clearable": true
}
file
File upload (input) or downloadable file reference (output). On input, the user picks a file from disk and your code receives its filename; on output you return a file for the user to download. See Files for how to read and write the bytes from inside process.
| Option | Description |
|---|---|
accept | Comma-separated MIME types or extensions, e.g. "image/*,.csv". |
multiple | Accept multiple files. |
maxSize | Max bytes per file. |
maxFiles | Max number of files when multiple is set. Picking past the limit appends only what fits and shows an inline "N files maximum" error — it doesn't reject the whole selection. |
"upload": {
"type": "file",
"label": "Upload CSV",
"accept": ".csv",
"maxSize": 5242880
}
image
Image output. Place it in output and return the same { path, size } shape a file output uses — the UI fetches the bytes back from the sandbox and renders the picture inline, with edit and download buttons in the top-right corner. A plain URL or data: URI string works too, if your func produces the image without writing it to disk.
Edit opens a full editor in a modal: crop and straighten, finetune (brightness, contrast, saturation, exposure, temperature, gamma, clarity, vignette), filter presets, freehand and shape annotations, an erase brush that cuts the background out to transparency (with a restore brush to carve back), stickers, background fill, pixelated redaction, decorative frames, and output resize — with undo/redo throughout. Edits are local to the browser: they change what you see and what the download button hands you, but they never rewrite the value the func returned, so a run stays reproducible. The "edited" badge reverts them.
Used as an input it behaves exactly like file (a picker); set accept to keep the choice to images.
"output": {
"thumbnail": {
"type": "image",
"label": "Generated thumbnail"
}
}
Empty until the run produces something:
color
Single color picker. Stored as a hex string — #RRGGBB, or #RRGGBBAA when an alpha (< 1) is chosen via the picker's alpha slider.
| Option | Description |
|---|---|
showTextField | Show a hex input next to the swatch. |
showSwatches | Show preset color swatches. |
variant | "minimal" — just the rounded-square swatch, no hex text. |
"brand": {
"type": "color",
"label": "Brand color",
"default": "#FF3C00",
"showTextField": true
}
color-palette
A list of hex colors that the user can add to or remove from. Stored as an array of strings.
"palette": {
"type": "color-palette",
"label": "Palette",
"default": ["#FF3C00", "#1A0A05"]
}
list
Array of homogeneous items. Use itemType to declare the type of each item — any field type from this page is allowed.
| Option | Description |
|---|---|
itemType | Field type used for each item. Defaults to text-field. |
addValueButtonText | Custom label for the "add item" button. |
"keywords": {
"type": "list",
"label": "Keywords",
"itemType": "text-field",
"default": []
}
select
Dropdown for picking a single value from a fixed set. Declare the choices with options. Stored as a string.
| Option | Description |
|---|---|
options | Array of selectable values. |
All common options (subtext, default, readonly, disabled, clearable, copiable, …) apply.
"size": {
"type": "select",
"label": "Size",
"subtext": "Pick the output size",
"options": ["Small", "Medium", "Large"],
"default": "Medium"
}
multi-select
Dropdown for picking any number of values from a fixed set. Same options as select. Stored as an array of strings.
| Option | Description |
|---|---|
options | Array of selectable values. |
"toppings": {
"type": "multi-select",
"label": "Toppings",
"options": ["Cheese", "Mushroom", "Olives"],
"default": []
}
Outputs
Output fields use the same type values as inputs. They're rendered as read-only by default. Add copiable: true to make them easy to copy:
"output": {
"result": {
"type": "text-field",
"label": "Result",
"copiable": true
}
}
A textarea output auto-grows to fit the result (capped, then scrolls) and shows a drag handle so the reader can resize it:
A select / multi-select placed in output renders automatically as a read-only display — plain text for select, chips for multi-select — with no dropdown chrome. Add copiable: true for a copy button:
"output": {
"tags": {
"type": "multi-select",
"label": "Detected tags",
"options": ["nature", "landscape", "portrait"],
"copiable": true
}
}
Settings
Settings declared under the top-level settings block use the exact same field types and options as inputs. They appear in a separate panel and persist across runs.