Formularios basados en esquemas en React: construyendo con TrueFoundry FormBuilder

Diseñado para la velocidad: ~ 10 ms de latencia, incluso bajo carga
¡Una forma increíblemente rápida de crear, rastrear e implementar sus modelos!
- Gestiona más de 350 RPS en solo 1 vCPU, sin necesidad de ajustes
- Listo para la producción con soporte empresarial completo
Si has utilizado TrueFoundry para desplegar un servicio, crear un clúster, configurar un modelo LLM o gestionar secretos, habrás interactuado con formularios que parecen interfaces normales, pero que están construidos de forma muy distinta a los formularios web típicos.
Por qué TrueFoundry utiliza formularios basados en esquemas
Los formularios de TrueFoundry suelen representar manifiestos: objetos YAML/JSON que también puedes aplicar con la CLI (tfy apply -f ...). El mismo objeto puede editarse en la interfaz, descargarse como YAML o enviarse a la API.
Un enfoque basado en esquemas proporciona a TrueFoundry:
- Una única fuente de verdad para la estructura del formulario (cargada desde el backend según el tipo de recurso).
- Un comportamiento coherente en despliegues, clústeres, políticas, modelos, secretos, formularios de configuración o cualquier otro formulario de la plataforma.
- Campos anidados y condicionales sin tener que reescribir la lógica del formulario en cada pantalla.
- Widgets específicos del dominio (selector de clúster, selector de secretos, límites de recursos) integrados en un entorno de ejecución compartido.
El modelo mental: el esquema describe la forma de los datos y cómo editarlos; FormBuilder convierte esa descripción en un formulario funcional.
1. Esquema del formulario:
Un esquema de formulario es una matriz de definiciones de campo. Cada campo es un objeto con algunas propiedades importantes:
Aquí tienes un ejemplo genérico simplificado; no es un esquema real de TrueFoundry, pero se acerca a cómo el producto entiende la configuración:
[
{
"sort": 1,
"jsonKey": "name",
"label": "Service Name",
"uiType": "Input",
"validate": { "required": true, "pattern": "^[a-z0-9-]+$" }
},
{
"sort": 2,
"jsonKey": "image",
"label": "Image",
"uiType": "Group",
"subParameters": [
{
"jsonKey": "type",
"label": "Source",
"uiType": "Radio",
"validate": {
"required": true,
"defaultValue": "build",
"options": [
{ "label": "Build", "value": "build" },
{ "label": "Existing image", "value": "existing" }
]
}
},
{
"jsonKey": "uri",
"label": "Image URI",
"uiType": "Input",
"conditions": [
{ "jsonKey": "image.type", "op": "==", "value": "existing" }
],
"validate": { "required": true }
}
]
}
]
Manifiesto/configuración resultante al enviar:
{
"name": "my-service",
"image": { "type": "existing", "uri": "registry.io/app:v1" }
}
2. Cómo se asignan los componentes y se renderizan los campos
El renderizado ocurre en una pequeña tubería; el flujo es el siguiente:

