generate-coloring-page

activev2026.09.16

Generate a printable coloring page: clean black line art on a white background (no fills, no shading), post-processed for paper or tablet, quality-gated against KDP print and WCAG touch standards, plus classifier-produced catalog metadata.

This page renders the template’s published registry entry — the contract itself, not a description of it. Immutable versions; sealed properties exist but are not public.

What you provide — intake contract

FieldTypeRequiredDefaultDescription
promptstringrequired—Subject of the coloring page
styleenum
coloring
optional"coloring"Coloring style
aspectRatioenum
1:13:44:33:22:316:99:16
required"3:4"Aspect ratio
qualityenum
lowmediumhighxhighmax
optional"medium"Render quality tier
sizestringoptional""Exact WIDTHxHEIGHT for this render, e.g. '2560x1440'. Empty (the default) means aspectRatio decides. Both edges must be multiples of 16, neither over 3840, the ratio between 1:3 and 3:1, and the total pixels between 655,360 and 8,294,400. Above 2560x1440 the provider calls results experimental — allowed, more variable.
detailenum
printapp
optional"print"Which product this page is: 'print' (paper — bold strokes, clear margins) or 'app' (tablet — sealed contours, tappable regions)
renderModelstringoptional"openai/gpt-image-2.5-flare-2026-09-08"Registry id of the image model to render with. Print: openai/gpt-image-2.5-flare-2026-09-08. App: openai/gpt-image-2.5-sunburst-2026-09-08. An unregistered id falls back to the bound provider.
postProcessbooleanoptionaltrueThreshold, seal gaps, raise strokes to the floor, despeckle. Off skips with provenance; the audit still runs on the raw render.
lineArtAuditModeenum
enforcereportoff
optional"enforce"Quality gate: 'enforce' (default) fails a page that would print or fill badly so the order re-renders it, 'report' records metrics only, 'off' skips the audit
categoriesstringrequired—Comma-separated category slugs the classifier must choose from (empty fails the run in preflight)
textPolicyenumoptional""Per-item text contract: none = text forbidden; exact = must match expectedText; freeform = text allowed, judged on legibility/spelling only. Empty derives from textBearing (true=exact, false=freeform). Use 'none' deliberately, for assets that must carry no characters at all.
textBearingbooleanoptionalfalseTrue when the asset must carry legible text (the OCR gate then checks it)
expectedTextstringoptional""The EXACT text the asset must carry; leave empty unless textPolicy is 'exact'

How it runs — step topology

1
Render line artimageimageGenerator
promptTemplate
2
Post-process line arttool
3
Audit line arttool
4
Text gatellmtextGategate

Hard gate: the run fails unless pass — OCR text gate rejected the render

systempromptTemplatemaxTokens
5
Classify assetllmclassifier
systempromptTemplatemaxTokens

Model roles: imageGenerator textGate classifier bindings budgetPolicy

What you get — artifact

coloring-pagevisual

Version lineage

2026.09.16rev 88current2026-09-20
sha256:8534d8500…
2026.09.10rev 862026-09-12
sha256:857afae2f…
2026.09.09.1rev 852026-09-12
sha256:9d9b4f4e7…
2026.09.10rev 842026-09-12
sha256:857afae2f…
2026.09.09.1rev 802026-09-09
sha256:9d9b4f4e7…
2026.07.04rev 522026-08-06
sha256:e2361b169…
2026.07.04rev 262026-07-26
sha256:10c84d784…
2026.07.04rev 12026-07-04
sha256:fde512a83…

Full contract (as served)

