Catálogos de seletores
Crie seletores do Nodaro em seu app com @nodaro/prompts, converta seleções em trechos de prompt, traduza rótulos, mostre imagens ou leia catálogos via API.
Um catálogo de seletor é o conjunto de dados por trás de um dos seletores do Nodaro, os nós dos Controles criativos, como Clima (Mood), Lente (Lens), Enquadramento (Framing) e Pessoa (Person). Ele contém as opções do seletor, o texto de prompt que cada opção adiciona, as categorias e as chaves das traduções. Os catálogos vêm como dados simples em pacotes npm, então você pode criar os mesmos seletores no seu próprio app, com o seu próprio estilo, e montar exatamente os prompts que o Nodaro monta.
Um seletor nunca chama um modelo. Ele adiciona um trecho descritivo ao prompt do nó que ele alimenta; veja Controles criativos.
Importar o pacote ou chamar a API
| O seu app | Use |
|---|---|
| Consegue incluir um pacote npm no bundle | Importe os catálogos de @nodaro/prompts. Eles são tipados, funcionam offline e não precisam de chamada à API. |
| Não consegue incluir um pacote, como um agente de IA via MCP | Leia os mesmos dados pela interface de descoberta: o endpoint REST GET /v1/picker-catalogs, client.pickerCatalogs no SDK, nodaro pickers na CLI ou a ferramenta MCP get_picker_catalog. |
Prefira o pacote quando puder: ele evita uma ida e volta à rede por dados que só mudam a cada versão.
npm install @nodaro/prompts @nodaro/shared @nodaro/sdk@nodaro/prompts contém os catálogos e as funções de prompt, @nodaro/shared contém as traduções, e @nodaro/sdk executa a geração.
O registro
import { PICKER_CATALOGS, getPickerCatalog, listPickerCatalogs } from "@nodaro/prompts"| Exportação | O que retorna |
|---|---|
PICKER_CATALOGS | Todos os catálogos de seletores: 28 seletores de uma dimensão e 11 de várias dimensões. |
getPickerCatalog(nodeTypeOrCatalogId) | Um catálogo, pelo tipo de nó (como "mood") ou pelo id do catálogo. |
listPickerCatalogs() | Todos eles. |
Os tipos do catálogo:
interface PickerOption {
id: string
label: string // English display text; translate it with the catalogId (see below)
description?: string
category?: string // group id, matching categoryOrder and categoryLabels
promptHint: string // the clause this option adds ("" for a no-op option such as "auto")
term: string // the short professional term Compact mode adds ("" for a no-op option)
icon?: string // reserved; pictures are served separately (see "Pictures")
}
interface PickerDimension { // multi-dimension pickers, and the secondary fields of a single-dimension picker
field: string // for example "shotSize"
label: string
options: readonly PickerOption[]
}
interface PickerCatalog {
nodeType: string // "mood", "framing", ...
label: string
catalogId: string // the key of the translations
kind: "single" | "multi"
valueField?: string // single: the field a selection writes
defaultValue?: string
categoryOrder?: readonly string[]
categoryLabels?: Readonly<Record<string, string>>
options?: readonly PickerOption[] // single-dimension pickers
fields?: readonly string[] // multi-dimension pickers: the dimension fields
dimensions?: readonly PickerDimension[] // multi-dimension pickers, and secondary fields
}Mostre o label e envie term ou promptHint ao modelo. Nunca derive um do outro.
Criar um seletor de uma dimensão
Um seletor de uma dimensão, como o Clima, é uma escolha em uma lista simples, opcionalmente agrupada. options traz tudo o que você precisa para desenhar a grade.
import { getPickerCatalog, getParameterPromptHint } from "@nodaro/prompts"
import { createClient, StaticTokenAuth } from "@nodaro/sdk"
const client = createClient({
baseUrl: "https://app.nodaro.ai",
auth: new StaticTokenAuth(process.env.NODARO_ACCESS_TOKEN!),
})
const mood = getPickerCatalog("mood")! // { nodeType: "mood", valueField: "mood", options, categoryOrder, categoryLabels }
// 1. Render your own tile grid, grouped by category
function MoodPicker({ value, onChange }: { value?: string; onChange: (id: string) => void }) {
return (mood.categoryOrder ?? [undefined]).map((cat) => (
<section key={cat ?? "all"}>
{cat && <h4>{mood.categoryLabels?.[cat]}</h4>}
{mood.options!
.filter((o) => !cat || o.category === cat)
.map((o) => (
<button key={o.id} aria-pressed={value === o.id} title={o.description} onClick={() => onChange(o.id)}>
{o.label}
</button>
))}
</section>
))
}
// 2. Selection, then prompt clause, then generation
const selected = "serene"
const clause = getParameterPromptHint({ type: "mood", data: { mood: selected } })
// or: mood.options!.find((o) => o.id === selected)!.promptHint
const prompt = ["a portrait of a woman", clause].filter(Boolean).join(", ")
const result = await client.nodes.runAndWait("generate-image", { prompt })
console.log(result.imageUrl)Parâmetros secundários de Transição, Efeitos de personagem e Movimento de personagem
Três seletores de uma dimensão têm campos extras além da escolha principal. Transição (Transition) e Efeitos de personagem (Character FX) têm, cada um, position, duration e intensity. Movimento de personagem (Character Motion) tem position e pace.
Esses campos também são catálogos, com as mesmas linhas de qualquer outra opção, e cada lista começa com um auto sem efeito. O catálogo os expõe como dimensions, além de options. Desenhe o seletor principal a partir de options e os menus suspensos a partir de dimensions; um cliente que envia só ids nunca escreve ele mesmo o trecho de timing.
const fx = getPickerCatalog("character-fx")!
fx.options // the effects of the main picker
fx.dimensions // [{ field: "position", ... }, { field: "duration", ... }, { field: "intensity", ... }]
// Each dimension's rows are also exported directly:
// TRANSITION_POSITIONS / TRANSITION_DURATIONS / TRANSITION_INTENSITIES
// CHARACTER_FX_POSITIONS / CHARACTER_FX_DURATIONS / CHARACTER_FX_INTENSITIES
// CHARACTER_MOTION_POSITIONS / CHARACTER_MOTION_PACESTransição e Efeitos de personagem compartilham os mesmos ids: start, middle, end e full; instant, short, medium e long; subtle, natural, dynamic e crazy. Eles não compartilham o texto: uma transição acontece e se estende pelo clipe, enquanto um efeito aparece e persiste. Sempre leia as linhas do catálogo do próprio nó. Movimento de personagem compartilha os ids de posição e adiciona os próprios ids de ritmo, slow-motion, slow, natural, fast e explosive, com o próprio texto.
Criar um seletor de várias dimensões
Um seletor de várias dimensões define vários campos independentes de uma vez. O Enquadramento, por exemplo, define o tamanho do plano, o ângulo, a cobertura, a composição e o ponto de vista. O catálogo dele tem uma entrada { field, label, options } por campo em dimensions.
import { getPickerCatalog, getParameterPromptHint } from "@nodaro/prompts"
const framing = getPickerCatalog("framing")!
// framing.dimensions = [
// { field: "shotSize", label: "Shot Size", options: [{ id: "close-up", ... }, ...] },
// { field: "angle", label: "Angle", options: [{ id: "low-angle", ... }, ...] },
// { field: "coverage", label: "Coverage", options: [...] },
// { field: "composition", label: "Composition", options: [...] },
// { field: "vantage", label: "Vantage", options: [...] },
// ]
function FramingPicker({ value, onChange }: {
value: Record<string, string>
onChange: (v: Record<string, string>) => void
}) {
return framing.dimensions!.map((dim) => (
<section key={dim.field}>
<h4>{dim.label}</h4>
{dim.options.map((o) => (
<button
key={o.id}
aria-pressed={value[dim.field] === o.id}
title={o.description}
onClick={() => onChange({ ...value, [dim.field]: o.id })}
>
{o.label}
</button>
))}
</section>
))
}
// Selection to clause: getParameterPromptHint composes every field that is set
const value = { shotSize: "close-up", angle: "low-angle", composition: "rule-of-thirds" }
const clause = getParameterPromptHint({ type: "framing", data: value })Transformar seleções em prompt
getParameterPromptHint({ type, data }) transforma qualquer seleção, de uma ou de várias dimensões, no trecho correspondente. É a mesma função que o Nodaro executa nos servidores dele, então os seus prompts correspondem aos do editor. Também existem construtores por catálogo, como buildFramingHints(value) para um seletor de várias dimensões e getMoodPromptHint(id) para uma opção.
// Several pickers, one prompt, one generation
const clauses = [
getParameterPromptHint({ type: "mood", data: { mood: "serene" } }),
getParameterPromptHint({ type: "lens", data: { lens: "portrait-85mm" } }),
getParameterPromptHint({ type: "framing", data: { shotSize: "close-up", angle: "eye-level" } }),
]
const prompt = ["a portrait of a woman in a garden", ...clauses].filter(Boolean).join(", ")
const result = await client.nodes.runAndWait("generate-image", { prompt, provider: "nano-banana-2" })Adicione hintMode: "compact" ao data de um seletor para obter o term curto dele em vez do trecho completo. Esse é o modo Compacto da opção Trecho do prompt do editor; veja Completo ou Compacto.
| Função | O que faz |
|---|---|
getParameterPromptHint({ type, data }) | Transforma qualquer seleção no trecho composto correspondente. |
build<Name>Hints(value) | Monta o trecho de um catálogo, como buildFramingHints. |
get<Name>PromptHint(id) | Devolve o trecho de uma opção, como getMoodPromptHint. |
PICKER_CATALOGS, getPickerCatalog, listPickerCatalogs | O registro. |
Traduzir os rótulos
Os rótulos dos catálogos estão em inglês. As traduções para 12 idiomas vêm em @nodaro/shared, indexadas pelo catalogId de cada catálogo: en, es, fr, de, pt-BR, ru, hi, ja, ko, zh-CN, he e ar. Os valores de promptHint e term ficam em inglês, porque são os modelos que os leem.
O inglês não precisa de configuração. Para os outros idiomas, registre os bundles de tradução uma vez na inicialização e depois resolva os rótulos de forma síncrona, com o inglês como fallback:
import { registerSidecarLoaders, ensureLocaleCatalogLoaded, resolveLabel } from "@nodaro/shared"
// 1. Once at startup, in a Vite app: wire the lazily loaded locale bundles
registerSidecarLoaders(import.meta.glob("/node_modules/@nodaro/shared/src/i18n/*.*.ts"))
// 2. Before rendering a locale, load that catalog's bundle
await ensureLocaleCatalogLoaded(mood.catalogId, "fr")
// 3. Resolve a label, synchronously; English when a translation is missing or not loaded yet
const label = resolveLabel(mood.catalogId, option.id, option.label, "fr")Os bundles são carregados sob demanda, então registerSidecarLoaders recebe um mapa de carregadores, como o que o import.meta.glob do Vite devolve. Backends e testes podem pular a tradução e usar o label em inglês.
Mostrar imagens
O seu app pode mostrar as mesmas imagens que o editor mostra nestes seletores:
- Fotos em Pessoa, Figurino e beleza (Styling), Objeto na mão (Held Prop), Material e Animal.
- Arte nos seletores de música e de voz: Gênero musical (Music Genre), Clima musical (Music Mood), Instrumentação (Instrumentation), Perfil da voz (Voice Character) e Estilo de fala (Voice Delivery).
- Imagens de prévia nos seletores de look, só no Nodaro Cloud. São eles: Estilo (Style), Cor / look (Color / Look), Época / período (Era / Period), Lente, Clima, Atmosfera (Atmosphere), Efeito de composição (Composition Effect), Câmera / película (Camera / Film), Enquadramento, Iluminação (Lighting) e Movimento de câmera (Camera Motion).
Pela API, toda opção com imagem traz um imageUrl absoluto na instalação consultada, e uma opção sem imagem não traz nenhum. Pessoa e Figurino e beleza também retornam sections: os tópicos deles, em ordem, cada um com uma imagem redonda. As regras das URLs estão em Ler os catálogos pela API.
Na biblioteca, @nodaro/prompts monta as mesmas URLs a partir dos mesmos dados:
pickerOptionImageUrl(catalog, field, id, { baseUrl })para uma opção;pickerSectionImageUrl(topicLabel, { baseUrl })para um tópico de Pessoa ou de Figurino e beleza.
baseUrl é a instalação do Nodaro que serve os arquivos: as imagens pertencem à instalação, não ao pacote npm. Passe lookPreviews: true só com o Nodaro Cloud. Para todos os outros seletores, desenhe os seus próprios visuais a partir de label, description e category.
Ler os catálogos pela API
Os dois endpoints são públicos, não precisam de token e ficam em cache por 5 minutos.
| Método | Caminho | O que retorna |
|---|---|---|
GET | /v1/picker-catalogs | Um diretório de todos os seletores: nodeType, label, catalogId, kind, valueField ou fields, optionCount e imageCount, o número de opções com imagem. |
GET | /v1/picker-catalogs/:nodeType | O catálogo de um seletor. Um tipo desconhecido responde 404 not_found. |
GET /v1/picker-catalogs/:nodeType aceita três parâmetros de query. Um valor inválido responde 400 validation_error.
| Parâmetro | Valores | O que faz |
|---|---|---|
detail | compact (padrão) ou full | compact retorna id, label, category, term, icon e imageUrl. full adiciona a description e o promptHint de cada opção. |
category | Um id de categoria | Filtra um seletor de uma dimensão por uma categoria. |
field | Um nome de campo | Retorna uma dimensão de um seletor de várias dimensões, ou um campo secundário de Transição, Efeitos de personagem ou Movimento de personagem. |
curl -s https://app.nodaro.ai/v1/picker-catalogs/mood | jq '.data.options[0]'{ "id": "happy", "label": "Happy", "category": "positive", "term": "happy expression",
"imageUrl": "https://cdn.nodaro.ai/cdn-cgi/image/width=480,format=auto,quality=80/images/710df65a-3c1e-485b-b8b7-29f7b3baf479.png" }As URLs das imagens
| Seletores | Imagem |
|---|---|
person, styling, held-prop, material, animal | Uma foto, WebP, com até 480 px de largura. |
music-genre, music-mood, instrumentation, voice-character, voice-delivery | Uma imagem de emoji 3D (WebP, 128 px) ou uma bandeira (WebP, 120 px de largura). |
Seletores de look, como style, color-look, lens, framing, lighting, mood, camera-format e camera-motion | No Nodaro Cloud, uma imagem fixa de 480 px da prévia renderizada, vinda da CDN do Nodaro; para camera-motion, um quadro do clipe. Uma instalação self-hosted não retorna nenhuma. |
- Host. Uma instalação serve as próprias imagens em
/picker-art/, então oimageUrlusa o endereço público dela:https://app.nodaro.aino Nodaro Cloud, ou oPUBLIC_URLde uma instalação self-hosted. Use cada URL como ela vem; nunca monte uma a partir do id de uma opção. - Cache. Os nomes dos arquivos trazem um hash do conteúdo, então uma imagem alterada ganha uma URL nova. Os arquivos são servidos com
Cache-Control: public, max-age=31536000, immutableeAccess-Control-Allow-Origin: *, então qualquer origem pode carregá-los em um<img>, comfetchou em um canvas. - Tópicos.
personestylingtambém retornamsections, cada uma com umlabel, osfieldsque ela agrupa e umimageUrlredondo opcional.
curl -s https://app.nodaro.ai/v1/picker-catalogs/person | jq '.data.sections[0], .data.dimensions[0].options[0]'{ "label": "Identity", "fields": ["type", "age", "ethnicity", "regionalAesthetic"],
"imageUrl": "https://app.nodaro.ai/picker-art/character/sections/identity.2d5ec1a4.webp" }
{ "id": "man", "label": "Man", "term": "man",
"imageUrl": "https://app.nodaro.ai/picker-art/character/person/man.d6bed999.webp" }Os catálogos curados de uma implantação
GET /v1/catalogs retorna todos os catálogos em uma única chamada, em um formato plano único. Uma implantação pode fazer a curadoria dos catálogos com pacotes vendorizados que substituem, estendem ou bloqueiam opções, e esse endpoint reflete essa curadoria. Quando a implantação registrou pacotes, a resposta traz curated: true e os catálogos em data. Sem nenhum pacote, ela traz curated: false, e você lê os catálogos incluídos, seletor por seletor, em /v1/picker-catalogs/:nodeType. O método do SDK é client.catalogs.list().
Preencher seletores a partir de uma descrição
POST /v1/text-to-picker escolhe valores de seletores a partir de uma descrição em texto livre de uma cena ou de uma tomada. Esse é o recurso AI Fill. Ele exige um token e é cobrado como uma chamada de LLM. Ele retorna pickerJson, organizado por tipo de seletor, depois por dimensão e depois pelos ids escolhidos, e gaps, os detalhes descritos que nenhuma opção de catálogo representa. O método do SDK é client.pickerCatalogs.analyzeText(), e o comando da CLI é nodaro pickers analyze.
Metadados de Movimento de personagem
As opções do catálogo de Movimento de personagem podem trazer metadados motion, nos dois níveis de detalhe. Os metadados descrevem o movimento:
- Os requisitos, as poses inicial e final, e a visibilidade e as mãos depois do movimento.
- Se ele precisa das mãos livres, o tipo, um ritmo fixo e a contraparte.
- Apelidos de busca, e se o id foi descontinuado e qual id o substitui.
Um campo ausente significa desconhecido.
Mantenha os ids descontinuados funcionando ao carregar workflows salvos, e oculte-os das novas escolhas. O tipo é CharacterMotionMetadata, exportado por @nodaro/prompts.
Perguntas frequentes
Páginas relacionadas
Controles criativos
Clima
SDK para TypeScript
Referência das ferramentas MCP
Comandos
Última atualização
Login externo (SSO)
Use um provedor de identidade confiável no login de uma instalação do Nodaro, com asserção JWT assinada, OIDC ou SAML, e controle a vinculação de contas.
Incorporações
As duas formas de levar o Nodaro ao seu produto: um miniapp que executa um workflow publicado e o viewport de cena 3D sem estado, e quando usar cada uma.