FormBuilder recorre el árbol del esquema y elige un componente de React por nodo basándose en uiType.
Tipos de componentes:
- Básicos: Input, Select, Radio, Switch, Number
- Estructurales: Group (sección), Structs (lista repetible), KV / ENV (clave-valor)
- Específicos del dominio: ClusterSelect, SecretSelect, Resources, ModelSelect, PermissionsMatrix, campos MCP y más
Condiciones: Si image.type !== "existing", el campo URI nunca se monta. Con shouldUnregister: true, también sale del estado del formulario, por lo que los valores ocultos no pueden filtrarse en el payload.
Lógica de mapeo en el código:
// FormComponentMap
const ComponentType = FormComponents[schema.uiType]
const CustomComp = CustomComponentsMap?.[schema.uiType]
if (!enabledByCondition) return null
return CustomComp
? <CustomComp schema={schema} />
: <ComponentType schema={schema} />
3. Cómo se gestiona el estado del formulario
FormBuilder utiliza react-hook-form como motor de estado. Esa elección es fundamental para el comportamiento del producto.
Inicialización/Uso del componente - crear y editar:
<FormBuilder
schema={schema}
defaultValues={existingManifest} // edit: pre-fill; create: empty/template
onSubmit={(manifest) => createOrUpdate({ manifest })}
/>
Configuración del formulario:
const methods = useForm({
mode: 'onChange', // validate as user types
defaultValues,
shouldUnregister: true, // hidden fields drop out of state
})
Registro de campos: cada entrada se vincula a su ruta:
// Inside a text field component
const { register } = useFormContext()
<input
{...register(schema.jsonKey, registerProps)}
defaultValue={defaultValue}
/>
Contexto adicional: formularios específicos pasan datos en tiempo de ejecución separados de los valores de los campos:
<FormBuilder
schema={schema}
extraContext={{
workspace,
cluster,
serviceAccountOptions, // dynamic dropdown options
dataTestPrefix: 'create-cluster',
}}
/>
Objeto único, rutas anidadas:
Todos los valores de los campos residen en un único objeto de formulario. Cada campo se registra bajo su ruta jsonKey completa:
- name → cadena de nivel superior
- image.type → valor anidado
- ports.0.container_port → primer elemento de una matriz
Al editar un campo, estás modificando este objeto compartido. Al enviar, FormBuilder lee el objeto completo y lo pasa al manejador del formulario (que normalmente llama a la API de TrueFoundry o genera YAML).
Valores predeterminados y modo de edición:
Al abrir un formulario para crear algo, los defaultValues pueden estar vacíos o provenir de una plantilla.
Al editar, defaultValues suele ser el manifiesto existente. Los campos del formulario se rellenan previamente a partir de ese objeto. Algunos campos se marcan como inmutables en el modo de edición (por ejemplo, el nombre del recurso), por lo que aparecen como de solo lectura.
Los campos ocultos se eliminan del estado:
Los formularios de TrueFoundry utilizan shouldUnregister: true. Esto significa que:
- Si un campo está oculto por una condición, se anula su registro en el estado del formulario
- Su valor no se filtra en la carga útil enviada
Esto es importante para los formularios condicionales: solo se envía lo que el usuario realmente pudo ver y editar.
4. Cómo funciona la validación
La validación en los formularios de TrueFoundry se realiza en dos niveles.
Nivel 1: Validación de esquema (declarativa)
El bloque validate de cada campo puede especificar:
- required
- min / max (rango permitido de valores enteros)
- minLength / maxLength (longitud de cadena o matriz)
- pattern (regex) con mensaje personalizado
- defaultValue
- immutable (solo lectura en modo edición)
Estas reglas se convierten en reglas de validación de react-hook-form. Los errores se muestran en línea junto al campo. La validación se ejecuta al cambiar (modo: 'onChange'), por lo que los usuarios reciben comentarios mientras escriben, no solo al enviar.
Nivel 2: Validación personalizada y asíncrona
Los esquemas también pueden adjuntar una función de validación personalizada, utilizada habitualmente para:
- Unicidad del nombre ("Ya existe una entidad con este nombre")
- Comprobaciones mediante API antes del envío
- Reglas entre campos dentro de un componente personalizado
- Las pantallas los vinculan en tiempo de ejecución con asistentes como “vincular validación al nombre del campo”. La interfaz muestra un indicador de carga mientras se ejecuta la validación asíncrona (por ejemplo, una comprobación de nombre con debounce).
useAttachValidation(schema, {
name: async (name) => {
const taken = await checkNameExists(name)
return taken ? 'Name already exists' : true
},
})Resumen: lo que experimentas como usuario
Cuando abres “Crear clúster”, “Desplegar servicio”, “Añadir modelo” o “Gestionar secretos”:
- TrueFoundry carga (o construye) un esquema para ese recurso
- FormBuilder renderiza cada nodo del esquema como el componente de entrada deseado
- Tus ediciones actualizan un único objeto de formulario anidado
- La validación se ejecuta de forma continua y de nuevo al enviar
- El objeto final es un manifiesto: la misma estructura que usarías en YAML o en la CLI
Es por eso que TrueFoundry puede admitir interfaces de configuración muy complejas sin que cada pantalla sea un formulario único: la complejidad reside en el esquema y en una biblioteca de componentes de campo, orquestados por un tiempo de ejecución compartido.
TrueFoundry AI Gateway ofrece una latencia de entre 3 y 4 ms, gestiona más de 350 RPS en una vCPU, se escala horizontalmente con facilidad y está listo para la producción, mientras que LitellM presenta una latencia alta, tiene dificultades para superar un RPS moderado, carece de escalado integrado y es ideal para cargas de trabajo ligeras o de prototipos.



Controle, implemente y rastree la IA en su propia infraestructura
Blogs recientes
Preguntas frecuentes
¿Por qué elegir un enfoque impulsado por esquemas en lugar de codificar formularios manualmente?
Los formularios impulsados por esquemas proporcionan una única fuente de verdad para sus manifiestos de configuración. Garantizan un comportamiento uniforme de la interfaz de usuario, permiten lógica anidada/condicional sin código repetido y posibilitan que el backend defina la estructura del formulario de forma dinámica.
¿Cómo funciona la validación en FormBuilder?
La validación se realiza en dos capas: validación declarativa de esquema (utilizando reglas como obligatorio, patrón o mín/máx) y validación personalizada/asíncrona para comprobaciones respaldadas por API, como la verificación de nombres de recursos únicos.
¿Puedo integrar esto con bibliotecas de React existentes?
Sí. El FormBuilder de TrueFoundry utiliza react-hook-form como su motor de estado principal, lo que lo hace compatible con los patrones estándar de React y fácil de extender con componentes personalizados.









.webp)



.png)

.png)
.png)




.png)
.png)
.png)
.png)
.png)







