Communitygithub.com

Diseño por Historia de Usuario

Crea un prototipo HTML autónomo de un producto digital, organizado por historias de usuario y dispositivos, con un selector de historia y dispositivo integrado para facilitar la revisión.

¿Qué es Diseño por Historia de Usuario?

Esta habilidad transforma historias de usuario en un prototipo de producto totalmente funcional y autocontenido en un solo archivo HTML. Está diseñada para que los revisores puedan seleccionar una historia de usuario específica y ver exactamente las pantallas y los datos que esa historia necesita, en múltiples dispositivos (web, Android, iPhone, iPad), todo en un mismo archivo. La habilidad integra la historia con sus criterios de aceptación, prioridad, estado y notas, y gestiona todo el ciclo de vida: desde la recopilación de requisitos, pasando por la creación de prototipos, hasta la verificación y modificación posterior de las historias. Soporta formatos de historias de usuario (incluyendo Given/When/Then para criterios de aceptación), la división de historias complejas en otras más pequeñas y la sincronización con sistemas de seguimiento de proyectos como Jira. Es ideal para equipos de producto, diseñadores y desarrolladores que necesitan iterar rápidamente sobre las funcionalidades de una aplicación y obtener retroalimentación visual temprana.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/rinkledink/design-by-story-skill/tree/HEAD/design-by-story

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Diseño por Historia de Usuario?

Construye un prototipo HTML de un solo archivo de un producto, visible en varios dispositivos, y desglosado por historia de usuario de la misma manera que se desglosa por dispositivo.

La barra superior tiene dos selectores:

  • Dispositivo: p. ej. Sitio web · Android · iPhone. Mismo producto, marco diferente.
  • Historia: "Todas las historias" más una entrada por cada historia de usuario. Al seleccionar una historia, se restablecen los datos compartidos a los datos iniciales de esa historia, se envía cada dispositivo a la pantalla de inicio de la historia y se abre un panel con la historia, prioridad, estado, criterios de aceptación, recorrido y notas.

