Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch
TypeScript SDK

Pickers, presets and prompts

Read every picker's valid options, fill pickers from a scene description, load node presets, and improve prompts with the Prompt Wizard from TypeScript.

Pickers are the Creative Controls nodes, such as Mood or Lens, whose choice adds tested wording to a prompt. client.pickerCatalogs and client.catalogs return each picker's valid options, and analyzeText() fills pickers from a scene description. client.presets reads saved node settings, and client.promptHelper is the Prompt Wizard, which improves prompts for any generation node. See Creative controls and Picker catalogs for the concepts.

Methods

MethodWhat it does
pickerCatalogs.list()List every picker and its catalog
pickerCatalogs.get(nodeType, opts?)Read one picker's options
pickerCatalogs.analyzeText(params)Fill picker choices from a text description
catalogs.list(opts?)Read every catalog of this deployment in one call
presets.list(nodeType?)List your saved presets
presets.listGroups(nodeType?)List your preset folders and sections
presets.listFactory(nodeType)List the built-in presets of a node type
promptHelper.analyze(input)Turn a rough idea into questions
promptHelper.generate(input)Build a prompt from the answers
promptHelper.enhance(input)Improve a prompt in one step

client.pickerCatalogs

The option lists of the picker nodes. Both read methods are public, need no token, and can be cached by the server for 5 minutes. If your code can import @nodaro/shared, the same catalogs ship there as typed data; these methods are for clients that cannot bundle it.

pickerCatalogs.list()

Lists every picker (GET /v1/picker-catalogs).

list(): Promise<{ data: PickerCatalogSummary[] }>
const { data: pickers } = await client.pickerCatalogs.list()
const mood = pickers.find((p) => p.nodeType === "mood")

Each entry has nodeType, label, catalogId, kind (single or multi), valueField for a single-dimension picker or fields for a multi-dimension one, optionCount, and imageCount, the number of options with a picture.

pickerCatalogs.get(nodeType, opts?)

Reads one picker's options (GET /v1/picker-catalogs/:nodeType). A single-dimension picker, such as Mood, has options. A multi-dimension picker, such as Person, has dimensions, each { field, label, options }. A few single-dimension pickers also have extra settings next to the main choice: transition and character-fx have position, duration and intensity, and character-motion has position and pace.

get(nodeType: string, opts?: { detail?: "compact" | "full"; category?: string; field?: string }): Promise<{ data: PickerCatalog }>

Prop

Type

const { data } = await client.pickerCatalogs.get("mood", { detail: "full" })
const serene = data.options?.find((o) => o.id === "serene")
console.log(serene?.term)       // the short phrase, added in Compact mode
console.log(serene?.promptHint) // the full sentence, added in Full mode

Throws NotFoundError for an unknown node type.

Show label, add term. Every option has a term at both detail levels: the short professional phrase to put in a prompt. label is for display only. Never derive one from the other. An option that adds nothing, such as auto or none, has an empty term.

Pictures. An option with a picture has an absolute imageUrl, at both detail levels. person and styling also return sections: the topics the editor groups their settings under, each { label, fields, imageUrl? }. Photos and music and voice art are served by the installation itself. The rendered look previews come from the Nodaro CDN, and only Nodaro Cloud returns them. File names carry a content hash, so you can cache the pictures without expiry.

const { data: person } = await client.pickerCatalogs.get("person")
for (const section of person.sections ?? []) {
  const settings = person.dimensions?.filter((d) => section.fields.includes(d.field)) ?? []
  for (const setting of settings) {
    for (const option of setting.options) renderTile(option.label, option.imageUrl)
  }
}

Character Motion. The options of character-motion carry an optional motion object at both detail levels. It says what a move needs and leaves: requires, startPose and endPose, endVisibility, handsAfter, needsFreeHands, kind, fixedPace, counterpart, search aliases, and deprecated with a replacementId. A missing field means unknown. Keep retired ids when you load saved workflows, and hide them from new choices. See Character Motion.

pickerCatalogs.analyzeText(params)

Fills picker choices from a free-text scene description (POST /v1/text-to-picker), the text version of Describe to Picker. It returns pickerJson, keyed by picker type, then by dimension, then the chosen id or ids. Load pickers from it as it is, then let the user adjust them. It costs credits, billed as Describe to Picker.

analyzeText(params: TextToPickerParams): Promise<{
  jobId: string
  pickerJson: Record<string, Record<string, string | string[]>>
  gaps?: { missingItems: object[]; missingCategories: object[] }
}>