GET /v1/catalog/workflows/generate-coloring-page
{
  "_comment": "SYNCED SNAPSHOT — do not hand-edit. Regenerate with: node scripts/sync-workflow-catalog.mjs (pulls api.esy.com GET /v1/catalog/workflows/{id}).",
  "generatedAt": "2026-09-22T16:13:54.045073Z",
  "id": "generate-coloring-page",
  "name": "Generate Coloring Page",
  "description": "Generate a printable coloring page: clean black line art on a white background (no fills, no shading), post-processed for paper or tablet, quality-gated against KDP print and WCAG touch standards, plus classifier-produced catalog metadata.",
  "shortDescription": "Printable line-art coloring page, post-processed, gated, classified.",
  "artifactClass": "visual",
  "outputType": "visual",
  "status": "active",
  "supersededById": null,
  "version": "2026.09.16",
  "stages": [
    {
      "name": "Render",
      "description": "Compose the line-art prompt and call the image model.",
      "stepCount": 1
    },
    {
      "name": "Post-process",
      "description": "Threshold, seal contour gaps, raise strokes to the print floor, despeckle.",
      "stepCount": 1
    },
    {
      "name": "Audit",
      "description": "Measure stroke weight, grey, margin ink, gaps and tappable regions; fail what would not print or fill.",
      "stepCount": 1
    },
    {
      "name": "Text gate",
      "description": "OCR the page against its text contract: exact lettering on a facts page, none on an art page.",
      "stepCount": 1
    },
    {
      "name": "Classify",
      "description": "Produce catalog metadata.",
      "stepCount": 1
    }
  ],
  "intakeSchema": {
    "fields": [
      {
        "name": "prompt",
        "type": "string",
        "required": true,
        "description": "Subject of the coloring page"
      },
      {
        "name": "style",
        "type": "enum",
        "required": false,
        "description": "Coloring style",
        "default": "coloring",
        "options": [
          "coloring"
        ]
      },
      {
        "name": "aspectRatio",
        "type": "enum",
        "required": true,
        "description": "Aspect ratio",
        "default": "3:4",
        "options": [
          "1:1",
          "3:4",
          "4:3",
          "3:2",
          "2:3",
          "16:9",
          "9:16"
        ]
      },
      {
        "name": "quality",
        "type": "enum",
        "required": false,
        "description": "Render quality tier",
        "default": "medium",
        "options": [
          "low",
          "medium",
          "high",
          "xhigh",
          "max"
        ]
      },
      {
        "name": "size",
        "type": "string",
        "required": false,
        "default": "",
        "description": "Exact WIDTHxHEIGHT for this render, e.g. '2560x1440'. Empty (the default) means aspectRatio decides. Both edges must be multiples of 16, neither over 3840, the ratio between 1:3 and 3:1, and the total pixels between 655,360 and 8,294,400. Above 2560x1440 the provider calls results experimental — allowed, more variable."
      },
      {
        "name": "detail",
        "type": "enum",
        "required": false,
        "default": "print",
        "description": "Which product this page is: 'print' (paper — bold strokes, clear margins) or 'app' (tablet — sealed contours, tappable regions)",
        "options": [
          "print",
          "app"
        ]
      },
      {
        "name": "renderModel",
        "type": "string",
        "required": false,
        "default": "openai/gpt-image-2.5-flare-2026-09-08",
        "description": "Registry id of the image model to render with. Print: openai/gpt-image-2.5-flare-2026-09-08. App: openai/gpt-image-2.5-sunburst-2026-09-08. An unregistered id falls back to the bound provider."
      },
      {
        "name": "postProcess",
        "type": "boolean",
        "required": false,
        "default": true,
        "description": "Threshold, seal gaps, raise strokes to the floor, despeckle. Off skips with provenance; the audit still runs on the raw render."
      },
      {
        "name": "lineArtAuditMode",
        "type": "enum",
        "required": false,
        "default": "enforce",
        "description": "Quality gate: 'enforce' (default) fails a page that would print or fill badly so the order re-renders it, 'report' records metrics only, 'off' skips the audit",
        "options": [
          "enforce",
          "report",
          "off"
        ]
      },
      {
        "name": "categories",
        "type": "string",
        "required": true,
        "description": "Comma-separated category slugs the classifier must choose from (empty fails the run in preflight)"
      },
      {
        "name": "textPolicy",
        "type": "enum",
        "required": false,
        "default": "",
        "options": [
          "",
          "none",
          "exact",
          "freeform"
        ],
        "description": "Per-item text contract: none = text forbidden; exact = must match expectedText; freeform = text allowed, judged on legibility/spelling only. Empty derives from textBearing (true=exact, false=freeform). Use 'none' deliberately, for assets that must carry no characters at all."
      },
      {
        "name": "textBearing",
        "type": "boolean",
        "required": false,
        "default": false,
        "description": "True when the asset must carry legible text (the OCR gate then checks it)"
      },
      {
        "name": "expectedText",
        "type": "string",
        "required": false,
        "default": "",
        "description": "The EXACT text the asset must carry; leave empty unless textPolicy is 'exact'"
      }
    ]
  },
  "runtimeSteps": [
    {
      "id": "step-1",
      "name": "Render line art",
      "kind": "image",
      "role": "imageGenerator",
      "promptTemplate": "redacted"
    },
    {
      "id": "step-2",
      "name": "Post-process line art",
      "kind": "tool",
      "inputPath": "step-1.url"
    },
    {
      "id": "step-3",
      "name": "Audit line art",
      "kind": "tool",
      "inputPath": "step-2.url"
    },
    {
      "id": "step-3b",
      "name": "Text gate",
      "kind": "llm",
      "capability": "text",
      "role": "textGate",
      "requireTrue": "pass",
      "failMessage": "OCR text gate rejected the render",
      "jsonSchema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "foundText": {
            "type": "string",
            "description": "All legible text read from the image; empty if none"
          },
          "pass": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "foundText",
          "pass",
          "reason"
        ]
      },
      "system": "redacted",
      "promptTemplate": "redacted",
      "maxTokens": "redacted"
    },
    {
      "id": "step-4",
      "name": "Classify asset",
      "kind": "llm",
      "capability": "text",
      "role": "classifier",
      "jsonSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Catalog-ready title, <= 60 chars"
          },
          "slug": {
            "type": "string",
            "description": "kebab-case URL slug"
          },
          "description": {
            "type": "string",
            "description": "1-2 sentence SEO-friendly description"
          },
          "category": {
            "type": "string",
            "description": "Exactly one of the provided category slugs"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "3-8 search tags"
          }
        },
        "required": [
          "title",
          "slug",
          "description",
          "category"
        ],
        "additionalProperties": false
      },
      "system": "redacted",
      "promptTemplate": "redacted",
      "maxTokens": "redacted"
    }
  ],
  "gates": [
    {
      "id": "gate-render",
      "name": "Provider execution",
      "type": "quality",
      "inputs": [
        "intake"
      ],
      "outputs": [
        "line-art"
      ],
      "unlocks": [
        "step-2"
      ]
    },
    {
      "id": "gate-line-art",
      "name": "Line-art audit",
      "type": "quality",
      "inputs": [
        "post-processed"
      ],
      "outputs": [
        "audited"
      ],
      "unlocks": [
        "step-3b"
      ]
    },
    {
      "id": "gate-text",
      "name": "OCR text gate",
      "type": "quality",
      "inputs": [
        "audited"
      ],
      "outputs": [
        "lettering-checked"
      ],
      "unlocks": [
        "step-4"
      ]
    }
  ],
  "artifactSchema": {
    "artifactClass": "visual",
    "artifactType": "coloring-page",
    "files": [
      "image/png"
    ],
    "metadata": {
      "aspectRatio": "enum [3:4, 1:1, 4:3]",
      "quality": "enum [low, medium, high, xhigh, max]",
      "detail": "enum [print, app]",
      "lineArtAudit": "object",
      "classification": "object"
    }
  },
  "providers": {
    "imageGenerator": "redacted",
    "textGate": "redacted",
    "classifier": "redacted"
  },
  "budgetPolicy": "redacted",
  "versions": [
    {
      "version": "2026.07.04",
      "revision": 1,
      "contentHash": "sha256:fde512a832e869e9e8f20b4e0be2d4e839f1d578961e99ce7f64fd9d09b45576",
      "createdAt": "2026-07-04T21:49:03.195883Z"
    },
    {
      "version": "2026.07.04",
      "revision": 26,
      "contentHash": "sha256:10c84d7845b8f8639c3c94fe43273ef08568071e14202c2fafd0919463b6db45",
      "createdAt": "2026-07-26T00:51:05.101830Z"
    },
    {
      "version": "2026.07.04",
      "revision": 52,
      "contentHash": "sha256:e2361b169361fe6e0963846552a4ce645567b0d5340cbeb090da3f92194ffc81",
      "createdAt": "2026-08-06T22:08:47.462572Z"
    },
    {
      "version": "2026.09.09.1",
      "revision": 80,
      "contentHash": "sha256:9d9b4f4e743530ad96d5392cbf5701d240a900bd6c9c7505658076b39dac2004",
      "createdAt": "2026-09-09T22:42:07.692657Z"
    },
    {
      "version": "2026.09.10",
      "revision": 84,
      "contentHash": "sha256:857afae2f856745fb09fb7d695279a6584b30b7fe2ec9d53e4c3f29d30cece57",
      "createdAt": "2026-09-12T04:56:49.454434Z"
    },
    {
      "version": "2026.09.09.1",
      "revision": 85,
      "contentHash": "sha256:9d9b4f4e743530ad96d5392cbf5701d240a900bd6c9c7505658076b39dac2004",
      "createdAt": "2026-09-12T23:37:44.483737Z"
    },
    {
      "version": "2026.09.10",
      "revision": 86,
      "contentHash": "sha256:857afae2f856745fb09fb7d695279a6584b30b7fe2ec9d53e4c3f29d30cece57",
      "createdAt": "2026-09-12T23:42:41.582175Z"
    },
    {
      "version": "2026.09.16",
      "revision": 88,
      "contentHash": "sha256:8534d85006b48d544c4a93066d6f5868695b431a8bbf9dcc7ecb276bf4d09899",
      "createdAt": "2026-09-20T02:38:59.510757Z"
    }
  ],
  "updatedAt": "2026-09-20T02:38:59.510757Z"
}

Snapshot generated 2026-09-22 from the live registry.