View examples
Settings form
A prefilled form with typed fields, save/discard controls, and revision-checked writes.

A prefilled form with typed fields, save/discard controls, and revision-checked writes.
Build this example
- Read get_context and list_views. Choose an unused view name; if adapting the name, update every work’s trigger.view and all work bindings together. Inspect existing works before deploying.
- Deploy each manifest and self-contained JavaScript source below with deploy_function. No terminal, imports, dependencies, or bundler is needed. Record each returned deployment ID.
- Test unpublished data works with their sample input and a fresh idempotency key. Only run sample actions when requested; they write synthetic records. Do not pass placeholder IDs or stale revisions.
- Replace each source/action version in the view definition, including modal bindings, with the matching deployment ID. Call validate_view with the deployment object; fix any issues, then call deploy_view.
- Open the returned manageUrl in Shopify to inspect the draft. Test empty states, form errors and refresh behaviour. Publish only when requested, using the returned version and current publishedVersion. A published page consumes one slot; its modals do not.
Load
Work manifest
{
"name": "starter.starter-settings.load",
"title": "Load",
"feature": "starter_starter_settings",
"environment": "preview",
"trigger": {
"type": "view",
"view": "starter-settings",
"role": "data"
},
"permissions": {
"shopify": false
},
"inputSchema": {
"type": "object",
"properties": {
"filters": {
"type": "object"
},
"search": {
"type": "string"
},
"sort": {
"type": [
"object",
"null"
]
},
"after": {
"type": [
"string",
"null"
]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 25
}
},
"required": [],
"additionalProperties": false
}
}Self-contained JavaScript source
export default async ({db}) => {
const record = await db.collection("settings").get("preferences");
return record ? {...record.data, revision: record.revision} : {label: "Request a quote", enabled: true, responseDays: 3, revision: null};
};Sample invocation input
{
"filters": {},
"search": "",
"sort": null,
"after": null,
"limit": 25
}Save
Work manifest
{
"name": "starter.starter-settings.save",
"title": "Save",
"feature": "starter_starter_settings",
"environment": "preview",
"trigger": {
"type": "view",
"view": "starter-settings",
"role": "action"
},
"permissions": {
"shopify": false
},
"inputSchema": {
"type": "object",
"properties": {
"revision": {
"type": [
"integer",
"null"
]
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"enabled": {
"type": "boolean"
},
"responseDays": {
"type": "integer",
"minimum": 1,
"maximum": 30
}
},
"required": [
"revision",
"label",
"enabled",
"responseDays"
],
"additionalProperties": false
}
}Self-contained JavaScript source
export default async ({input, db}) => {
const settings = db.collection("settings");
const current = await settings.get("preferences");
if ((current?.revision ?? null) !== input.revision) return Response.json({error: "Settings changed. Refresh before saving."}, {status: 409});
const label = input.label.trim();
if (!label) return Response.json({error: "Enter a heading."}, {status: 422});
const data = {label, enabled: input.enabled, responseDays: input.responseDays};
const saved = current ? await settings.update(current.id, data, {revision: current.revision}) : await settings.create(data, {id: "preferences"});
return {revision: saved.revision};
};Sample invocation input
{
"revision": null,
"label": "Request a quote",
"enabled": true,
"responseDays": 3
}View definition
validate_view / deploy_view arguments
{
"baseVersion": null,
"definition": {
"apiVersion": 3,
"name": "starter-settings",
"title": "Request settings",
"sources": [
{
"id": "settings",
"work": "starter.starter-settings.load",
"version": "00000000-0000-4000-8000-000000000001"
}
],
"actions": [
{
"id": "save",
"label": "Save settings",
"work": "starter.starter-settings.save",
"version": "00000000-0000-4000-8000-000000000002",
"scope": "page",
"source": "settings",
"input": {
"revision": {
"source": "data",
"field": "revision"
},
"label": {
"source": "form",
"field": "label"
},
"enabled": {
"source": "form",
"field": "enabled"
},
"responseDays": {
"source": "form",
"field": "responseDays"
}
},
"fields": [
{
"name": "label",
"label": "Request heading",
"type": "text",
"required": true,
"maxLength": 100,
"initialField": "label"
},
{
"name": "enabled",
"label": "Accept requests",
"type": "checkbox",
"initialField": "enabled"
},
{
"name": "responseDays",
"label": "Response time (days)",
"type": "number",
"required": true,
"min": 1,
"max": 30,
"step": 1,
"initialField": "responseDays"
}
],
"refresh": [
"settings"
]
}
],
"layout": {
"type": "stack",
"main": [
"settingsCard"
],
"elements": {
"settingsCard": {
"type": "Section",
"props": {
"heading": "Request preferences"
},
"children": [
"form"
]
},
"form": {
"type": "Form",
"props": {
"action": "save"
}
}
}
}
}
}