GPT Image 2.5 Flare & Sunburst ya están disponibles en EvoLinkProbar GPT Image 2.5
Vista descompuesta de componentes metálicos de precisión
Casos de uso

Cómo crear un prototipo interactivo con IA a partir de requisitos

EvoLink Team
EvoLink Team
Equipo de producto
16 de octubre de 2026
9 min de lectura

Unas tarjetas pulidas y botones aparentes no bastan si confirmar una reserva no cambia nada. Para convertir requisitos en un prototipo hay que definir el comportamiento.

Escribe primero estados y pruebas de aceptación; genera después la interfaz mínima que los demuestre. Un archivo HTML local permite revisar el flujo antes de crear el backend.

Definir una decisión que comprobar

En el ejemplo ficticio hay mañana y tarde, con dos plazas iniciales cada una. Confirmar reserva una plaza; repetir no descuenta otra; cancelar devuelve una al turno reservado.

Solo usa memoria de página. Recargar reinicia y otra pestaña no comparte capacidad. Es el límite del ejemplo, no un sistema real de reservas.

EstadoAcciónResultado
Sin selecciónIntentar confirmarDesactivado, plazas 2/2
Mañana seleccionadaConfirmarMañana 1, reserva de mañana
ReservadoRepetir confirmaciónSin segundo descuento
ReservadoCancelarMañana vuelve a 2, reserva borrada
Sin reservaCancelar otra vezCapacidad igual
Mañana completaSeleccionar Morning y después AfternoonLa mañana permanece en 0 y no admite reservas; la tarde sí
Cambiar de escenarioModificar la disponibilidad inicialBorrar reserva y selección; restablecer el escenario elegido

La tabla da un criterio común, más preciso que pedir una interfaz intuitiva.

Dar a la IA comportamiento y alcance

Construye un prototipo de reserva en un archivo HTML.
Usa controles nativos label/select/button y estado visible.
Capacidad inicial: mañana 2, tarde 2. Una reserva por sesión de página.
Sin selección, desactiva confirmar; exige capacidad positiva.
Con reserva, impide reconfirmación y cambio de selección.
Cancelar devuelve exactamente una plaza al turno reservado y borra la reserva.
Repetir cancelar no hace nada. Anuncia cambios con una región live polite.
Sin bibliotecas, red, datos personales, pagos ni persistencia.
Devuelve HTML completo, apertura y casos de aceptación.
No afirmes garantías de concurrencia o reserva en producción.
Usa Agent o API de EvoLink Gemini 4. Pide el archivo completo, no una captura ni una lista de componentes, y conserva requisitos y código juntos.

Envíe la tabla de estados con el prompt y solicite un HTML completo. Ábralo y recorra los casos de aceptación; una captura o la palabra «implementado» no sustituyen al archivo funcional.

  1. Abre la página de Gemini 4 en EvoLink y sigue las instrucciones de Agent o API. Envía juntos la tabla de estados y el prompt. Añade dos escenarios: disponibilidad normal 2/2 y mañana completa 0/2. Cambiar de escenario borra la selección y la reserva. Pide un diseño legible, plazas restantes y mensajes claros de confirmación, cancelación y aforo completo.
  2. Solicita un documento HTML completo, con estilos y script. Con un Agent, pide guardarlo como booking.html; con un cliente API, guarda el texto HTML devuelto sin los delimitadores Markdown. No guardes la envoltura JSON como HTML. Antes de abrirlo, comprueba que no incluya scripts remotos ni peticiones de red inesperadas.
  3. Abre booking.html en el navegador. En el escenario normal, selecciona Morning y confirma: las plazas pasan de 2 a 1 y aparece la confirmación. Cancela: vuelven a 2 y se borra la selección. Invocar otra vez el controlador de cancelación en una prueba debe mantener el contador en 2.
  4. Cambia a Morning full y selecciona Morning: deben aparecer 0 plazas, un aviso de aforo completo y la confirmación desactivada. Afternoon sigue disponible; al confirmar, sus plazas pasan de 2 a 1. Volver a Normal borra la reserva y restablece 2/2. Este control prepara datos de prueba; no simula otros usuarios ni concurrencia en el servidor.
  5. Si algo falla, devuelve por la misma integración el estado inicial, los clics, el resultado esperado, el resultado real y el HTML. Pide una corrección concreta y repite ambos escenarios. Registra los resultados aceptados y el consumo antes de comparar otro modelo mediante la pasarela; generar un archivo no demuestra por sí solo calidad ni ahorro.