Prop

Type

const { pickerJson, gaps } = await client.pickerCatalogs.analyzeText({
  text: "Neon-soaked Tokyo alley at night, rain, handheld tracking shot, moody synthwave",
})
console.log(pickerJson["setting"], pickerJson["camera-motion"])

Dimensions the text says nothing about are left out: the analysis does not guess. gaps lists what the text describes that no catalog option represents well, in missingItems and missingCategories. Show it to the user as "we could not match X; choose one yourself".

client.catalogs

catalogs.list(opts?)

Returns every picker catalog in one call, as this deployment serves it (GET /v1/catalogs). A deployment can register catalog packs that replace, extend or hide options. A client that draws its own pickers should read this list to respect them. It is public and can be cached for 5 minutes.

list(opts?: { detail?: "compact" | "full" }): Promise<{
  curated: boolean
  packs: number
  version: number
  data?: ProjectedCatalog[]
}>

Prop

Type

const { curated, data } = await client.catalogs.list({ detail: "full" })
if (curated) {
  const setting = data?.find((c) => c.catalogId === "setting")
  console.log(setting?.options?.[0]?.term)
}

data is present only when the deployment registered catalog packs (curated: true). Without packs, the catalogs are the standard ones: read them one by one with pickerCatalogs.get(). Options carry the same imageUrl, and person and styling the same sections.

client.presets

Your saved node presets and the built-in ones, read only. A preset's data is a node's saved settings. To apply a preset, merge its data into a node's data when you build a workflow. An OAuth token needs the presets:read scope. See Presets.

presets.list(nodeType?)

Lists your saved presets, newest first (GET /v1/node-presets).

list(nodeType?: string): Promise<NodePreset[]>

Prop

Type

const presets = await client.presets.list("generate-image")
const cinematic = presets.find((p) => p.name === "Cinematic Portrait")
// apply: spread cinematic.data into the node's data when you create the workflow

A NodePreset has id, nodeType, name, description, data, groupId, tags, sortOrder, createdAt and updatedAt.

presets.listGroups(nodeType?)

Lists your preset folders and sections (GET /v1/node-preset-groups).

listGroups(nodeType?: string): Promise<NodePresetGroup[]>

Prop

Type

const groups = await client.presets.listGroups("generate-image")

Each group has id, nodeType, name, kind (folder or section), sortOrder, createdAt and updatedAt.

presets.listFactory(nodeType)

Lists the built-in presets of a node type (GET /v1/node-presets/factory).

listFactory(nodeType: string): Promise<{ data: FactoryPreset[] }>

Prop

Type

const { data } = await client.presets.listFactory("generate-video")
const orbit = data.find((p) => p.id === "generate-video/orbit-360")

client.promptHelper

The Prompt Wizard: AI help to write prompts for generation nodes. All three methods send their request to POST /v1/prompt-helper/wizard, and each call costs credits. See Prompt Wizard for the REST view.

All three take these common fields:

Prop

Type

The CLI offers the same through nodaro prompt wizard, analyze, generate and enhance, with --llm-model and --reasoning-effort. See the CLI.

promptHelper.analyze(input)

Turns a rough idea into guided questions for a node type. Answer them, then pass the answers to generate().

analyze(input: AnalyzeInput): Promise<{ jobId: string; questions: WizardQuestion[] }>

Prop

Type

const { questions } = await client.promptHelper.analyze({
  nodeType: "generate-image",
  prompt: "a snow leopard",
})

promptHelper.generate(input)

Builds one optimized prompt from the chosen answers. Each selection is { category, value, isCustom }.

generate(input: GenerateInput): Promise<{ jobId: string; prompt: string; recommendedModel?: RecommendedModel }>

Prop

Type

const { prompt, recommendedModel } = await client.promptHelper.generate({
  nodeType: "generate-image",
  selections: [{ category: "subject", value: "snow leopard", isCustom: false }],
})

promptHelper.enhance(input)

Improves a prompt in one step, without the questions.

enhance(input: EnhanceInput): Promise<{ jobId: string; prompt: string; recommendedModel?: RecommendedModel }>

Prop

Type

const { prompt } = await client.promptHelper.enhance({
  nodeType: "generate-image",
  prompt: "snow leopard on a rock",
  reasoningEffort: "high",
})

Frequently asked questions

Last updated on

On this page