Ambas selecciones viven en el hash de la URL (#story=S2&device=iphone), por lo que se puede pegar un enlace a una historia en un dispositivo en una revisión o ticket.

Flujo de trabajo

  1. Recopilar entradas (pregunta solo por lo que falte, en un solo mensaje):

    • Qué es el producto y quién lo usa.
    • Qué dispositivos mostrar. Por defecto: Sitio web + Android + iPhone. Tablet si se usa en campo / quiosco.
    • Las historias de usuario, en cualquier formato (una lista, una exportación del backlog, documentos de funcionalidades).
    • Formato de CA: Given/When/Then o reglas simples? Por defecto, Given/When/Then.
    • Prioridad (MoSCoW) y estado, si los tienen. De lo contrario, por defecto should / draft.
    • El modelo de datos principal (registro principal + campos clave), o inferirlo de las historias.

    Normaliza cada historia al formato de historia. Si el usuario no tiene historias, redacta de 3 a 6 a partir de la descripción del producto y confírmalas antes de construir.

  2. Verificar las historias con la lista de verificación de calidad. Plantea los problemas en una lista breve. No reescribas en silencio las palabras del usuario.

  3. Planificar pantallas por historia. Para cada historia, enumera las pantallas que toca en cada dispositivo y los datos iniciales que necesita. Una historia omite un dispositivo solo cuando el producto realmente funciona así (p. ej., administración solo en el sitio web). Su lista de devices lo indica, y el selector deshabilita los otros dispositivos mientras está seleccionada.

  4. Copiar assets/shell.html a la ruta elegida por el usuario (por defecto docs/reference/prototype.html) y rellenarlo. Lee references/prototype-spec.md para conocer las reglas visuales (marcos, tokens, tipografía, tarjetas, píldoras, toasts, cajones, iconos, tono de las copias).

  5. Construir pantallas, no historias. Las pantallas se comparten; las historias son puntos de entrada y datos iniciales para ellas. Nunca dupliques una pantalla por historia. Si una historia necesita una variante, condúcela desde los datos iniciales.

  6. Verificar en un navegador. Usa una herramienta de navegador si tienes una. De lo contrario, usa Chrome sin interfaz gráfica: --dump-dom "file://…/prototype.html#story=S2&device=iphone" para comprobar lo que se renderizó, --screenshot para verlo y --enable-logging=stderr para capturar errores de consola. Comprueba que:

    • cada historia en cada dispositivo que lista se abre en la pantalla correcta;
    • cada CA se puede demostrar y se puede hacer clic en el recorrido;
    • cambiar de dispositivo a mitad de la historia mantiene el estado;
    • ningún control de una historia aparece debajo de otra, y "Todas las historias" tiene todos los controles de cada historia funcionando juntos;
    • la consola está limpia.
  7. Mantenerlo sincronizado. Cuando se agregue o cambie una historia más adelante, actualiza su entrada #story-text, su entrada BEHAVIOUR y cada dispositivo que enumere en la misma edición.

Formato de historia

Una historia vive en dos lugares del shell, ambos identificados por su id:

  • su texto en el bloque JSON #story-text, mostrado como solo lectura en el panel de la historia;
  • su comportamiento en BEHAVIOUR, que es solo código.
<script type="application/json" id="story-text">
{
  "S1": {
    "title": "Guardar una búsqueda",
    "story": "Como visitante, quiero guardar una búsqueda, para enterarme de nuevas coincidencias sin tener que buscar de nuevo.",
    "priority": "must",
    "status": "draft",
    "ac": [
      { "id": "S1-AC1", "text": "Dado que he buscado \"mesa de roble\", cuando toco Guardar búsqueda, entonces aparece en Guardados" },
      { "id": "S1-AC2", "text": "Dado que esa búsqueda ya está guardada, cuando la guardo de nuevo, entonces Guardados todavía la muestra una vez" }
    ],
    "acNext": 2,
    "walkthrough": ["Buscar \"mesa de roble\"", "Tocar Guardar búsqueda", "Abrir Guardados"],
    "outOfScope": ["Alertas por correo electrónico"],
    "assumptions": ["Los visitantes deben iniciar sesión para guardar"],
    "questions": ["¿Hay un límite en las búsquedas guardadas?"]
  }
}
</script>
const BEHAVIOUR = {
  S1: {
    devices: ['web', 'android', 'iphone'],         // a qué marcos se aplica esta historia
    start: { web: 'search', android: 'search', iphone: 'search' }, // pantalla por dispositivo
    features: ['save-search'],                      // qué activa esta historia
    seed: () => ({ user: SIGNED_IN, saved: [] }),  // datos nuevos para esta historia
  },
};
CampoReglas
storyComo <persona>, quiero <acción>, para <beneficio>. El beneficio es lo que gana el usuario, no una repetición de la acción.
prioritymust · should · could · won't (MoSCoW).
statusdraft · in review · agreed.
acObjetos { id, text }. Las IDs son <story>-AC<n>, nunca se renumeran, nunca se reutilizan. Ver más abajo.
acNextEl número de CA más alto jamás emitido para esta historia. Una nueva CA toma acNext + 1, y acNext se actualiza para coincidir. Actualízalo cada vez que agregues una CA.
walkthroughEl guion de demostración por el que un revisor hace clic. No son criterios de aceptación; mantenlo breve.
outOfScope, assumptions, questionsListas simples. Déjalas vacías en lugar de inventar contenido de relleno. Registra cualquier cosa de la que el usuario no esté seguro como una pregunta.

seed() devuelve un objeto nuevo en cada llamada, por lo que volver a seleccionar una historia siempre la reinicia desde cero. "Todas las historias" usa DEFAULT_SEED y la pantalla de inicio de cada dispositivo.

Criterios de aceptación

  • Un comportamiento comprobable por CA, en el formato elegido por el usuario. Given/When/Then es una línea: Dado <contexto>, cuando <acción>, entonces <resultado observable>.
  • Copia exacta: cuando una CA trata sobre un mensaje, cita el mensaje (entonces veo "Nada abierto ahora mismo."), nunca "un mensaje amigable".
  • Resultados, no estilo: "se muestra como Hecho", no "aparece una píldora verde". Un detalle visual es una CA solo cuando es el requisito.
  • Comprobable en un solo dispositivo. No escribas CAs sobre otros dispositivos ("aparece en todos los dispositivos", "solo en web", "los teléfonos no pueden cambiarlo"). Qué dispositivos cubre una historia pertenece a devices, y la sincronización entre dispositivos es responsabilidad del backend.
  • Las IDs son permanentes. S1-AC3 conserva su ID cuando se edita, mueve o divide en una historia hija, para que pueda rastrearse hasta las pruebas y los tickets. Las nuevas CAs toman acNext + 1. Las IDs eliminadas nunca se reasignan y nada se renumeran.

Lista de verificación de calidad

Verifica cada historia antes de construirla y cada vez que cambie:

  • ¿Es la persona un rol de usuario real, y es el beneficio algo que dirían?
  • ¿Aporta valor por sí sola (independiente) y es lo suficientemente pequeña para demostrarla en menos de un minuto? Si no, divídela.
  • ¿Tiene cada CA una ID, un único comportamiento y un resultado observable?
  • ¿Están cubiertos los casos vacíos, de error y de límite, o figuran en questions?
  • ¿Son visibles las dependencias de otras historias? (Una clave de funcionalidad compartida, más una mención en assumptions, p. ej., "Se basa en S2".)

La funcionalidad de la historia está desactivada hasta que se selecciona la historia

Cada interacción que introduce una historia obtiene una clave de funcionalidad, listada en features de esa historia. can('save-search') es true solo mientras esté seleccionada una historia que la enumere.

  • Renderizado: envuelve los controles de la historia en can(...) para que no existan de otro modo (sin botón, sin formulario, sin elemento de menú). No los muestres desactivados. Los revisores deben ver solo lo que añade la historia seleccionada.
  • Manejadores: inicia cada manejador de historia con if (!can('save-search')) return; para que no se active nada fuera de la historia, incluso desde un DOM obsoleto o la consola.
  • "Todas las historias" activa todas las funcionalidades de todas las historias a la vez: el producto completo tal como está, en DEFAULT_SEED. Verifica que las historias no entren en conflicto allí (p. ej., dos controles en el mismo lugar).
  • Una historia que depende de la interacción de otra historia enumera ambas claves (p. ej., "Filtrar por estado" enumera ['filter', 'complete'] para que marcar una tarea como completada se pueda mostrar saliendo de la lista filtrada).
  • Los datos que una historia solo muestra (p. ej., las iniciales de un asignado) no están restringidos; solo lo está la capacidad de cambiarlos.

Cambio de historias

El prototipo solo muestra historias; nunca las edita ni las guarda. Todos los cambios de historia pasan por Claude, en el chat:

  • Nueva historia: redacta la historia, las CAs y las preguntas, ejecuta la lista de verificación de calidad con el usuario, luego escribe la entrada #story-text y la entrada BEHAVIOUR y construye las pantallas en una sola edición. Una historia nunca existe solo como texto. Si así fuera, el shell la omitiría del selector y registraría un error en la consola.
  • Historia cambiada (redacción, CAs, prioridad, estado, notas): edita #story-text. Si el cambio altera lo que hace la historia (una nueva CA, un recorrido diferente), actualiza las pantallas y BEHAVIOUR para que coincidan en la misma edición.
  • Comentarios de revisión: cuando el usuario transmite los comentarios de los revisores, convierte cada uno en uno de los cambios anteriores, o en una entrada en questions si aún está abierta.
  • Di siempre lo que construiste o cambiaste, por historia e ID de CA.

Si el usuario mantiene las historias en un rastreador (Jira o similar), el rastreador es la copia maestra. Refleja su redacción aquí en lugar de editar historias solo en el prototipo.

División de una historia

Cuando el usuario pida dividir una historia, o una historia tenga más de unas 5 CAs, más de una clave de funcionalidad principal, o CAs que podrían enviarse por separado, divídela.

  1. Elige un patrón de división y di cuál usaste:

    • pasos del flujo de trabajo (crear → revisar → publicar)
    • operaciones (añadir / editar / eliminar)
    • camino feliz primero, luego casos extremos (vacío, duplicado, límite alcanzado)
    • por dispositivo o rol (captura en teléfono vs. gestión en sitio web)
    • por variación de datos (un elemento → muchos, una moneda → varias)
    • simple primero, luego extras (ordenación simple → preferencias de ordenación guardadas)

    Cada hijo debe seguir siendo un Como… quiero… para… completo con valor propio.

  2. Numera a los hijos a partir del padre: S3 → S3.1, S3.2, … Elimina al padre tanto de #story-text como de BEHAVIOUR y coloca a los hijos donde estaba. El readHash del shell envía un enlace antiguo #story=S3 a S3.1, para que los enlaces compartidos sigan funcionando.

  3. Particiona, no dupliques:

    • Criterios de aceptación. Cada CA del padre se mueve a exactamente un hijo con su ID original (S3-AC2 sigue siendo S3-AC2 dentro de S3.1). Si una CA abarca dos hijos, reescríbela en dos nuevas CAs (S3.1-AC1, S3.2-AC1) y anota qué ID del padre reemplazan.
    • Claves de funcionalidad. Divide una clave si su interacción se divide (filter → filter-status, filter-counts). Un hijo también puede enumerar la clave de un hermano cuando se basa en ella, como en la regla de dependencia anterior.
    • Dispositivos. Cada hijo enumera solo los dispositivos que realmente toca.
    • Semillas. El seed() de un hijo posterior comienza desde el estado que dejarían los hijos anteriores (p. ej., S3.2 siembra algunos elementos ya guardados), para que cada hijo pueda revisarse por sí solo.
    • Notas. Dale a cada hijo los elementos fuera de alcance, suposiciones y preguntas que le correspondan. Los hijos heredan la prioridad del padre a menos que el usuario diga lo contrario.
  4. Actualiza las pantallas: vuelve a restringir cualquier control que se haya movido a una clave diferente. Luego verifica cada hijo en cada dispositivo que enumera y verifica que el id del padre redirija.

  5. Informa de la división como una tabla breve (id del hijo, historia, prioridad, dispositivos, IDs de CA) para que el usuario pueda verificar que cada CA del padre haya ido a parar a algún sitio. Refleja la división en su backlog o documentos de funcionalidades si guarda historias allí.

Reglas

  • Un solo archivo HTML, CSS/JS en línea, sin paso de compilación, sin framework, sin backend. Ábrelo directamente desde el disco.
  • Todos los datos en un único state compartido en memoria; cada dispositivo lo lee y escribe.
  • Las funciones de renderizado toman el id del dispositivo y redibujan desde state (ver shell).
  • Usa datos de muestra inventados y neutrales. Nunca copies nombres, marcas o contenido de otros proyectos en el prototipo.
  • Los marcos móviles renderizan el mismo marcado de la aplicación; las diferencias entre Android y iPhone son cromadas (barra de estado, notch/isla, barra de gestos), no aplicaciones separadas, a menos que el usuario solicite una interfaz de usuario específica de la plataforma.

Skills relacionados