Prototipo de referencia ejecutable

Guárdalo como booking.html y ábrelo:

La referencia siguiente es un ejemplo didáctico escrito, no una respuesta registrada de un modelo. La interfaz permanece en inglés en todos los idiomas para mantener idéntico el archivo ejecutable. El diseño y los mensajes permiten revisar el flujo, pero no representan el diseño final del producto.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Session booking · Review prototype</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; background: #f4f6f8; color: #172033; font: 16px/1.6 system-ui, sans-serif; }
main { max-width: 640px; margin: 48px auto; padding: 28px; background: white; border: 1px solid #dce2ea; border-radius: 16px; }
h1 { margin: 8px 0; font-size: 30px; line-height: 1.2; }
p { margin: 12px 0; }
.eyebrow { color: #526077; font-size: 13px; text-transform: uppercase; letter-spacing: .08em; }
label { display: block; font-weight: 600; margin: 16px 0 6px; }
select, button { font: inherit; padding: 10px 14px; border: 1px solid #aeb9c8; border-radius: 8px; }
select { width: 100%; background: white; color: #172033; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
button { cursor: pointer; background: white; color: #172033; }
#confirm { background: #193e87; color: white; border-color: #193e87; }
button:disabled { opacity: .5; cursor: not-allowed; }
:focus-visible { outline: 3px solid #b56b00; outline-offset: 3px; }
#status { background: #edf3fc; padding: 16px; border-radius: 8px; }
small { display: block; color: #526077; }
fieldset { margin: 28px 0 0; padding: 16px; border: 1px dashed #aeb9c8; border-radius: 8px; }
legend { font-weight: 600; }
@media (max-width: 680px) { main { margin: 16px; padding: 20px; } }
</style>
</head>
<body><main>
<p class="eyebrow">Interactive prototype · Local demo</p>
<h1>Book a workshop session</h1>
<p>Choose a session, confirm your place, or cancel to release it.</p>
<p id="capacity"></p>
<label for="slot">Session</label>
<select id="slot"><option value="">Choose a session</option>
<option value="am">Morning</option><option value="pm">Afternoon</option></select>
<div class="actions">
<button id="confirm" type="button" disabled>Confirm booking</button>
<button id="cancel" type="button" disabled>Cancel booking</button>
</div>
<p id="status" role="status" aria-live="polite"></p>
<small>One booking per page. Refresh resets this demo; other tabs do not share availability.</small>
<fieldset><legend>Review scenarios</legend>
<label for="scenario">Starting availability</label>
<select id="scenario"><option value="normal">Normal · 2 morning / 2 afternoon</option>
<option value="full">Morning full · 0 morning / 2 afternoon</option></select>
<p><small>Changing the scenario clears the current booking and selection. This control is for review only.</small></p>
</fieldset>
</main>
<script>
const capacity = { am: 2, pm: 2 };
const names = { am: "Morning", pm: "Afternoon" };
let selected = "";
let booking = null;
const slot = document.getElementById("slot");
const scenario = document.getElementById("scenario");
const confirmButton = document.getElementById("confirm");
const cancelButton = document.getElementById("cancel");
const status = document.getElementById("status");
const availability = document.getElementById("capacity");
function render(message = "") {
  const valid = Object.hasOwn(capacity, selected);
  confirmButton.disabled = !valid || booking !== null || capacity[selected] <= 0;
  cancelButton.disabled = booking === null;
  slot.disabled = booking !== null;
  availability.textContent = `Available: morning ${capacity.am}, afternoon ${capacity.pm}`;
  status.textContent = message || (booking !== null
    ? `Booked: ${names[booking]}. Your place is reserved in this demo.`
    : valid && capacity[selected] === 0
      ? `${names[selected]} is full. Choose another session.`
      : "Choose a session to book your place.");
}
slot.addEventListener("change", () => { selected = slot.value; render(); });
confirmButton.addEventListener("click", () => {
  if (!Object.hasOwn(capacity, selected) || booking !== null || capacity[selected] <= 0) return;
  capacity[selected] -= 1;
  booking = selected;
  render();
});
cancelButton.addEventListener("click", () => {
  if (booking === null) return;
  const cancelled = names[booking];
  capacity[booking] += 1;
  booking = null;
  selected = "";
  slot.value = "";
  render(`${cancelled} booking cancelled. Your place has been released.`);
});
scenario.addEventListener("change", () => {
  capacity.am = scenario.value === "full" ? 0 : 2;
  capacity.pm = 2;
  booking = null;
  selected = "";
  slot.value = "";
  render("Review scenario reset. Choose a session to test it.");
});
render();
</script>
</body></html>
Los botones nativos admiten teclado. La región live anuncia cambios sin mover el foco. Aun así, revisa teclado y tecnología de asistencia en el entorno destino.

Probar comportamiento antes del diseño

Sin selección, confirmar debe estar desactivado. Elige mañana, confirma y revisa el estado. Cancela y comprueba dos plazas en ambos turnos. Repite cancelar mediante interfaz o pruebas: no puede aparecer una tercera plaza.

Prueba después tarde y verifica que se borra la reserva antes de cambiar. Los controles del manejador también importan: desactivar el botón no basta si otro código lo invoca otra vez.

El aforo completo ya se puede comprobar directamente en Review scenarios. Los errores de red y las solicitudes pendientes quedan fuera de este ejemplo local; define esos estados antes de conectar un servicio real.

Detectar huecos del requisito

ObservaciónPregunta
Cambiar de turno después de reservar¿Cancelar y reservar o transferencia independiente?
Dos personas quieren la última plaza¿Qué servidor controla capacidad y conflictos?
Recargar pierde la reserva¿Incluye persistencia el alcance?
No se puede usar con teclado¿Bastan etiquetas, orden de foco y avisos?

La implementación posterior necesita capacidad autoritativa y conflictos en backend. El contador local no prueba concurrencia.

En Next.js reutiliza el sistema de componentes y límites de estado del proyecto, sin pegar esta página directamente en producción. Es un artefacto para hacer concreta una decisión de producto.

Entregar requisitos y archivo juntos

Guarda revisión, prototipo, aceptación, resultados observados y preguntas pendientes. Si cambia cancelación, actualiza tabla e interfaz y repite las pruebas afectadas.

Para una actividad de aprendizaje con respuestas justificadas y puntuación, continúa con artículo a cuestionario.

Preguntas frecuentes

¿Necesita backend un prototipo clicable?

No para este flujo local. Reservas compartidas y capacidad persistente sí necesitan una implementación autoritativa.

¿Qué doy además del diseño?

Estados, acciones, resultados, fallos y alcance. Una imagen no define transiciones.

¿Basta con desactivar el botón?

Comprueba también el manejador para impedir actualizaciones inválidas.

¿Por qué cancelar dos veces?

Detecta que se devuelva más de una plaza para una reserva.

¿Puedo copiarlo a producción?

Adáptalo a la arquitectura y completa backend, validación y accesibilidad antes de depender de él.

¿Cuándo está listo para revisión?

Abre, cumple las interacciones acordadas y permite reproducir pruebas con límites conocidos.

Fuentes

Integra modelos de IA mediante una API unificada

Compara modelos y precios actuales y sigue la documentación de la API para integrar el modelo que mejor se adapte a tu tarea.