00-day-brief.md
00 — Day brief · 2026-08-28 · MANTA
Decisiones ALS-2 BRIEF
| Campo | Valor |
|---|---|
| Fecha | 2026-08-28 |
| Nombre | MANTA |
| Complejidad | Nivel 1 (no L2 consecutivo tras PIÑÓN) |
| Sector | Economía circular / merendero de trueque de barrio (plaza de Usera) |
| Tipo | Plano de plaza + dejar/llevarse un trasto + mesa REGIDORA JWT |
| Plataforma | Web responsive (plano en el móvil · mesa en el portátil de la portera) |
| Registro | R-CL — merendero clásico, no app de marketplace |
| Shell | S-BOTTOM — Plaza · Dejar · Mesa |
| Home | H-MAP · FOLD-MAP — plaza a sangre con 4 hotspots encima, no panel lateral de cards |
| Fold | FOLD-MAP (CRON §5.9). No FOLD-SPLIT de LOMO ni grid 2×2 al lado del hero. |
| Flujo | F-MKT — llevarse un trasto (una pieza, sin carrito) |
| Por qué no PIÑÓN | No S-TOP / H-BENTO / F-CMP; no taller; no ganchos |
| Por qué no BOBINA | No S-DOCK / H-FEED / F-STORY; no cineclub |
| Por qué no LOMO | No S-CMD / H-DATA / F-LEAD; no mesa de ejemplares |
| Por qué no DERIVA | DERIVA era paseo turístico F-MAP; aquí F-MKT de un objeto, no una ruta |
| Por qué no CESTA | CESTA era tabla de necesidades ONG; aquí plano de mantas, no despensa |
| Por qué no PLIEGO | No lookbook de atelier; no se vende ropa nueva |
Terna unicidad
R-CL · S-BOTTOM · H-MAP · F-MKT
0 códigos iguales a N−1 (PIÑÓN: R-HY · S-TOP · H-BENTO · F-CMP).
≥2 distintos vs N−2 (BOBINA: S-DOCK · H-FEED · F-STORY) y N−3 (LOMO: S-CMD · H-DATA · F-LEAD).
S-BOTTOM, H-MAP y F-MKT no están en los últimos 5.
R-CL cumple la mezcla de 4 días (PIÑÓN R-HY, BOBINA R-IN, LOMO R-CL).
Ground (CRON §5.6)
- Familia: G-BONE (botanical)
- Hex:
#F4F1E8 - Por qué: no grafito de nave (PIÑÓN), no terciopelo (BOBINA), no caliza (LOMO), no cartel blanco (ONDA), no hielo (RAMAL). El merendero se lee con hueso de plaza y musgo, no con sepia de rastro vintage (primer instinto).
Mood visual (Paper)
- Candidatos: rastro vintage sepia (primer instinto), arid/dust, botanical, rusted, pastoral
- Elegido: botanical — no el primer instinto El Rastro. Un domingo en Usera se lee con geranio, plátano de sombra y hueso de muro, no con sepia de mercadillo “vintage”.
- Paleta:
#F4F1E8hueso de muro (ground)#1A2B1Cmusgo profundo (ink)#FFFFFFficha#3F6B4Amusgo (mark)#6E7A70mute#C45C4Ageranio (poco)
- Tipo: Libre Baskerville display · Nunito Sans UI
Home foto-led (D-P1-09)
UI-01 = Deriva en plano: tile de la plaza a sangre (≥40 % del recorte 16/10) + lead + 3 datos (libres / pedidos / entregados) + 4 mantas. No tabla H-DATA. Cuota last 6 ya cumple 3; aun así la home pública lleva foto.
Alcance L1 must
- Home plano foto-led: 4 mantas + 3 métricas
- Dejar un trasto (nombre, teléfono, qué es, color)
- Llevarse un trasto (F-MKT, una pieza, sin carrito)
- Success con código
- Login JWT REGIDORA
- Mesa de mantas (LIBRE / PEDIDO / ENTREGADO) — no kanban
- Empty / error / loading / mobile
- ≥12 UX + ≥10 UI
Microcopy duro
- Dejar el trasto ≠ vender en Wallapop. No hay puja ni anuncio.
- Trueque ≠ subasta. No se puja.
- Llevarse ≠ reservar IKEA. No hay carrito.
- MANTA no es Wallapop.
Supuestos
- S1: El merendero atiende 4 trastos/mañana en el slice; demo 4. [SUPUESTO]
- S2: El vecino deja o se lleva sin cuenta. JWT solo REGIDORA. [SUPUESTO]
- S3: Sin pagos, sin GPS, sin chat, sin kanban, sin e-commerce. [DECISIÓN]
- S4: Usera / plaza es atrezzo, no un merendero real. [SUPUESTO de plaza]
Hipótesis
| ID | Señal |
|---|---|
| H1 | Un plano de mantas reduce «¿sigue ahí la lámpara?» por WhatsApp |
| H2 | Una pieza por vez evita el carrito que convierte el trueque en tienda |
| H3 | Cuatro trastos bastan; no hace falta el catálogo de Wallapop |
Seed demo
| Código | Trasto | Color | Estado |
|---|---|---|---|
| MNT-2801 | Lámpara de pie | crema | LIBRE |
| MNT-2802 | Silla de enea | madera | PEDIDO |
| MNT-2803 | Cuna plegable | crudo | LIBRE |
| MNT-2804 | Maleta rígida | verde | ENTREGADO |
Objetos son catálogo demo. No es un merendero real. [SUPUESTO de plaza]
JWT
nines@manta.plaza / password123 · rol REGIDORA · API :3028
00-paper-reference.md
Paper reference · MANTA
| URL | https://app.paper.design/file/01M13JZXPYG2GXDC3HWW5K8X6K |
| File ID | 01M13JZXPYG2GXDC3HWW5K8X6K |
UX-count: 12 UI-count: 12
UX process (prefijo UX- · mínimo 12)
| ID | Nombre | Contenido |
|---|---|---|
| UX-00 | Cover | Identidad botanical, terna, foto plaza |
| UX-01 | Stakeholders | Nines REGIDORA, Pilar VECINA |
| UX-02 | Personas | Pilar 62 / Nines 48 |
| UX-03 | JTBD | Funcional / emocional / social |
| UX-04 | Stories | Must dejar / llevar / mesa |
| UX-05 | Journey | Descubrir → manta → trato → código |
| UX-06 | Blueprint | Frontstage / mesa / Neon / 409 |
| UX-07 | Site map | S-BOTTOM Plaza · Dejar · Mesa |
| UX-08 | Flujos | POST trastos + tratos + JWT |
| UX-09 | Datos + permisos | Trasto / Trato / User |
| UX-10 | Métricas | North star trastos recogidos |
| UX-11 | Research notes | COMPROBADO / SUPUESTO / HIPÓTESIS / DECISIÓN |
UI producto (prefijo UI- · mínimo 10)
| ID | Nombre | Flujo |
|---|---|---|
| UI-01 | Plaza Deriva foto-led | Home H-MAP ≥40 % |
| UI-02 | Dejar trasto | F-MKT dejar |
| UI-03 | Llevarse | F-MKT una pieza |
| UI-04 | Success | MNT-2805 copy duro |
| UI-05 | Login | JWT REGIDORA |
| UI-06 | Mesa | LIBRE / PEDIDO / ENTREGADO |
| UI-07 | Empty | No hay mantas |
| UI-08 | Error | 409 no libre |
| UI-09 | Loading | Skeletons |
| UI-10 | Tokens | G-BONE botanical |
| UI-11 | Mobile plaza | Core 390 |
| UI-12 | Mobile dejar | Form 390 |
01-project-definition.md
01 — Definición de proyecto — MANTA
1. Identidad
| Campo | Valor |
|---|---|
| Nombre | MANTA |
| Significado | La manta es el suelo del merendero de barrio: se deja un trasto, se lleva otro. No es un anuncio. |
| Eslogan | «La manta, no el anuncio.» |
| Una frase | Plano foto-led de plaza + dejar/llevarse un trasto + mesa REGIDORA JWT. |
| Sector | Economía circular / merendero de trueque de barrio (plaza de Usera, Madrid) |
| Tipo | Web L1 — plano H-MAP Deriva + chrome S-BOTTOM + mercado F-MKT de una pieza + mesa JWT — Nivel 1, vertical slice de merendero |
| Plataforma | Web responsive (plano en el móvil · mesa en el portátil de la portera) |
| Mercado demo | España · Madrid · Usera (una plaza, no Wallapop) |
| Idioma | es-ES |
| Fecha caso | 2026-08-28 |
| Terna | R-CL · S-BOTTOM · H-MAP · F-MKT |
[COMPROBADO] Nombre, terna, nivel, sector, ground y paleta salen de docs/00-day-brief.md.
[SUPUESTO de plaza] Usera / plaza / trastos seed son atrezzo de mercado, no un merendero real ni un acuerdo municipal.
Tras PIÑÓN (L2 taller, 2026-08-27) el día elige L1 merendero, no otro L2 consecutivo. N−1 es PIÑÓN. [DECISIÓN]
2. Problema
Principal (hipótesis de diseño)
[HIPÓTESIS] La vecina de Usera no necesita vender en Wallapop ni pujar ni reservar IKEA: necesita dejar un trasto en la manta y saber si la lámpara sigue ahí sin preguntar por WhatsApp. Hoy eso vive en un recado al grupo del portal, una foto borrosa y una expectativa de «tienda». Dejar el trasto se lee como vender; el trueque se lee como subasta; llevarse se lee como reservar; el producto se lee como Wallapop. [SUPUESTO] Un merendero de barrio atiende 4 trastos/mañana; no opera un catálogo ni un GPS.
Secundarios
| Problema | Quién lo sufre | Efecto |
|---|---|---|
| «¿Sigue ahí la lámpara?» por WhatsApp | VECINA (Pilar) | Pregunta, espera, pasa de ir a la plaza |
| Dejar se lee como vender | Pilar + Nines | Esperan anuncio, precio, puja |
| Trueque se lee como subasta | Pilar | Esperan timer, mejor oferta |
| Llevarse se lee como reservar IKEA | Pilar + Amparo | Esperan carrito, hold, click & collect |
| La mesa REGIDORA se lee como kanban | REGIDORA (Nines) | Esperan Recibido / En curso / Cerrado |
| El dueño pide pagos y GPS el día 1 | Plaza | El L1 se vuelve Wallapop + TROCHA |
Supuestos (no investigación primaria propia)
- S1: El merendero atiende 4 trastos/mañana en el slice; demo 4. [SUPUESTO]
- S2: El vecino deja o se lleva sin cuenta. JWT solo REGIDORA. [SUPUESTO]
- S3: Sin pagos, sin GPS, sin chat, sin kanban, sin e-commerce. [DECISIÓN]
- S4: Usera / plaza es atrezzo, no un merendero real. [SUPUESTO de plaza]
Hipótesis de producto
| ID | Hipótesis | Señal de validación (futura) |
|---|---|---|
| H1 | Un plano de mantas reduce «¿sigue ahí la lámpara?» por WhatsApp | % de visitas a / que consultan estado sin mensaje |
| H2 | Una pieza por vez evita el carrito que convierte el trueque en tienda | POST /api/tratos de un código; 0 carrito |
| H3 | Cuatro trastos bastan; no hace falta el catálogo de Wallapop | 0 catálogo infinito; Nines opera 4 mantas |
No se afirman estadísticas de plaza inventadas. Todo lo anterior es razonamiento de diseño etiquetado.
3. Propuesta de valor
| Para | Valor |
|---|---|
| VECINA (Pilar Ramos) | Ve 4 mantas en el plano, deja un trasto o se lleva uno, se lleva el código. Nadie le pide cuenta ni le vende. |
| REGIDORA (Nines Ortega) | Ve la mesa de mantas (LIBRE / PEDIDO / ENTREGADO). No mueve columnas. No cobra. |
| VECINA MAYOR (Amparo) | Fuera del login; la documentación y a11y la contemplan (contraste ink/hueso, targets, copy legible). |
| Merendero MANTA | Una superficie mínima: plano + dejar + llevarse + mesa, sin Wallapop y sin GPS. |
No es MANTA
| Excluido | Por qué |
|---|---|
| Anuncio / venta / precio | Dejar el trasto ≠ vender en Wallapop |
| Subasta / puja / timer | Trueque ≠ subasta |
| Carrito / hold / click & collect | Llevarse ≠ reservar IKEA |
| Wallapop / marketplace | MANTA no es Wallapop |
| Catálogo completo / miles de SKU | H3 · S1 |
| Chat de vecinos / kanban | Eso fue PREGÓN (H-CHAT / F-KAN) |
| Flota de última milla / GPS | Eso fue TROCHA |
| Taller de bicis / ganchos | Eso fue PIÑÓN (S-TOP / H-BENTO / F-CMP) |
| Paseo turístico / ruta | Eso fue DERIVA (F-MAP, no F-MKT de un objeto) |
| Tabla de necesidades ONG | Eso fue CESTA (H-TABLE, despensa) |
| Lookbook de atelier | Eso fue PLIEGO |
| Hero 2-col + 3 cards de «tu rastro» | Anti-patrón AP-12; contradice H-MAP Deriva |
| App de 40.000 anuncios | L1 compacto, no Wallapop |
4. Objetivos
Negocio / caso de estudio
- Demostrar vertical slice L1 merendero de barrio con Trasto + Trato + JWT REGIDORA.
- Portfolio coherente: Paper (12 UX + 12 UI) + docs + app runnable.
- Terna R-CL · S-BOTTOM · H-MAP · F-MKT frente a PIÑÓN (top/bento/cmp), BOBINA (dock/feed/story) y LOMO (cmd/datos/lead).
- No encadenar otro L2 tras PIÑÓN. [DECISIÓN]
Usuario
| Rol | Objetivo medible en demo |
|---|---|
| VECINA | Ver 4 mantas, dejar un trasto o llevarse uno y ver el success en < 90 s, sin cuenta |
| REGIDORA | Entrar a mesa, ver LIBRE / PEDIDO / ENTREGADO en < 45 s |
| VECINA MAYOR | No encuentra login forzado; a11y y docs la contemplan; no es rol de sistema |
No objetivos v1 (explícitos)
- Pagos, precio, pasarela, escrow
- GPS, tracking, mapa GIS de la ciudad
- Subasta, puja, timer
- Carrito, hold IKEA, multi-pieza
- Chat, kanban, columnas Recibido / En curso
- Cuenta de vecino, socio, newsletter
- Multi-plaza, multi-regidora
- App nativa ni notificaciones push
- Rol portera / dueño autenticado extra (Nines es la REGIDORA)
- Bicis, ganchos, MECANICO,
pinon-api(PIÑÓN es otro día) - Sesiones, butacas, PROGRAMADOR (BOBINA es otro día)
- Ejemplares, BIBLIO, comando (LOMO es otro día)
5. Roles y permisos (resumen)
| Acción | Anónimo (vecina) | REGIDORA | VECINA MAYOR |
|---|---|---|---|
Ver plaza / | Sí | Sí | Sin cuenta; usa la pública |
Ver dejar /dejar | Sí | Sí (no es el job) | — |
| POST dejar trasto | Sí | Sí (no es el job) | Sí (mismo form público) |
| POST llevarse (trato) | Sí si LIBRE | Sí (no es el job) | Sí |
Ver success /ok/:code | Sí (código en URL) | Sí | — |
Ver mesa /mesa | No (401 / redirect) | Sí | No |
GET /api/mesa | 401 | Sí | — |
| Ver teléfonos de tratos / dejas | No | Sí (mesa) | — |
| Cobrar / pujar | No (no existe) | No | Fuera |
| GPS / reparto | Copy: fuera | Copy: fuera | Oficio fuera de app |
[DECISIÓN] Un solo rol autenticado: REGIDORA. La vecina no es un usuario del sistema: es autora de un trasto (dejar) o de un trato (llevarse). Amparo no es un rol de sistema el día 1.
6. Métricas (modelo, no instrumentadas en v1 salvo base)
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | % de visitas a plaza que resuelven «¿sigue ahí la lámpara?» sin WhatsApp | Oficio de manta, no pageviews |
| Activación vecina | 1.er POST /api/trastos o /api/tratos con code | H2 |
| Integridad de expectativa | Reclamaciones «¿lo vendo?» / «¿subo puja?» / «¿lo reservo?» | H2 + microcopy |
| Integridad de auth | GET /api/mesa sin token → 401; POST trastos/tratos sin token → 201/409 | Plano público + mesa REGIDORA cerrada |
| Integridad de mercado | POST /api/tratos sobre no-LIBRE → 409 | H2 · una pieza |
| Salud | Error rate API trastos / tratos | 4xx/5xx |
7. Alcance funcional v1 (L1)
| Módulo | Incluido |
|---|---|
| Home plano | GET /api/trastos · tile de plaza a sangre + 3 métricas + 4 mantas |
| Dejar | /dejar · nombre, teléfono, qué es, color · POST /api/trastos |
| Llevarse | F-MKT sobre / · una pieza · POST /api/tratos · 409 si no LIBRE |
| Success | /ok/:code · código + 4 oposiciones |
| Auth | POST /api/auth/login → JWT REGIDORA |
| Mesa REGIDORA | GET /api/mesa JWT · LIBRE / PEDIDO / ENTREGADO, no kanban |
| Estados UI | Empty (0 trastos), loading skeleton, error de red, 409 |
| Mobile | Plaza ~390px · S-BOTTOM Plaza · Dejar · Mesa · targets ≥44px |
| Seed | 1 REGIDORA, 4 trastos (2 LIBRE, 1 PEDIDO, 1 ENTREGADO) |
| Salud | GET /api/health → { ok: true, service: "manta-api" } |
8. Criterios de aceptación de producto
/es el plano foto-led Deriva (tile de plaza a sangre ≥40 % del recorte 16/10 + lead + 3 datos + 4 mantas). No pide cuenta. No es un hero 2-col + 3 cards. No es un feed. No es una mesa de datos. No es un bento de ganchos.- Una vecina puede ver 4 trastos, dejar uno y obtener success en
/ok/MNT-XXXX, o llevarse uno LIBRE. /ok/:codedice explícitamente que dejar el trasto no es vender en Wallapop y que trueque no es subasta.- La UI dice explícitamente que llevarse no es reservar IKEA y que MANTA no es Wallapop.
- Sin token, GET
/api/mesaresponde 401. POST/api/trastos, POST/api/tratosy GET/api/trastosson públicos. - Un POST de dejar no crea user, no cobra, no abre anuncio, no mueve kanban, no enciende GPS.
- Un POST de llevarse sobre no-LIBRE responde 409. Una pieza. Sin carrito.
- Una REGIDORA inicia sesión y ve 4 trastos (2 LIBRE, 1 PEDIDO, 1 ENTREGADO) en el seed.
- El tablero autenticado es una mesa de mantas. No es un kanban de 3 columnas. No es un split lista | ficha.
- Fotos reales en las cubiertas seed (assets
trastos/*). - Chrome S-BOTTOM: Plaza · Dejar · Mesa. Home sin top de taller y sin dock de cineclub.
- Rutas solo las del doc 03. No existen
/encargo,/buscar,/carrito,/subasta,/gps. GET /api/healthdevuelveservice: "manta-api"(nopinon-api, nobobina-api).- El plano público no muestra teléfonos de otras vecinas; la mesa REGIDORA sí muestra dejas y tratos con nombre y teléfono.
- MNT-2801 y MNT-2803 aparecen LIBRE; MNT-2802 PEDIDO; MNT-2804 ENTREGADO; no se vende ninguno.
9. Stack y artefactos
| Capa | Detalle |
|---|---|
| Frontend | Angular + Tailwind · puerto 4200 |
| Backend | NestJS · puerto 3028 |
| DB | Neon PostgreSQL · project fancy-sun-85815074 (DATABASE_URL) |
| Auth | JWT (REGIDORA) |
| Diseño | Paper 01M13JZXPYG2GXDC3HWW5K8X6K |
| Repo app | /Users/cristian/orca/manta-app/ · GH Criscode2022/manta-app |
| Package | pnpm |
[COMPROBADO] Puerto, Paper file ID, path de app, Neon y GH constan en el encargo.
El código vive en manta-app con este contrato. Este doc es la fuente de verdad del slice L1.
10. Riesgos y mitigaciones
| Riesgo | Impacto | Mitigación v1 |
|---|---|---|
| Expectativa de Wallapop | «¿Lo vendo?» | Copy «Dejar el trasto ≠ vender en Wallapop» |
| Expectativa de subasta | Puja, timer | Copy «Trueque ≠ subasta» |
| Expectativa de IKEA | Carrito, hold | Copy «Llevarse ≠ reservar IKEA» |
| Expectativa de marketplace | Catálogo, SKU | Copy «MANTA no es Wallapop» |
| Expectativa de kanban | Recibido / En curso | Mesa de mantas, no columnas de flujo |
| Leftover PIÑÓN | bicis, MECANICO, pinon-api, ganchos | Contrato MANTA; health manta-api; 0 copy de taller |
| Leftover BOBINA / LOMO | sesiones, ejemplares | Dominio trastos + tratos + REGIDORA |
| Pagos el día 1 | Alcance L2/L3 disfrazado | S3; H3: cuatro mantas |
| GPS el día 1 | Alcance TROCHA | S3; roadmap L2/L3 |
| Cuenta de vecina | Rompe S2 | Sin signup; POST público con nombre + teléfono |
| Home percibida como landing de rastro | Pérdida de H-MAP / AP-12 | Deriva tile + 3 datos + 4 mantas |
| Home percibida como mapa turístico | Confundir con DERIVA | F-MKT de un objeto, no F-MAP de ruta |
| Home percibida como bento de ganchos | Confundir con PIÑÓN | Plano de plaza, no H-BENTO |
| Home percibida como tabla ONG | Confundir con CESTA | Plano, no despensa |
| Carrito en F-MKT | Rompe H2 | Una pieza; 409 si no LIBRE |
| 0 trastos | Plano vacío sin oficio | Empty «Aún no hay mantas.» |
| WhatsApp paralelo | H1 no se mide | North star etiquetada como modelo |
| Geranio como texto de párrafo | Contraste WCAG | Geranio pinta sello PEDIDO/error; ink escribe |
11. Glosario
| Término | Definición en MANTA |
|---|---|
| Manta | Suelo del merendero; superficie del plano; el producto, no el anuncio |
| Trasto | Objeto en manta (trastos); no es un anuncio de Wallapop |
| Código | MNT-XXXX; identifica el trasto / el trato |
| Dejar | POST /api/trastos; no es vender |
| Llevarse | POST /api/tratos; no es reservar IKEA |
| Trato | Acción de llevarse una pieza; no es subasta |
| Plaza | Superficie H-MAP pública de mantas; plano sobre foto de plaza |
| Mesa (REGIDORA) | Superficie JWT de Nines (mantas por estado, no kanban) |
| Libre | Estado LIBRE; se puede llevar |
| Pedido | Estado PEDIDO; ya hay un trato esta mañana |
| Entregado | Estado ENTREGADO; ya no está en la manta |
| Success | Código (MNT-XXXX); no es un ticket de tienda |
| S-BOTTOM | Chrome: Plaza · Dejar · Mesa |
| REGIDORA | Usuario autenticado que opera la mesa |
| VECINA | Autora del dejar / llevarse; no tiene fila en users |
| VECINA MAYOR | Persona de docs / a11y; fuera del login |
| Wallapop | Marketplace; fuera. Dejar ≠ vender |
| Subasta | Puja; fuera. Trueque ≠ subasta |
| IKEA | Reserva / carrito; fuera. Llevarse ≠ reservar |
| Botanical | Mood: geranio, plátano de sombra, hueso de muro; no sepia de rastro |
| Ground | Hueso de muro #F4F1E8 |
| Ink | Musgo profundo #1A2B1C |
| Card | Ficha #FFFFFF |
| Mark | Musgo #3F6B4A |
| Mute | #6E7A70 |
| Geranio | #C45C4A, poco |
| Deriva | Home foto-led: tile de plaza a sangre + 3 datos + 4 mantas |
12. Decisiones de diseño (cierre de brief)
| ID | Decisión | Alternativa descartada |
|---|---|---|
| D1 | Home = plano foto-led Deriva (H-MAP) | Hero 2-col + 3 cards (AP-12) · bento (PIÑÓN) · feed (BOBINA) · tabla (CESTA) |
| D2 | Shell bottom Plaza · Dejar · Mesa (S-BOTTOM) | Top de taller · dock de cineclub · comando de archivo |
| D3 | Registro clásico: merendero, no app de marketplace (R-CL) | Sepia rastro vintage (primer instinto) · industrial PIÑÓN |
| D4 | Flujo F-MKT (llevarse un trasto, una pieza, sin carrito) | F-CMP, F-MAP turístico, F-LEAD, carrito checkout |
| D5 | Mood botanical | Rastro vintage sepia (primer instinto), arid/dust, rusted, pastoral |
| D6 | Un rol autenticado REGIDORA | Multi-rol vecina / portera / dueño |
| D7 | Status LIBRE / PEDIDO / ENTREGADO | Kanban; «vendido»; «en ruta»; ESPERA / EN_TALLER |
| D8 | Vecina sin cuenta | Signup, socio, carnet de merendero |
| D9 | Plano público no lista teléfonos | Tablero público enumerable |
| D10 | POST público de dejar con nombre + teléfono + qué es + color | Formulario de DNI + pago + precio |
| D11 | Ground G-BONE #F4F1E8 | G-GRAPHITE, G-VELVET, G-STONE, sepia de rastro |
| D12 | Success en /ok/:code | Toast único sin pantalla |
| D13 | Dejar en /dejar; llevarse sheet sobre / (sin quinta ruta) | /llevarse/:code; carrito /checkout |
| D14 | Mesa REGIDORA = mantas por estado, no kanban ni split | Recibido / En curso / Cerrado; lista | ficha RAMAL |
| D15 | Plano público + mesa JWT (no auth-first total) | Todo cerrado (rompería S2) · todo abierto (rompería mesa) |
| D16 | Sin pagos / GPS | Precio + tracking |
| D17 | Leftover PIÑÓN no es el producto | Mantener bicis / MECANICO / pinon-api / ganchos |
| D18 | Health manta-api · puerto 3028 | leftover pinon-api · :3027 |
| D19 | Llevarse = una pieza; 409 si no LIBRE | Carrito multi-SKU; hold IKEA |
| D20 | POST tratos sobre LIBRE → PEDIDO | Pasa a ENTREGADO (saltaría el recado de plaza) |
13. Relación con el día anterior
| Case | Terna | Por qué MANTA no lo copia |
|---|---|---|
| PIÑÓN (N−1) | R-HY · S-TOP · H-BENTO · F-CMP | No taller, no ganchos, no bento, no configurador, no MECANICO |
| BOBINA (N−2) | R-IN · S-DOCK · H-FEED · F-STORY | No cineclub, no feed, no dock, no butaca |
| LOMO (N−3) | R-CL · S-CMD · H-DATA · F-LEAD | Comparte R-CL; no archivo, no ejemplares, no comando, no mesa de datos |
| DERIVA | R-IN · S-SPLIT · H-MAP · F-MAP | Comparte H-MAP; aquí F-MKT de un objeto, no ruta turística |
| CESTA | R-CL · S-RAIL · H-TABLE · F-LEAD | Plano de mantas, no despensa / tabla de necesidades |
| PLIEGO | — | No lookbook; no se vende ropa nueva |
| MATIZ | R-HY · S-BOTTOM · H-BENTO · F-EDIT | Comparte S-BOTTOM; aquí H-MAP + F-MKT, no editor de gramos |
[COMPROBADO] El brief fija terna R-CL · S-BOTTOM · H-MAP · F-MKT. 0 códigos iguales a N−1 (PIÑÓN). ≥2 distintos vs N−2 (BOBINA) y N−3 (LOMO). S-BOTTOM, H-MAP y F-MKT no están en los últimos 5. Ground G-BONE #F4F1E8, no G-GRAPHITE ni sepia de rastro.
02-ux-research-strategy.md
02 — Estrategia de investigación UX — MANTA
Importante: este documento contiene artefactos de diseño y razonamiento secundario.
No hay entrevistas de campo primarias ni estadísticas inventadas presentadas como dato medido.
Etiquetas: [COMPROBADO] en producto, [SUPUESTO], [HIPÓTESIS], [DECISIÓN].
1. Objetivos de investigación (del caso)
| Objetivo | Método en este caso | Salida |
|---|---|---|
| Entender actores del merendero de barrio | Modelado de stakeholders + personas | §3–4 |
| Definir job «dejar o llevarse un trasto y saber si sigue ahí sin WhatsApp» | JTBD + stories Must | §5–6 |
| Mapear fricción WhatsApp / Wallapop / subasta / IKEA → plano + F-MKT | Journey + service blueprint | §7–8 |
| Traducir a requisitos L1 plano + dejar + llevarse + mesa | Matriz hallazgo → requisito → feature | §9 |
2. Fuentes y límites
Fuentes admisibles (secundarias / operativas)
- Conocimiento general de merenderos / trueques de barrio (manta en plaza, recado de «¿sigue ahí?», 4 trastos a la mañana, portera que mira, grupo de WhatsApp del portal).
- Analogía operativa con superficie pública + panel JWT de la serie daily.
- Restricciones ALS-2: no Wallapop, no subasta, no reserva IKEA, no taller de bicis, no paseo turístico, no despensa ONG.
Límites éticos de verdad
| Prohibido | Permitido |
|---|---|
| «El 62% de vecinas de Usera pregunta por WhatsApp si sigue la lámpara» sin fuente | «[SUPUESTO] Pilar abre la plaza desde el móvil» |
| Citas de entrevistas ficticias como campo real | Quotes de persona etiquetadas como constructo de diseño |
| Volumen medido «18 lámparas/semana» como KPI de mercado | Trastos de seed de producto, etiquetados como demo |
| Merendero municipal oficial en Usera 2026 | Plaza de atrezzo; Nines, Pilar y Amparo son personas de diseño |
| «Pilar existe y nos dijo…» | Pilar Ramos es persona de diseño |
3. Stakeholders
| Stakeholder | Influencia | Interés | Necesidad principal |
|---|---|---|---|
| REGIDORA (Nines) | Alta | Muy alta | Ver mantas sin kanban ni anuncio |
| VECINA (Pilar) | Alta en el gesto | Muy alta | Dejar o llevarse un trasto y saber el código, sin cuenta |
| VECINA MAYOR (Amparo) | Media formal, baja en producto día 1 | Alta | Leer el plano con contraste y targets; sin login forzado |
| Plaza / merendero de barrio | Alta formal | Alta | Que se vea qué hay en la manta; que no se confunda con Wallapop |
| Wallapop / marketplace | Competencia / analogía falsa | — | Fuera de alcance; no clonar anuncio |
| Subasta / puja | Analogía falsa de trueque | — | Fuera; Trueque ≠ subasta |
| IKEA / carrito / hold | Analogía falsa de llevarse | — | Fuera; Llevarse ≠ reservar IKEA |
| PIÑÓN / taller | Anti-patrón N−1 | — | Fuera; no bicis, no ganchos, no MECANICO |
| DERIVA / paseo | Analogía falsa de H-MAP | — | Fuera; F-MKT de un objeto, no ruta |
| CESTA / despensa | Analogía falsa de merendero | — | Fuera; plano de mantas, no tabla de necesidades |
| Grupo de WhatsApp del portal | Canal paralelo | — | No es el backoffice; H1 apunta a reducirlo |
| Dueño de puesto / transportista | Fuera | — | Fuera del JWT |
Mapa de poder (resumen)
- Decisor de adopción: la plaza (quién tiende las mantas) y, en uso diario, Nines (quien mira la mesa).
- Usuario frecuente de dejar/llevarse: VECINA (plano + form, sin cuenta).
- Usuario frecuente de oficio: REGIDORA (mesa
/mesa). - Riesgo de rechazo: si el success parece un ticket de tienda; si el tile parece un anuncio; si hay que crear cuenta; si la mesa parece un kanban; si llevarse abre un carrito.
4. Personas
P1 — Nines Ortega · REGIDORA
| Campo | Detalle |
|---|---|
| Edad / contexto | 54 años; regidora del merendero MANTA en plaza de Usera; mesa de mantas, no de anuncios. Edad = constructo. |
| Digital | Fluida en el portátil de la portería; el plano público no es su herramienta principal, pero lo mira |
| Goals | Ver qué trastos están libres, cuáles tienen pedido, cuáles ya se entregaron |
| Pains | WhatsApp a deshora; «¿lo pongo en Wallapop?»; un kanban que no es su oficio; un GPS que no es su job de hoy |
| Quote de diseño | «Quiero ver las mantas. No una tienda y no una subasta.» |
| Email demo | nines@manta.plaza / password123 |
Escenario: Entra a /login, abre /mesa, lee MNT-2801 Lámpara LIBRE, ve los tratos. El copy dice que llevarse no es reservar IKEA.
[COMPROBADO] Nombre de cuenta, email demo y rol salen del encargo. Edad es constructo de diseño. [DECISIÓN]
P2 — Pilar Ramos · VECINA
| Campo | Detalle |
|---|---|
| Edad / contexto | 47 años; vive en Usera; deja un trasto el domingo o se lleva uno; no quiere «otra cuenta de Wallapop». Edad = constructo. |
| Digital | Móvil desde el banco de la plaza o el sofá; no se registra si puede evitarlo |
| Goals | Ver qué hay en las mantas; dejar un trasto; llevarse uno; llevarse un código |
| Pains | El WhatsApp dice «creo que la lámpara sigue»; abre Wallapop; le piden precio; cree que reserva como en IKEA |
| Quote de diseño | «Solo quiero dejar el trasto. No me hagas un anuncio.» |
Escenario: Abre / en el móvil, ve 4 mantas, toca la lámpara LIBRE o Dejar, escribe nombre y teléfono, lee «dejar el trasto ≠ vender en Wallapop» y el código MNT-XXXX.
[COMPROBADO] El gesto (vecina, deja o se lleva sin cuenta) sale del encargo. Nombre sale del encargo. Edad es constructo. [DECISIÓN]
Pilar no tiene fila en users. [DECISIÓN]
P3 — Amparo · VECINA MAYOR (docs / a11y)
| Campo | Detalle |
|---|---|
| Edad / contexto | 71 años; vecina de Usera; lee el plano con calma; contraste y tamaño importan. Edad = constructo de la serie a11y. |
| Digital | No tiene login en el slice L1; usa la superficie pública si el contraste y los targets aguantan |
| Goals | Entender cómo dejar o llevarse un trasto, sin mistificarse con Wallapop ni con un carrito |
| Pains | Texto mute sobre hueso; botones pequeños; copy de marketplace |
| Quote de diseño | «Si no leo la manta, no dejo el trasto. No me lo vendáis.» |
[DECISIÓN] no hay cuenta de Amparo en v1; a11y la contempla en docs 10. Sin apellido inventado más allá del nombre del encargo. Edad = constructo de diseño.
5. JTBD
Job principal (vecina)
Cuando sobra un trasto o falta uno en casa, quiero dejarlo en la manta o llevarme uno que esté libre sin preguntar por WhatsApp, para que Nines lo vea sin que eso signifique venta, cuenta, subasta ni reserva IKEA.
Job principal (regidora)
Cuando hay mantas tendidas y tratos nuevos, quiero ver LIBRE / PEDIDO / ENTREGADO, para mover el oficio de la plaza sin un kanban ni un anuncio.
Jobs que MANTA no hace
| Job | Por qué no |
|---|---|
| Vender un trasto | Dejar el trasto ≠ vender en Wallapop · S3 |
| Pujar / subastar | Trueque ≠ subasta |
| Reservar / hold / carrito | Llevarse ≠ reservar IKEA |
| Sustituir a Wallapop | MANTA no es Wallapop |
| Rastrear GPS / última milla | ≠ TROCHA · S3 |
| Dejar una bici / configurar arreglo | ≠ PIÑÓN |
| Pedir un paseo turístico | ≠ DERIVA |
| Comprometer aceite a una despensa | ≠ CESTA |
| Pedir butaca de cineclub | ≠ BOBINA |
6. Stories Must (v1)
| ID | Como | Quiero | Para |
|---|---|---|---|
| US-01 | Vecina | Ver plano foto-led de 4 mantas + 3 métricas | Distinguir merendero de Wallapop / feed / tabla / bento |
| US-02 | Vecina | Dejar un trasto (nombre, teléfono, qué es, color) y ver success MNT-XXXX | Dejar constancia, no vender |
| US-03 | Vecina | Llevarse un trasto LIBRE (F-MKT, sin carrito) | Evitar tienda |
| US-04 | Vecina | Recibir 409 si el trasto no está LIBRE | No «reservar» lo que ya no está |
| US-05 | Regidora | Entrar con JWT | Abrir la mesa de mantas |
| US-06 | Regidora | Ver LIBRE / PEDIDO / ENTREGADO + tratos | Oficio sin kanban |
| US-07 | Ambos | Ver empty / error / loading | No quedarse en blanco |
| US-08 | Vecina | Usar S-BOTTOM en 390 | Plaza · Dejar · Mesa sin hamburger |
Could (fuera de L1, solo L2/L3): pagos, GPS, login de Amparo, chat, cuenta de vecina, carrito.
7. Journey (resumen)
- Pilar abre
/. Ve tile de plaza a sangre + 3 datos (libres / pedidos / entregados) + 4 mantas. MNT-2801 LIBRE; MNT-2802 PEDIDO. [H1] - Toca la lámpara LIBRE → sheet llevarse (UI-03). Escribe «Pilar Ramos» y teléfono. POST
/api/tratos→/ok/MNT-2801. Lee las cuatro oposiciones. [H2] - Alternativa: toca Dejar →
/dejar. Nombre, teléfono, qué es, color. POST/api/trastos→/ok/MNT-2805. - Intento de silla PEDIDO → 409 «Ese trasto ya no está libre.»
- Nines entra a
/login→/mesa. Mantas por estado + tratos. - Lee MNT-2801 PEDIDO (si hubo trato) y MNT-2804 ENTREGADO. Copy: llevarse no es reservar IKEA.
Backstage: Nest + Neon + JWT. Transportista y dueño no entran. No hay Wallapop. No hay GPS.
8. Blueprint (resumen)
| Capa | Qué pasa |
|---|---|
| Frontstage (plaza / banco) | Plano Deriva en móvil. Form dejar. Sheet llevarse. Success. S-BOTTOM. |
| Backstage (portería) | Nines mira /mesa. El trueque físico es oficio, no un anuncio. GPS y caja están fuera de app. |
| Soporte | Nest · Neon fancy-sun-85815074 · JWT REGIDORA · Paper botanical |
9. Matriz hallazgo → requisito → feature
| Hallazgo (etiquetado) | Requisito | Feature v1 |
|---|---|---|
| [HIPÓTESIS H1] Plano de mantas reduce WhatsApp | 4 trastos + 3 métricas en fold sobre tile | / H-MAP Deriva |
| [HIPÓTESIS H2] Una pieza evita el carrito | POST tratos de un código; 409 si no LIBRE | UI-03 · POST /api/tratos |
| [HIPÓTESIS H3] Cuatro trastos bastan | Sin catálogo Wallapop | Seed 4 · no marketplace |
| [SUPUESTO S2] Sin cuenta de vecina | POST público | POST /api/trastos + /api/tratos |
| [SUPUESTO S1] 4 / mañana | Demo 4 | Seed MNT-2801…2804 |
| [DECISIÓN S3] Sin pagos / GPS / chat / kanban | No cobro, no tracking, no hilo, no columnas | Fuera de alcance · L2/L3 pagos/GPS |
10. Preguntas que este case no responde
- ¿Cuántos trastos reales se dejan en Usera en 2026?
- ¿Qué junta de distrito opera un merendero oficial?
- ¿Pilar preferiría el WhatsApp?
- ¿Amparo necesita un modo tipográfico mayor permanente?
- ¿Nines marcaría ENTREGADO antes de las 14:00 de verdad?
Esas preguntas piden campo. Aquí hay un vertical slice de diseño, no un estudio.
11. Cierre
Investigación = modelado etiquetado + restricciones ALS-2.
No hay entrevistas inventadas.
Paper UX-00…11 documenta el mismo arco. [COMPROBADO] inventario en 00-paper-reference.md.
03-information-architecture.md
03 — Arquitectura de información — MANTA
1. Principios de IA
| Principio | Aplicación |
|---|---|
| Plano first | La home es tile de plaza a sangre + 3 datos + 4 mantas. No hay landing de marca por delante. No hay feed. No hay mesa de datos. No hay bento de ganchos. |
| Público / mesa | Pilar deja o se lleva sin cuenta; Nines entra con JWT |
| Dejar | llevarse → success | Profundidad 1–2 desde el plano hasta el código (F-MKT) |
| El núcleo es una pieza | F-MKT: un trasto LIBRE, sin carrito |
| Mesa REGIDORA = mantas | LIBRE / PEDIDO / ENTREGADO en una mesa; no kanban, no split lista | ficha |
| Lenguaje de dominio | Trasto, manta, trato, plaza, mesa — no «SKU», «anuncio», «gancho», «bici» |
| Dejar no es vender | El success no tiene precio ni anuncio |
| Plaza no es Wallapop | No hay puja, no hay carrito, no hay catálogo infinito |
| Chrome de merendero | S-BOTTOM Plaza · Dejar · Mesa; plano sin top de taller |
2. Sitemap
/ Plaza plano público (Deriva) H-MAP
+ sheet llevarse (UI-03) F-MKT · público
/dejar Dejar un trasto público
/ok/:code Success post-dejar o post-trato público
/login Login JWT REGIDORA público
/mesa Mantas LIBRE / PEDIDO / ENTREGADO auth
/** → redirect /
Árbol por audiencia
| Audiencia | Nodos relevantes |
|---|---|
| VECINA | Plaza → Dejar o Llevarse (sheet) → Ok. No ve /mesa |
| REGIDORA | Login → Mesa · (puede leer la plaza y dejar) |
| VECINA MAYOR | Plaza / Dejar públicos; sin login |
[COMPROBADO] Cinco rutas del encargo L1. No se inventan /encargo, /carrito, /subasta, /gps, /buscar.
Llevarse no es ruta extra: es el sheet UI-03 sobre / (tap manta LIBRE). L1 compacto. [DECISIÓN]
/ok/:code usa el código de trasto (MNT-2801 en trato, MNT-2805 en dejar nuevo). [DECISIÓN]
No hay /buscar: no hay S-CMD. El hallazgo es el plano. [DECISIÓN]
No hay /trasto/:code de ficha pública permanente: el oficio de estado vive en el plano y en la mesa. Could L2. [DECISIÓN]
3. Navegación
Bottom (S-BOTTOM · todas las superficies salvo login/ok pueden mostrarlo)
| Slot | Destino | Visibilidad | Notas |
|---|---|---|---|
| Plaza | / | Todos | Vuelve al plano Deriva. No es hero de marca |
| Dejar | /dejar | Todos | Entra al form de dejar |
| Mesa | /mesa | REGIDORA; si guest → /login?next=/mesa | Oficio JWT |
[DECISIÓN] El bottom es la navegación primaria. No hay top de taller (PIÑÓN), no hay dock (BOBINA), no hay comando (LOMO), no hay rail (ONDA / CESTA).
Desktop ≥960px: barra inferior fija hueso; wordmark MANTA a la izquierda o centrado; slots Plaza · Dejar · Mesa.
Mobile ~390px: bottom compacto Plaza · Dejar · Mesa; no hamburger. [DECISIÓN] En 390 el bottom no se esconde detrás de un menú. Padding-bottom del contenido ≥ altura bar.
Plaza pública (H-MAP Deriva)
| Elemento | Destino | Notas |
|---|---|---|
| Tile de plaza a sangre | — | ≥40 % del recorte 16/10; foto-led |
| Wordmark MANTA | / | Sello mark sobre hueso |
| Eslogan | — | «La manta, no el anuncio.» |
| 3 datos | — | Libres / Pedidos / Entregados (números del seed) |
| Pin / ficha de manta | sheet llevarse si LIBRE | 4 mantas; título, color, estado |
| Tap LIBRE | UI-03 sheet | Arranque de F-MKT |
| Tap PEDIDO / ENTREGADO | sello + copy; no POST | 409 si se fuerza |
| CTA Dejar | /dejar | S-BOTTOM o lead |
| Slot Mesa (mute) | /login o /mesa si hay token | Oficio, no CTA de marca |
[DECISIÓN] La plaza no tiene tabs de marketing, no tiene «Vender / Subastar / Reservar». El plano basta para hallar.
Chrome de dejar (/dejar)
| Slot | Destino | Notas |
|---|---|---|
| ← Plaza | / | Un paso atrás, no stepper de 5 |
| Form | /dejar | Nombre, teléfono, qué es, color |
| Enviar | POST → /ok/:code | Una acción |
[DECISIÓN] Dejar no es un modal efímero sin URL. No hay wizard de criterios.
Chrome de llevarse (sheet sobre /)
| Slot | Destino | Notas |
|---|---|---|
| Cerrar | / | Conserva el plano |
| Form | mismo path | Nombre, teléfono; código en solo lectura |
| Enviar | POST /api/tratos → /ok/:code | Una pieza |
| No LIBRE | 409 / disabled | «Ese trasto ya no está libre.» |
Chrome de mesa (/mesa autenticado)
| Slot | Destino | Visibilidad | Notas |
|---|---|---|---|
| Mesa | /mesa | Auth | Titular de oficio |
| Mantas | — | Auth | Agrupadas LIBRE / PEDIDO / ENTREGADO |
| Tratos | — | Auth | Nombre + teléfono + código; no columnas de flujo |
| Plaza | / | Auth | Secundario vía S-BOTTOM |
| Salir | limpia token → / | Auth | Cabecera de mesa, no cuarto slot del bottom |
[DECISIÓN] No hay S-SPLIT (RAMAL / DERIVA). No hay kanban (PREGÓN). No hay /mesa/:code: L1 lee mantas + tratos.
4. Etiquetas de IA (UI)
| Concepto | Label |
|---|---|
| Home | Plaza (no «Inicio», no «Taller», no «Cartelera», no «Mapa turístico») |
| Flujo dejar | Dejar (no «vender», no «publicar anuncio») |
| Flujo mercado | Llevarse (no «reservar», no «añadir al carrito», no «pujar») |
| Success | Dejado / Trato / código |
| Staff | Mesa (no «Backoffice», no «Kanban», no «Hoy» JWT) |
| Auth | Regidora (no «Área cliente», no «Mecánica») |
| CTA dejar | Dejar el trasto (no «Vender», no «Publicar») |
| CTA llevarse | Llevarse (no «Reservar», no «Comprar») |
En docs puede decirse «plaza plano» para H-MAP y «mesa REGIDORA» para el oficio JWT. En UI pública el titular es Plaza. En UI autenticada el titular es Mesa. [DECISIÓN]
5. Contenido de cada nodo de IA
| Ruta | Qué hay | Qué no hay |
|---|---|---|
/ | Tile de plaza, eslogan, 3 métricas, 4 mantas, S-BOTTOM, sheet llevarse | Precios, login de vecina, carrito, GPS, ganchos |
/dejar | Nombre, teléfono, qué es, color, disclaimer | DNI, email, pago, precio, socio |
/ok/:code | Código + 4 oposiciones | Contrato, ticket, «ya está publicado», QR de tienda |
/login | Email / clave REGIDORA | Signup de vecina |
/mesa | Mantas de 4 + tratos | Columnas Recibido / En curso; split ficha; mapa GPS |
6. Error / empty / loading (sitio)
Viven en las mismas rutas, no en URLs extra. Artboards: UI-07 empty · UI-08 error · UI-09 loading.
| Estado | Superficie |
|---|---|
| Loading | Skeletons de tile + 3 datos + 4 mantas / form dejar / lista de mesa |
| Empty plaza | «Aún no hay mantas.» |
| Empty mesa tratos | «No hay tratos.» (pueden existir 4 trastos seed con 0 tratos nuevos) |
| Error red | «La red no responde» + Reintentar |
| 404 código | «Ese trasto no está» en success |
| 409 llevarse | «Ese trasto ya no está libre.» |
| Dejar incompleto | CTA disabled · «Escribe qué dejas.» |
7. Profundidad y hallazgo
No hay búsqueda Must: el hallazgo es el plano de 4 mantas. Introducir /buscar copiaría LOMO y rompería la terna. [DECISIÓN]
Nines no filtra la mesa con chips en v1: ve los tres grupos. Could L2: filtro; no se cuela como deuda del L1.
8. Códigos y URLs
| Pieza | Forma |
|---|---|
| Trasto | MNT-2801 … MNT-2804 (MNT versales, guion, 4 dígitos) |
| Dejar nuevo | MNT-2805+ secuencial al POST /api/trastos |
| Trato | mismo code del trasto LIBRE |
| Success | /ok/MNT-2801 o /ok/MNT-2805 |
9. Mapa Paper → rutas
| Artboard | Ruta | Componente |
|---|---|---|
| UI-01 Plaza Deriva | / | PlazaPage |
| UI-11 Mobile plaza | / @390 | PlazaPage |
| UI-02 Dejar | /dejar | DejarPage |
| UI-12 Mobile dejar | /dejar @390 | DejarPage |
| UI-03 Llevarse | / sheet | LlevarseSheet en PlazaPage |
| UI-04 Success | /ok/:code | OkPage |
| UI-05 Login | /login | LoginPage |
| UI-06 Mesa | /mesa | MesaPage |
| UI-07 Empty | mismas rutas | estados |
| UI-08 Error | mismas rutas | estados |
| UI-09 Loading | mismas rutas | estados |
| UI-10 Tokens | theme | Tailwind |
[COMPROBADO] Mapeo alineado a docs/00-paper-reference.md.
04-user-flows.md
04 — Flujos de usuario — MANTA
1. Convenciones
| Token | Significado |
|---|---|
| F-MKT | Llevarse un trasto LIBRE; la home es el plano, no el form |
| Mesa | Mantas REGIDORA, JWT |
| 201 | Dejado (trasto LIBRE nuevo) o trato (trasto pasa a PEDIDO) |
| 400 | Nombre / teléfono / título / color inválidos |
| 401 | Mesa sin token |
| 404 | Código inexistente |
| 409 | Llevarse un trasto que no está LIBRE |
2. F1 — Vecina se lleva un trasto desde el plano (Must · F-MKT)
/ → GET /api/trastos
→ ve 3 métricas (libres / pedidos / entregados) + 4 mantas
→ tap MNT-2801 Lámpara LIBRE
→ sheet llevarse (UI-03)
→ escribe nombre «Pilar Ramos», teléfono
→ POST /api/tratos { code: "MNT-2801", name, phone }
→ 201 { code: MNT-2801, status: PEDIDO, trato: true }
→ /ok/MNT-2801
Entrada: plaza plano, sin cuenta.
Salida: código visible + copy «llevarse ≠ reservar IKEA».
Errores: red (reintentar), 400 validación, 409 si ya no LIBRE, 0 trastos (empty de plaza).
AC
- El form no pide email, DNI, pago ni signup.
- POST no cobra, no crea user, no abre anuncio, no mueve kanban, no enciende GPS.
- Una pieza. Cero carrito. Cero segunda línea.
/ok/MNT-2801muestra las cuatro oposiciones.- El sheet existe: F-MKT no es un POST oculto sin UI. [DECISIÓN]
- Status destino = PEDIDO, no ENTREGADO. [DECISIÓN D20]
3. F2 — Vecina intenta llevarse un trasto no LIBRE (Must · 409)
/ → tap MNT-2802 Silla PEDIDO
→ CTA Llevarse disabled o POST /api/tratos
→ 409
→ copy «Ese trasto ya no está libre.»
Mismo resultado si MNT-2804 ENTREGADO, o si Pilar reintenta MNT-2801 tras un 201.
AC
- 409 si
status ≠ LIBRE. - Copy: no «agotado» retail. No «añadir a lista de espera». No «reservar».
- Pilar puede elegir MNT-2803 Cuna (LIBRE) y continuar.
4. F3 — Vecina deja un trasto (Must)
/dejar → escribe nombre «Pilar Ramos», teléfono, qué es «Espejo óvalo», color «dorado»
→ POST /api/trastos { name, phone, title, color }
→ 201 { code: MNT-2805, status: LIBRE, dejado: true }
→ /ok/MNT-2805
AC
- El form no pide precio, foto obligatoria, categoría Wallapop ni cuenta.
- POST crea trasto LIBRE + datos de quien deja (no visibles en plano público).
/ok/MNT-2805dice «Dejar el trasto ≠ vender en Wallapop».- CTA Dejar disabled si falta título / nombre / teléfono / color.
5. F4 — Regidora entra a mesa (Must)
/login → POST /api/auth/login
→ JWT REGIDORA
→ /mesa
→ GET /api/mesa
AC
- Sin token,
/mesaredirige a/login?next=/mesa. - GET
/api/mesasin Bearer → 401. - Mantas: 4 filas agrupadas LIBRE / PEDIDO / ENTREGADO + tratos (nombre, teléfono, código). No columnas Recibido / En curso.
- Desktop: grupos + tratos en el panel. 390: apilado sobre el S-BOTTOM.
- ENTREGADO sí aparece (oficio de cierre de mañana). [DECISIÓN] distinto de PIÑÓN, donde ENTREGADA se ocultaba.
6. F5 — Estados de sistema
| Estado | Trigger | UI |
|---|---|---|
| Loading plaza | GET trastos en vuelo | Skeletons de tile + 3 datos + 4 fichas (UI-09) |
| Empty plaza | 200 { trastos: [] } | «Aún no hay mantas.» (UI-07) |
| Error plaza | 5xx / red | Reintentar (UI-08) |
| Loading dejar | — | Form listo; submit pending (UI-09) |
| Loading llevarse | POST en vuelo | pending en CTA |
| 409 | no LIBRE | «Ese trasto ya no está libre.» (UI-08) |
| Loading mesa | GET mesa en vuelo | Skeletons de manta + tratos |
| Empty mesa tratos | 200 { tratos: [] } | «No hay tratos.» (las 4 mantas seed pueden existir) |
| Login 401 | credenciales | «Email o contraseña no valen.» |
| 404 success | código inexistente | «Ese trasto no está.» |
7. Flujos que no existen
| Flujo | Por qué |
|---|---|
| Signup vecina | S2 · Dejar ≠ socio |
| Vender / publicar anuncio | S3 · Dejar ≠ vender en Wallapop |
| Subasta / puja / timer | Trueque ≠ subasta |
| Carrito / hold / click & collect | Llevarse ≠ reservar IKEA |
| GPS / ruta / última milla | ≠ TROCHA · S3 |
| Chat | ≠ PREGÓN |
| Configurar arreglo / dejar bici | ≠ PIÑÓN |
| Pedir paseo / pin de ruta | ≠ DERIVA |
| Comprometer necesidad ONG | ≠ CESTA |
| Pedir butaca | ≠ BOBINA |
| Login Amparo | Slice L1 · docs / a11y |
| PATCH estado de trasto | Nines lee mantas; no mueve columnas en v1 |
| Catálogo Wallapop | H3 · S3 |
Búsqueda ?q= | Sin S-CMD |
| Multi-pieza / checkout | Rompe H2 |
8. Tiempos de demo (modelo)
| Actor | Recorrido | Techo |
|---|---|---|
| Pilar (llevarse) | Plaza → sheet → trato → código | < 90 s |
| Pilar (dejar) | Dejar → form → dejado | < 90 s |
| Pilar (409) | Silla PEDIDO → bloqueo → cuna LIBRE | < 90 s |
| Nines | Login → mesa → leer MNT-2802 PEDIDO | < 45 s |
No son KPIs medidos. Son techos de diseño para el guión. [HIPÓTESIS]
9. Guión de demo canónico
/— tile de plaza a sangre + 3 datos (2 libres / 1 pedido / 1 entregado) + 4 mantas. Eslogan. S-BOTTOM.- Lectura rápida: MNT-2801 Lámpara crema LIBRE; MNT-2802 Silla enea PEDIDO; MNT-2803 Cuna crudo LIBRE; MNT-2804 Maleta verde ENTREGADO.
- Llevarse — tap lámpara · Pilar Ramos · teléfono · POST →
/ok/MNT-2801. Copy ×4. - Reintento lámpara → 409.
- Dejar —
/dejar· Espejo óvalo · dorado ·/ok/MNT-2805. /login—nines@manta.plaza/password123./mesa— mantas LIBRE / PEDIDO / ENTREGADO; MNT-2801 PEDIDO si se hizo el trato; trato de Pilar visible.- 390: plano + S-BOTTOM; no carousel; targets ≥44px.
- API down: error + Reintentar.
10. Contratos de error de API (flujo)
| Caso | HTTP | UI |
|---|---|---|
| POST dejar, título vacío | 400 | «Escribe qué dejas.» |
| POST dejar, nombre vacío | 400 | «Escribe un nombre.» |
| POST dejar, teléfono vacío / corto | 400 | «Escribe un teléfono.» |
| POST dejar, color vacío | 400 | «Di el color.» |
| POST trato, code ausente | 400 | «Elige un trasto.» |
| POST trato, no LIBRE | 409 | «Ese trasto ya no está libre.» |
| POST trato, nombre / teléfono inválido | 400 | Campos |
| POST, red | — | mark + Reintentar; no navega a ok |
| GET mesa sin JWT | 401 | redirect login |
| Login malo | 401 | copy de login |
GET /ok code 404 | 404 | «Ese trasto no está.» |
11. S-BOTTOM en flujo
| Desde | Slot | Comportamiento |
|---|---|---|
/ | Plaza | aria-current |
/ | Dejar | /dejar |
/dejar | Dejar | aria-current |
/ok/:code | Plaza | Vuelve al plano |
/ guest | Mesa | /login?next=/mesa |
/ con token | Mesa | /mesa |
[DECISIÓN] El slot Dejar no abre el sheet de llevarse; abre el form de dejar. Llevarse arranca en el plano.
05-data-model.md
05 — Modelo de datos — MANTA
1. Visión general
Dominio L1 de mantas de merendero + dejar + llevarse autenticable:
| Entidad | Tabla SQL | Propósito |
|---|---|---|
| User | users | Identidad de oficio (rol REGIDORA) |
| Session | sessions | Sesión JWT / token persistido |
| Trasto | trastos | Objeto en manta (código MNT-XXXX, título, color, estado, cover, quien deja) |
| Trato | tratos | Llevarse anónimo de cuenta sobre un trasto LIBRE (nombre, teléfono) |
Base: PostgreSQL (Neon project fancy-sun-85815074 · DATABASE_URL) · IDs: serial + texto estable (MNT-2801).
[DECISIÓN] ensureSchema es válido si el contrato de tablas se cumple; el brief de stack no exige Prisma.
Contrato de producto: trastos + tratos + JWT REGIDORA.
No bicis / requests / sesiones / ejemplares / ganchos.
2. Enums (aplicación; persistidos como TEXT + check)
Role
| Valor | Descripción |
|---|---|
REGIDORA | Regidora de la mesa; único rol autenticado v1 |
TrastoStatus
| Valor | Descripción |
|---|---|
LIBRE | En la manta; se puede llevar |
PEDIDO | Hay un trato esta mañana; ya no está libre |
ENTREGADO | Ya no está en la manta |
Un POST de dejar crea el trasto en LIBRE. [DECISIÓN]
Un POST de trato sobre LIBRE pasa el trasto a PEDIDO. [DECISIÓN D20]
Si status ≠ LIBRE → 409. [DECISIÓN]
Nines no hace PATCH de estado en v1: la mesa es lectura de mantas. [DECISIÓN]
3. Diagrama ER (texto)
users
id, email, password_hash, name, role(REGIDORA)
created_at
1 ──< sessions
sessions
id, user_id → users
expires_at, revoked_at
created_at
trastos
id
code (unique, MNT-XXXX)
title, color
status (LIBRE|PEDIDO|ENTREGADO)
cover
donor_name, donor_phone
sort_order
created_at, updated_at
1 ──< tratos
tratos
id
trasto_id → trastos
code (denorm MNT-XXXX)
name
phone
created_at
v1: una sola REGIDORA opera sobre el conjunto global.
No hay FK de vecina-usuario: la vecina no se loguea.
trastos.donor_namees quien deja (oral), no una cuenta.
tratos.namees quien se lleva.
Teléfonos no se pintan en el plano público.
4. Tablas
users
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| TEXT UNIQUE | nines@manta.plaza | |
| password_hash | TEXT | bcrypt 12 · seed $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m |
| name | TEXT | Nines Ortega |
| role | TEXT | REGIDORA |
| created_at | TIMESTAMPTZ |
sessions
| Columna | Tipo | Notas |
|---|---|---|
| id | UUID PK | sid del JWT |
| user_id | BIGINT FK | |
| expires_at | TIMESTAMPTZ | |
| revoked_at | TIMESTAMPTZ | logout |
| created_at | TIMESTAMPTZ |
trastos
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| code | TEXT UNIQUE | MNT-2801 |
| title | TEXT | Lámpara de pie · Silla de enea · Cuna plegable · Maleta rígida · o el del form |
| color | TEXT | crema / madera / crudo / verde / el del form |
| status | TEXT | LIBRE | PEDIDO | ENTREGADO |
| cover | TEXT | /assets/trastos/lampara.jpg (seed); POST nuevo puede ir sin cover |
| donor_name | TEXT | Quien deja; no público |
| donor_phone | TEXT | Recado de quien deja; no público |
| sort_order | INTEGER | 1 = primer pin del plano |
| created_at / updated_at | TIMESTAMPTZ |
tratos
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| trasto_id | BIGINT FK | |
| code | TEXT | Denorm MNT-2801 para mesa sin join extra |
| name | TEXT | Nombre de quien se lleva (Pilar Ramos) |
| phone | TEXT | Teléfono de recado |
| created_at | TIMESTAMPTZ |
Sin email, sin DNI, sin pago, sin GPS, sin precio. Dejar el trasto ≠ vender en Wallapop. [DECISIÓN]
Índices: trastos(code), trastos(status), trastos(sort_order), users(email), tratos(trasto_id), tratos(created_at DESC).
Unicidad operativa: como máximo un trato activo por trasto PEDIDO/ENTREGADO en v1. [DECISIÓN]
5. Seed
REGIDORA
nines@manta.plaza / password123 · Nines Ortega · REGIDORA
Hash bcrypt fijo: $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
Trastos
| code | title | color | status | cover | donor_name |
|---|---|---|---|---|---|
| MNT-2801 | Lámpara de pie | crema | LIBRE | /assets/trastos/lampara.jpg | Carmen Soto |
| MNT-2802 | Silla de enea | madera | PEDIDO | /assets/trastos/silla.jpg | Diego Rueda |
| MNT-2803 | Cuna plegable | crudo | LIBRE | /assets/trastos/cuna.jpg | Inma Paz |
| MNT-2804 | Maleta rígida | verde | ENTREGADO | /assets/trastos/maleta.jpg | Rafael Hoyos |
Métricas derivadas del seed: libres 2 · pedidos 1 · entregados 1.
[SUPUESTO de plaza] Títulos, colores y nombres de donantes son atrezzo. No es un merendero real.
[DECISIÓN] sort_order 1…4 = MNT-2801…2804.
Nombres de donantes seed = constructo de diseño para que la mesa no esté vacía; no son entrevistas. [DECISIÓN]
Tratos seed
| code | name | phone | Notas |
|---|---|---|---|
| MNT-2802 | Lola Méndez | 612440282 | Silla ya pedida |
| MNT-2804 | Toni Vega | 625118904 | Maleta ya entregada |
LIBRE (2801, 2803) no tienen trato. El POST de smoke de Pilar crea el de MNT-2801.
El seed idempotente restaura los 4 trastos de catálogo (estados) para que el demo sea repetible. [DECISIÓN]
Re-seed no borra MNT-2805+ salvo flag explícito de demo. [DECISIÓN]
Nombres Lola / Toni / Carmen / Diego / Inma / Rafael = constructo de seed, no campo. [DECISIÓN]
6. JSON (camelCase)
API: sortOrder, createdAt, libres, pedidos, entregados, cover, status, title, color, code, name, phone, donorName.
SQL: sort_order, created_at, donor_name, donor_phone.
GET /api/trastos
{
"metrics": { "libres": 2, "pedidos": 1, "entregados": 1 },
"trastos": [
{
"code": "MNT-2801",
"title": "Lámpara de pie",
"color": "crema",
"status": "LIBRE",
"cover": "/assets/trastos/lampara.jpg",
"sortOrder": 1
}
]
}
Lista pública: no incluye name, phone, donorName ni donorPhone. [DECISIÓN]
Métricas cuentan los tres estados. [DECISIÓN]
GET /api/trastos/:code [DECISIÓN] soporte de success
Mismo shape de item público; 404 si no existe.
POST /api/trastos (dejar)
Request:
{ "name": "Pilar Ramos", "phone": "600123123", "title": "Espejo óvalo", "color": "dorado" }
name obligatorio, trim, min 2. phone obligatorio, dígitos ≥ 9. title obligatorio, trim, min 2. color obligatorio, trim, min 3. [DECISIÓN]
Response 201:
{
"code": "MNT-2805",
"title": "Espejo óvalo",
"color": "dorado",
"status": "LIBRE",
"dejado": true
}
Algoritmo: INSERT trasto (status LIBRE, code siguiente, donor_name/phone). Transacción única. [DECISIÓN]
POST /api/tratos (llevarse)
Request:
{ "code": "MNT-2801", "name": "Pilar Ramos", "phone": "600123123" }
Response 201:
{
"code": "MNT-2801",
"title": "Lámpara de pie",
"color": "crema",
"status": "PEDIDO",
"trato": true
}
Algoritmo: SELECT FOR UPDATE por code; si no existe → 404; si status ≠ LIBRE → 409; validar name/phone; UPDATE status PEDIDO; INSERT trato. Transacción única. [DECISIÓN]
GET /api/mesa (JWT)
{
"metrics": { "libres": 2, "pedidos": 1, "entregados": 1 },
"mantas": {
"LIBRE": [ /* trastos + donorName, donorPhone */ ],
"PEDIDO": [ /* … */ ],
"ENTREGADO": [ /* … */ ]
},
"tratos": [
{
"id": 1,
"code": "MNT-2802",
"name": "Lola Méndez",
"phone": "612440282",
"status": "PEDIDO",
"createdAt": "2026-08-28T09:12:00.000Z"
}
]
}
7. Reglas de integridad
| Regla | Detalle |
|---|---|
| Unicidad de código | trastos.code UNIQUE |
| Trato solo LIBRE | Si status ≠ LIBRE → 409 |
| Dejar siempre LIBRE | POST trastos no escribe PEDIDO / ENTREGADO |
| Sin user en trato / donante | No FK a users desde trastos ni tratos |
| Mesa privada | GET /api/mesa exige JWT role REGIDORA |
| Plano público | GET /api/trastos sin auth |
| Teléfono no público | GET /api/trastos sin phone ni name ni donor |
| Una pieza | Body de trato = un code; no array |
8. Fuera del modelo v1
| Concepto | Por qué fuera |
|---|---|
| Precio / pago / SKU / puja | Dejar ≠ vender · trueque ≠ subasta |
| Email de la vecina | Minimización; S2. El recado es el teléfono |
| GPS / lat-lng / ruta | S3 · L2/L3 |
Tabla bicis / requests | Leftover PIÑÓN |
Tabla sesiones / ejemplares | Leftover BOBINA / LOMO |
| PATCH status | Mesa de lectura; no kanban |
| Carrito / líneas | H2 |
| Multi-tenant plaza | L1 compacto |
9. Naming vs leftover
| Prohibido (leftover) | Contrato MANTA |
|---|---|
bicis / requests / ganchos | trastos / tratos / mantas |
| MECANICO | REGIDORA |
pinon-api | manta-api |
| PIN-XXXX | MNT-XXXX |
| ESPERA / EN_TALLER / LISTA | LIBRE / PEDIDO / ENTREGADO |
| puerto 3027 | 3028 |
/encargo | /dejar + sheet llevarse |
06-tech-stack.md
06 — Stack técnico — MANTA
1. Resumen
| Capa | Elección | Notas |
|---|---|---|
| Frontend | Angular (standalone) + Tailwind | Puerto 4200 |
| Backend | NestJS | Puerto 3028 · prefijo /api |
| DB | Neon PostgreSQL | Project fancy-sun-85815074 · DATABASE_URL |
| Auth | JWT Bearer | Rol REGIDORA |
| Package | pnpm | Apps independientes (pnpm --filter) |
| Diseño | Paper | File 01M13JZXPYG2GXDC3HWW5K8X6K |
| Repo | /Users/cristian/orca/manta-app | GH Criscode2022/manta-app |
[COMPROBADO] Angular + NestJS + Neon + Tailwind, puerto API 3028, Paper file ID, Neon y path de app salen del encargo.
2. Por qué este stack
| Decisión | Razón | Alternativa descartada |
|---|---|---|
| Angular standalone | Coherencia serie ALS-2 daily | Next/React (rompería espejo de cases) |
| NestJS | Mismo contrato API que PIÑÓN/BOBINA | Express suelto sin módulos |
| Neon | Postgres managed; project dedicado MANTA | SQLite local (no portfolio cloud) |
| Tailwind | Tokens botanical rápidos | CSS modules sin design tokens |
| JWT | Mesa cerrada; plano abierto | Session cookie-only sin Bearer documentado |
| pnpm filter | Monorepo ligero sin npm workspaces | Turborepo pesado para L1 |
3. Puertos y health
| Servicio | Puerto | Health |
|---|---|---|
| API | 3028 | GET /api/health → { ok: true, service: "manta-api" } |
| Web | 4200 | Angular dev server |
Leftover pinon-api / puerto 3027 / bobina-api no son el producto. [DECISIÓN]
4. Estructura de repo (contrato)
manta-app/
apps/
api/ NestJS · PORT=3028
web/ Angular · 4200
package.json pnpm workspaces o filter
Proxy web → API en dev (/api → http://localhost:3028). [DECISIÓN]
5. Variables de entorno (API)
| Variable | Uso |
|---|---|
DATABASE_URL | Neon connection string (project fancy-sun-85815074) |
JWT_SECRET | Firma HS256 |
PORT | 3028 |
NODE_ENV | development / production |
No commitear secretos. .env local; ejemplo en .env.example sin credenciales reales. [DECISIÓN]
6. Auth
| Pieza | Detalle |
|---|---|
| Login | POST /api/auth/login { email, password } |
| Hash | bcrypt 12 · seed fijo del encargo |
| Token | JWT · claims sub, email, role: REGIDORA |
| Guard | Bearer en GET /api/mesa |
| Público | health, trastos, trastos/:code, POST trastos, POST tratos, login |
| Storage web | localStorage o memory + interceptor; logout limpia |
[COMPROBADO] Credenciales demo: nines@manta.plaza / password123.
7. Endpoints (contrato)
| Método | Ruta | Auth | Respuesta clave |
|---|---|---|---|
| GET | /api/health | No | manta-api |
| GET | /api/trastos | No | metrics + array 4 |
| GET | /api/trastos/:code | No | item · soporte success [DECISIÓN] |
| POST | /api/trastos | No | 201 / 400 · dejar |
| POST | /api/tratos | No | 201 / 400 / 409 · llevarse |
| POST | /api/auth/login | No | { accessToken } |
| GET | /api/mesa | JWT | mantas + tratos |
CORS: origen http://localhost:4200 en dev. [DECISIÓN]
8. Frontend — rutas y componentes
| Ruta | Componente | Guard |
|---|---|---|
/ | PlazaPage (+ LlevarseSheet) | — |
/dejar | DejarPage | — |
/ok/:code | OkPage | — |
/login | LoginPage | — |
/mesa | MesaPage | authGuard REGIDORA |
Chrome: BottomNavComponent (S-BOTTOM). Tokens Tailwind: ground, ink, card, mark, mute, geranio.
9. Assets
| Origen case | Destino app |
|---|---|
2026-08-28-manta/assets/hero.jpg | Tile Deriva / cover |
assets/trastos/*.jpg | apps/web/public/assets/trastos/ o equivalente |
Covers en DB como paths /assets/trastos/lampara.jpg etc. [DECISIÓN]
10. Calidad y toolchains
| Herramienta | Uso v1 |
|---|---|
| TypeScript | Strict en api y web |
| ESLint / Prettier | Serie daily |
| Vitest / Jest | Smoke API del slice |
| Playwright | Smoke S01–S12 del plan QA (doc 13) |
11. Anti-stack (no introducir)
| Tecnología | Por qué no |
|---|---|
| Prisma obligatorio | Brief no lo exige; ensureSchema + pg válido |
| Stripe / pago | Dejar ≠ vender |
| Firebase Auth | JWT propio REGIDORA |
| GraphQL | REST L1 |
| Socket.io / chat | ≠ PREGÓN |
| Mapbox / GPS | ≠ TROCHA · L2/L3 |
| Carrito persistente | Rompe H2 |
Leftover Nest modules bicis | ≠ PIÑÓN |
12. Criterios de aceptación técnicos
GET /api/health→service: "manta-api".- Seed idempotente: 1 REGIDORA + 4 trastos + 2 tratos seed.
- POST dejar crea trasto LIBRE y devuelve
MNT-XXXX. - POST trato sobre LIBRE → 201 PEDIDO; sobre no-LIBRE → 409.
- GET mesa sin token → 401.
- Web en 4200 consume API 3028 sin mixed-content local.
- 0 referencias de producto a
bicis, MECANICO,pinon-api, ganchos en runtime.
[COMPROBADO] Contrato alineado a docs 01, 05 y README.
07-creative-direction.md
07 — Dirección creativa — MANTA
1. Concepto
MANTA es un domingo de plaza con geranio y plátano de sombra: se entra a un tile de plaza a sangre con tres números y cuatro mantas, y se sale habiendo dejado o llevado un trasto, no una landing de «tu marketplace». El ground es hueso de muro. El musgo puntúa. El geranio, poco.
Mood elegido: botanical.
Primer instinto descartado: rastro vintage sepia. Un domingo en Usera se lee con geranio, plátano de sombra y hueso de muro, no con sepia de mercadillo «vintage».
[COMPROBADO] Mood, ground y paleta salen de docs/00-day-brief.md.
2. Territorio visual
| Eje | Sí | No |
|---|---|---|
| Superficie | Hueso #F4F1E8, ink #1A2B1C, card #FFFFFF, mark #3F6B4A | Grafito PIÑÓN, velvet BOBINA, caliza LOMO, sepia de rastro |
| Tipo | Libre Baskerville + Nunito Sans | Spectral+Sora (PIÑÓN), Cormorant+Manrope (BOBINA), Source Serif+Outfit (LOMO) |
| Foto | Plaza, manta, trasto de barrio, Usera | Sepia El Rastro, lineal IKEA, mock Wallapop, gancho de taller |
| Grid | Deriva: tile plaza ≥40 % 16/10 + 3 datos + 4 mantas | Hero 2-col + 3 cards (AP-12) · bento (PIÑÓN) · feed · tabla CESTA |
| Acento | Mark en CTA/foco/slot activo; geranio en PEDIDO/error | Naranja reflector PIÑÓN, brass de sala, cinta amarilla |
| Chrome | S-BOTTOM Plaza · Dejar · Mesa | Top taller, dock cineclub, comando archivo |
3. Paleta
| Token | Hex | Rol |
|---|---|---|
| Ground / G-BONE | #F4F1E8 | Hueso de muro. Fondo de página. |
| Ink | #1A2B1C | Musgo profundo. Texto primario. |
| Card | #FFFFFF | Ficha / manta. Superficie elevada. |
| Mark | #3F6B4A | Musgo: CTA Dejar/Llevarse, foco, wordmark. |
| Mute | #6E7A70 | Meta, labels, estado secundario, idle S-BOTTOM |
| Geranio | #C45C4A | Poco: sello PEDIDO, error, énfasis. No pinta el header. |
Jerarquía de color: el hueso carga; el mark puntúa; el geranio filetea el conflicto (pedido / error). Si el geranio pinta fondos enteros, deja de ser flor y se vuelve «brand rastro». El texto sobre hueso es ink; nunca mute como párrafo largo. Ink sobre hueso debe pasar contraste WCAG 2.2 AA. [DECISIÓN]
Candidatos de mood descartados: rastro vintage sepia (primer instinto), arid/dust, rusted, pastoral.
4. Tipografía
| Uso | Familia | Tamaños de referencia |
|---|---|---|
| Wordmark | Libre Baskerville 600 | 24–28 desktop · 22 mobile |
| Titular de plaza / mesa | Libre Baskerville 600 | 32–44 |
| Código MNT-XXXX | Libre Baskerville 600 | 28–36 |
| Título de trasto | Libre Baskerville 600 | 22–28 |
| Cuerpo / disclaimers | Nunito Sans 400 | 16–17 / 26–28 lh |
| UI, S-BOTTOM, form, lista | Nunito Sans 400/500/600 | 14 / 16 |
| Meta (color, status) | Nunito Sans 500 | 12–13, tracking 0.08em, mute o ink |
Prohibido: Libre Baskerville por debajo de 18px (se rompe). Nunito Sans en el wordmark de plaza (se vuelve SaaS). Geranio como color de texto de párrafo largo (contraste).
Fuentes vetadas de la serie reciente cuando el brief fija otras: Spectral / Sora (PIÑÓN), Cormorant / Manrope (BOBINA), Source Serif 4 / Outfit (LOMO), DM Serif Display / IBM Plex Sans, Newsreader / Figtree, Fraunces / Atkinson. Libre Baskerville + Nunito Sans sí entran: el brief los fija. [COMPROBADO]
5. Fotografía
| Asset | Debe | No debe |
|---|---|---|
| hero.jpg | Plaza de barrio: manta, luz de domingo, Usera, hueso y sombra | Sepia El Rastro, stock de flea market vintage, gancho de taller |
| lampara.jpg | Lámpara de pie crema; LIBRE se lee en UI | Anuncio Wallapop con precio |
| silla.jpg | Silla de enea; PEDIDO se lee en UI | Thumbnail de e-commerce |
| cuna.jpg | Cuna plegable crudo; merendero | Banner IKEA |
| maleta.jpg | Maleta rígida verde; ENTREGADO se lee en UI | Foto de subasta |
Alt: título + color, no «imagen1». Ver doc 09.
[COMPROBADO] Los cuatro covers y el hero existen en assets/.
6. Registro R-CL
Clásico: merendero de plaza, wordmark Baskerville, mantas, bottom tabs de oficio. No es un dashboard de seguros. No es un kiosk de horas. No es una mesa de datos de archivo. No es sepia de rastro «cool».
La innovación de terna está en H-MAP Deriva + S-BOTTOM + F-MKT de una pieza, no en un look «vintage market». [DECISIÓN]
7. Anti-moods
| Mood | Por qué no |
|---|---|
| Rastro vintage sepia | Primer instinto; es El Rastro de postal |
| Industrial / grafito | Fue PIÑÓN |
| Candlelit / velvet | Fue BOBINA |
| Mineral / caliza | Fue LOMO |
| Signage / cinta amarilla | Fue ONDA |
| Ice institucional | Fue RAMAL |
| Chapel amatista | Fue MATIZ |
| Dusk cartográfico | Fue DERIVA (paseo, no merendero) |
8. Densidad (AP-21)
En el recorte Deriva: eslogan + tile de plaza dominante + 3 datos (libres / pedidos / entregados) + 4 mantas con título, color y estado visibles sin hover. Headline huérfano + foto = card hueca. [COMPROBADO] CRON §5.8 / D-P1-09 foto-led.
Tile de plaza ≥40 % del recorte 16/10. Los 3 datos y las 4 mantas no tapan el oficio de la foto: legibles, no sticker. [DECISIÓN]
9. Motion
| Gesto | Tratamiento |
|---|---|
| Entrada plano | Fade corto 120–160ms; tile estático (no Ken Burns agresivo) |
| Hover ficha desktop | Ring mark 2px; sin lift excesivo |
| S-BOTTOM activo | Mark en label; idle mute |
| Sheet llevarse | Slide-up 160ms; reduced = instant |
| Reduced motion | 0ms; tile sin parallax |
10. Voice visual ↔ copy
El mood botanical refuerza el microcopy: manta de plaza, no anuncio. Si la UI parece Wallapop (precio, corazón, «subir anuncio») o IKEA (carrito, amarillo) o El Rastro de postal (sepia, filigrana), el copy irrenunciable pierde fuerza. [DECISIÓN]
08-design-system.md
08 — Sistema de diseño — MANTA
1. Tokens
| Token | Valor | Uso |
|---|---|---|
--ground | #F4F1E8 | Fondo de página (hueso de muro) |
--ink | #1A2B1C | Texto primario, títulos |
--card | #FFFFFF | Tarjeta de manta, form, mesa |
--mark | #3F6B4A | CTA, foco, S-BOTTOM activo |
--mute | #6E7A70 | Meta, idle |
--geranio | #C45C4A | Sello PEDIDO, error, poco |
--font-display | Libre Baskerville | Titulares |
--font-sans | Nunito Sans | UI |
--target | 44×44 min | Toques |
Tailwind: bg-ground, text-ink, bg-card, bg-mark, text-mute, text-geranio, font-display.
La tarjeta vive sobre --card; el ground es hueso alrededor. [DECISIÓN]
2. Contraste (obligatorio)
| Par | Uso | Nota |
|---|---|---|
Ink #1A2B1C sobre Hueso #F4F1E8 | Cuerpo y títulos | Debe pasar WCAG 2.2 AA |
Ink sobre Card #FFFFFF | Texto en tarjeta | Verificar AA |
| Mark sobre Hueso | CTA fill + texto cream/hueso invertido en botón | No sustituye ink en párrafo |
| Mute sobre Hueso | Meta corta; no cuerpo | Evitar párrafos mute |
| Geranio sobre Hueso | Sello / error corto | No cuerpo |
[DECISIÓN] Geranio nunca como color de párrafo. Mute nunca como único color de disclaimer largo.
CTA mark: texto #F4F1E8 o #FFFFFF sobre #3F6B4A — verificar AA en implementación. [HIPÓTESIS operativa]
3. Escala de tipo
| Rol | Size / leading |
|---|---|
| Display plaza | clamp(2.2rem, 5vw, 3.6rem) / 0.95 |
| H1 mesa / success | 2.5rem / 1 |
| H2 título trasto | 28px / 32px |
| Cuerpo | 16–17 / 26 |
| Meta | 12–13 / 16, tracking 0.08em |
| S-BOTTOM | 12–14 / 16, Nunito Sans 500 |
4. Componentes
Ficha de manta (plano)
Cover recorte + título Baskerville · color · status. Tap LIBRE abre sheet llevarse. Orden por sort_order.
Tile Deriva (UI-01)
Imagen de plaza a sangre ≥40 % del frame 16/10; gradient hueso→transparente para legibilidad del plano; wordmark + eslogan + 3 datos (libres / pedidos / entregados). Overlay de 4 mantas como plano, no GIS.
Dato (métrica de manta)
Número ink grande + label mute («libres», «pedidos», «entregados»). Tres en fila desktop; wrap en 390. No es un sparkline ni una tabla H-DATA.
Form dejar (UI-02)
Nombre, teléfono, qué es, color, disclaimer, submit mark.
Sheet llevarse (UI-03)
Código + título en solo lectura, nombre, teléfono, disclaimer, submit mark. Si no LIBRE: geranio + «Ese trasto ya no está libre.»
Success (UI-04)
Código Baskerville enorme + bloque card con título y color + 4 oposiciones en ink/mute.
Fila de mesa REGIDORA (UI-06)
Grupos LIBRE / PEDIDO / ENTREGADO. Fila: código · título · color · status · donor. Tratos debajo: name · phone · code · hora. Sin acciones PATCH en v1.
Login (UI-05)
Wordmark + dos inputs + CTA mark. Ayuda mute con demo.
Bottom nav (S-BOTTOM)
Tres slots: Plaza · Dejar · Mesa. Activo: mark. Idle: mute. Fondo card/ground. Targets ≥44px. Safe-area inset.
Skeleton (UI-09)
animate-pulse bg-card o mute/20. aria-busy.
Error (UI-08)
Titular display + cuerpo ink/mute + Reintentar mark. 409 usa geranio en sello, no en párrafo.
Empty (UI-07)
Titular Baskerville + mute. Sin CTA de Wallapop ni de IKEA.
Sello LIBRE / PEDIDO / ENTREGADO
Texto «Libre» / «Pedido» / «Entregado» + mark o geranio o mute. Nunca solo el color. Poco: un sello por ficha.
5. Layouts
| Superficie | Grid |
|---|---|
| Plaza 1440 | Tile plaza full-bleed 16/10; 3 datos en fila; 4 fichas 2×2 sobre/bajo el plano; S-BOTTOM |
| Plaza 390 | Tile + 3 datos wrap + stack de 4; S-BOTTOM fijo inferior |
| Dejar / Ok / login | Columna max-w-lg |
| Mesa REGIDORA | Grupos + tratos; stacked < lg |
| Sheet llevarse | Bottom sheet max-w-lg; full-bleed 390 |
Max page 1440px. Padding 20 / 40 / 48. Padding-bottom ≥ 72px donde hay S-BOTTOM.
6. Estados de control
| Estado | Tratamiento |
|---|---|
| Default | Card + ink |
| Hover | Ring mark 2px |
| Focus visible | Outline mark 2px offset 2 |
| Active / pressed | Mark fill breve |
| Disabled | Opacity 0.45 · no hit · aria-disabled |
| Pending | disabled + aria-busy |
| Error | Borde geranio + mensaje |
| LIBRE seleccionada | Ring mark |
| No LIBRE | Sello; CTA disabled |
7. Iconografía
S-BOTTOM: pictogramas simples (plaza / manta / mesa). Stroke 1.5–2px. No icon packs «carrito», «corazón Wallapop», «bici», «gancho». [DECISIÓN]
8. Elevación y bordes
| Superficie | Tratamiento |
|---|---|
| Card sobre hueso | Sombra suave 0 1px 2px ink/8; borde 1px mute/20 |
| S-BOTTOM | Barra card; filete mute 1px superior; no material neón |
| Sheet | Overlay ink/40 + card; no modal centrado de SaaS |
| Modal extra | No en v1 Must |
9. Mapa a Paper UI
| UI | Componentes clave |
|---|---|
| UI-01 / 11 | Tile plaza + 3 datos + 4 mantas + S-BOTTOM |
| UI-02 / 12 | Form dejar |
| UI-03 | Sheet llevarse |
| UI-04 | Success |
| UI-05 | Login |
| UI-06 | Mesa mantas |
| UI-07 | Empty |
| UI-08 | Error / 409 |
| UI-09 | Loading |
| UI-10 | Tokens |
[COMPROBADO] Inventario en 00-paper-reference.md.
09-content-guide.md
09 — Guía de contenido — MANTA
1. Voz
MANTA habla como merendero de plaza, no como anuncio ni como lineal.
| Eje | Sí | No |
|---|---|---|
| Tono | Seco, breve, de barrio | Corporativo Wallapop, hype de subasta |
| Persona | «Dejamos el trasto» / tuteo de plaza | «Publica tu anuncio» / «reserva tu artículo» |
| Ritmo | Frases cortas. Una idea por línea en disclaimers | Párrafos legales de marketplace |
| Humor | Seco, poco | Memes, jerga de rastro vintage |
[DECISIÓN] Tuteo en UI. Nines en mesa puede verse en usted solo en docs, no en labels.
2. Microcopy irrenunciable
Presente en plaza (pie o banner), dejar, llevarse, success y pie de mesa:
| Oposición | Copy canónico |
|---|---|
| Dejar vs vender | Dejar el trasto ≠ vender en Wallapop. |
| Trueque vs subasta | Trueque ≠ subasta. |
| Llevarse vs reservar | Llevarse ≠ reservar IKEA. |
| Barrio vs marketplace | MANTA no es Wallapop. |
No se parafrasean hasta diluirlas. Pueden acortarse en UI estrecha manteniendo ≠. [DECISIÓN]
3. Glosario UI
| Concepto | Label canónico | Evitar |
|---|---|---|
| Home | Plaza | Inicio, Taller, Cartelera, Mapa, Catálogo |
| Item | Trasto / Manta | SKU, anuncio, gancho, bici |
| Flujo dejar | Dejar | Vender, publicar, subir anuncio |
| Flujo mercado | Llevarse | Reservar, añadir al carrito, pujar |
| CTA dejar | Dejar el trasto | Publicar, Vender |
| CTA llevarse | Llevarse | Reservar, Comprar, Hold |
| Success | Dejado / Trato | Confirmación de compra, Anuncio activo |
| Staff | Mesa | Backoffice, Admin, Kanban |
| Estado | Libre / Pedido / Entregado | Disponible / Agotado (retail), En ruta (TROCHA), En taller (PIÑÓN) |
| Persona auth | Regidora | Mecánica, Programadora, Admin |
| Error 409 | Ya no está libre | Agotado, Sold, Reserved |
4. Pantalla a pantalla
Plaza /
| Slot | Copy |
|---|---|
| Wordmark | MANTA |
| Eslogan | La manta, no el anuncio. |
| Dato 1 | {n} libres |
| Dato 2 | {n} pedidos |
| Dato 3 | {n} entregados |
| CTA bottom | Dejar |
| Empty | Aún no hay mantas. |
| Error | La red no responde. · Reintentar |
Dejar /dejar (UI-02)
| Slot | Copy |
|---|---|
| Título | Dejar el trasto |
| Label nombre | Tu nombre |
| Label teléfono | Teléfono |
| Label título | Qué es |
| Label color | Color |
| Submit | Dejar el trasto |
| Disclaimer | No es un anuncio. No hay puja. Llevarse ≠ reservar IKEA. |
| Error nombre | Escribe un nombre. |
| Error teléfono | Escribe un teléfono. |
| Error título | Escribe qué dejas. |
| Error color | Di el color. |
Llevarse sheet (UI-03)
| Slot | Copy |
|---|---|
| Título | Llevarse |
| Meta | {title} · {color} · {code} |
| Label nombre | Tu nombre |
| Label teléfono | Teléfono |
| Submit | Llevarse |
| Disabled / 409 | Ese trasto ya no está libre. |
| Disclaimer | Una pieza. No es una reserva. MANTA no es Wallapop. |
Success /ok/:code
| Slot | Copy |
|---|---|
| Titular (dejar) | Dejado. |
| Titular (trato) | Trato. |
| Código | {code} |
| Cuerpo dejar | {title} · {color}. Libre en la manta. |
| Cuerpo trato | {title} · {color}. Pedido esta mañana. |
| Oposiciones | Las cuatro líneas irrenunciables |
| Volver | Volver a la plaza |
Login /login
| Slot | Copy |
|---|---|
| Título | Mesa |
| Ayuda | Solo regidora. |
| Demo | nines@manta.plaza |
| Error | Email o contraseña no valen. |
Mesa /mesa
| Slot | Copy |
|---|---|
| Título | Mesa |
| Grupos | Libre · Pedido · Entregado |
| Empty tratos | No hay tratos. |
| Salir | Salir |
| Pie | Dejar el trasto ≠ vender en Wallapop. |
5. Alt text de imágenes
| Asset | Alt (modelo) |
|---|---|
| hero | Plaza de barrio con mantas, luz de domingo, Usera |
| lampara | Lámpara de pie crema en la manta |
| silla | Silla de enea, ya con pedido |
| cuna | Cuna plegable crudo en la manta |
| maleta | Maleta rígida verde, ya entregada |
Evitar «imagen1», «item.jpg», copy de anuncio con precio. [DECISIÓN]
6. Trastos seed (atrezzo)
Lámpara / silla / cuna / maleta son catálogo demo. En UI no se afirma «merendero municipal de Usera». Los blurbs pueden recordar dejar ≠ vender. [SUPUESTO de plaza]
7. Tono de error
| Caso | Copy |
|---|---|
| Red | La red no responde. |
| 404 | Ese trasto no está. |
| 409 | Ese trasto ya no está libre. |
| 400 título | Escribe qué dejas. |
| 401 mesa | Entra como regidora. |
Sin culpa al usuario. Sin jerga HTTP en UI.
8. Anti-copy (vetado)
| Vetado | Por qué |
|---|---|
| Vender / anuncio / precio / SKU / corazón | Wallapop |
| Pujar / subasta / timer / puja | Subasta |
| Reservar / carrito / hold / click & collect | IKEA |
| En ruta / GPS / parada | TROCHA |
| Gancho / bici / encargo / mecánica | PIÑÓN |
| Pedir butaca / sesión / taquilla | BOBINA |
| Recibido / En curso / Cerrado | PREGÓN kanban |
| Compromiso / despensa | CESTA |
| «El 80% de vecinas…» | Estadística inventada |
| Añadir otra pieza | Rompe H2 |
9. Criterios de aceptación de contenido
- Las cuatro oposiciones aparecen al menos en success y en una superficie de plaza o dejar/llevarse.
- Ningún CTA dice Vender / Reservar / Pujar / Añadir al carrito.
- LIBRE se etiqueta «Libre», no «Disponible» retail.
- Códigos se muestran como
MNT-XXXXen versales. - Docs y UI no inventan KPIs numéricos de Usera como hecho.
10-accessibility.md
10 — Accesibilidad — MANTA
1. Objetivo
Cumplir WCAG 2.2 AA en el vertical slice L1. Ground claro (hueso): el par ink sobre hueso es el contrato de legibilidad. Amparo (71) es persona de diseño que fuerza contraste, tamaño y targets; no tiene login. [COMPROBADO] requisito del encargo · [DECISIÓN] persona Amparo en docs.
2. Contraste
| Par | Ratio objetivo | Uso |
|---|---|---|
#1A2B1C sobre #F4F1E8 | ≥ 4.5:1 (texto) / ≥ 3:1 (UI grande) | Cuerpo, títulos |
#1A2B1C sobre #FFFFFF | ≥ 4.5:1 | Texto en card |
#3F6B4A sobre #F4F1E8 | ≥ 3:1 para UI; texto de párrafo no | Foco, iconos |
#F4F1E8 o #FFFFFF sobre #3F6B4A | ≥ 4.5:1 en CTA | Label del botón |
#6E7A70 sobre #F4F1E8 | Verificar; limitar a meta corta | Labels |
#C45C4A sobre #F4F1E8 | Sello / error corto | Geranio; no cuerpo |
[DECISIÓN] Si mute falla AA en párrafo, se asciende a ink. Geranio no escribe disclaimers. Mark no escribe disclaimers largos.
Verificación: contraste en tokens al build de UI; no se afirman ratios inventados sin medir en implementación. [HIPÓTESIS operativa] ink/hueso pasa; se valida en QA (doc 13).
3. Tipografía y lectura
| Regla | Aplicación |
|---|---|
| Cuerpo ≥ 16px | Nunito Sans 16–17 |
| Display no < 18px | Libre Baskerville solo en titulares |
| Line-height ≥ 1.5 en cuerpo | 26–28 lh |
| Zoom 200% | Layout no rompe S-BOTTOM ni form |
| Sin justificado forzado | Alineación start |
4. Targets y pointer
| Elemento | Mínimo |
|---|---|
| Slots S-BOTTOM | 44×44 CSS px |
| CTA Dejar el trasto / Llevarse | ≥ 44 px alto |
| Ficha de manta | Hit area completa ≥ 44 alto |
| Inputs | ≥ 44 alto |
| Cerrar sheet | ≥ 44 |
Spacing entre slots del bottom ≥ 8px. [DECISIÓN]
5. Teclado y foco
| Superficie | Comportamiento |
|---|---|
| Plaza | Tab por S-BOTTOM → fichas LIBRE → Dejar |
| Sheet llevarse | Nombre → teléfono → submit; Esc cierra |
| Form dejar | Nombre → teléfono → qué es → color → submit |
| Login | Email → password → entrar |
| Mesa | Grupos legibles; salir alcanzable |
| Focus visible | Outline mark 2px offset 2 |
| Skip link | «Saltar a la plaza» en / si el tile decorativo es largo |
Sin keyboard traps. Sheet: foco inicial en nombre; retorno al pin al cerrar. [DECISIÓN]
6. Semántica y nombres
| UI | Rol / nombre |
|---|---|
| S-BOTTOM | navigation · aria-label «MANTA» |
| Slot activo | aria-current="page" |
| 3 datos | list o group «Mantas» · cada dato con texto «{n} libres» no solo el número |
| Fichas trasto | article «{title} {color}» + status en texto |
| Sheet | dialog · aria-modal · labelledby título |
| Form | label asociado; errores con aria-live="polite" |
| Loading | aria-busy="true" en región |
| Success código | Texto real, no solo imagen |
| 409 | aria-live="assertive" |
7. Imágenes y tile
| Caso | Tratamiento |
|---|---|
| Tile Deriva | alt descriptivo corto o alt="" si puro decorativo y el plano encima lleva el oficio |
| Covers trasto | Alt «{title} {color}» |
| Iconos S-BOTTOM | aria-hidden si hay label texto visible |
[DECISIÓN] Preferir tile con alt útil en cover UX; en producto, si el overlay ya nombra MANTA y las mantas, evitar alt redundante largo.
8. Motion
| Preferencia | Comportamiento |
|---|---|
prefers-reduced-motion: reduce | Transiciones 0ms; sin parallax del tile; sheet instant |
| Default | 120–160ms ease-out |
9. Estados y color
LIBRE / PEDIDO / ENTREGADO / error nunca se comunican solo con color: texto + sello. Mark y geranio refuerzan, no sustituyen. [DECISIÓN]
10. Auth y a11y
- Login solo REGIDORA; Amparo no necesita cuenta para leer la plaza ni dejar/llevarse.
- Mensajes de error de login claros, sin enumerar si el email existe (seguridad + claridad).
/mesaredirige a login con foco en email.
11. Mobile 390
- S-BOTTOM fijo no tapa el CTA final: padding-bottom del contenido ≥ altura bar + safe-area.
- Sheet llevarse por encima del bottom; submit visible.
- Formularios:
autocompletename on; teltel; passwordcurrent-password. - Viewport meta; sin zoom bloqueado. [DECISIÓN]
- UI-11 plaza y UI-12 dejar cubren el recorte 390. No carousel.
12. Criterios de aceptación a11y
- Ink sobre hueso usado en cuerpo; mute limitado a meta.
- Targets S-BOTTOM y CTA ≥ 44×44.
- Focus visible mark en todos los interactivos.
- Status y métricas con texto, no solo color o número huérfano.
- Reduced motion respetado.
- Form con labels y errores anunciables.
- Ningún toast único sin pantalla como único success (hay
/ok/:code). - Sheet llevarse es
dialogalcanzable con teclado.
13. Fuera de v1 (L2/L3, no deuda)
- Modo tipográfico «letra grande» persistente para Amparo.
- App nativa con VoiceOver de plaza física.
- ATAG de CMS (no hay CMS).
11-privacy-security.md
11 — Privacidad y seguridad — MANTA
1. Principios
| Principio | Aplicación v1 |
|---|---|
| Minimización | Dejar = nombre + teléfono + título + color; trato = nombre + teléfono + code; sin email, DNI, GPS, precio |
| Separación público / oficio | Plano y POST públicos; mesa JWT |
| Sin cuenta de vecina | Pilar y Amparo no se registran |
| Transparencia de copy | Success dice que no es venta ni reserva |
| Secretos fuera del repo | DATABASE_URL, JWT_SECRET en env |
[DECISIÓN] No se inventa un aviso legal largo de marketplace; hay disclaimer de producto y minimización real.
2. Datos tratados
| Dato | Dónde | Base operativa (modelo) | Retención v1 |
|---|---|---|---|
| Nombre de quien deja | trastos.donor_name | Prestación del merendero (apuntar quién deja) | Mientras el seed/demo viva; sin política de mercado afirmada |
| Teléfono de quien deja | trastos.donor_phone | Recado | Igual |
| Nombre de trato | tratos.name | Quién se lleva | Igual |
| Teléfono de trato | tratos.phone | Recado cuando está PEDIDO | Igual |
| Título / color | trastos | Oficio de la manta | Igual |
| Email REGIDORA | users.email | Cuenta de oficio | Cuenta demo |
| Password hash | users.password_hash | Auth | bcrypt 12 |
| JWT sid | sessions | Sesión de mesa | Expiración + revoke |
No se tratan: pago, tarjeta, geolocalización, ID de dispositivo publicitario, mensajes de chat, DNI, IBAN, precio.
[SUPUESTO] El merendero demo opera en España; el slice no implementa un RGPD completo de empresa real.
3. Superficies públicas vs privadas
| Superficie | Público | Privado |
|---|---|---|
GET /api/trastos | Sí · sin nombres ni teléfonos | — |
GET /api/trastos/:code | Sí · sin teléfono | — |
| POST trastos / tratos | Sí · crea fila | — |
GET /api/mesa | No · 401 | Sí · donor + tratos con name + phone |
| Plaza UI | Sin listar quién dejó | — |
| Mesa UI | — | Lista dejas y tratos |
[DECISIÓN] Enumerar teléfonos en el plano rompería privacidad de plaza; solo Nines ve recados.
4. AuthN / AuthZ
| Control | Detalle |
|---|---|
| Password | bcrypt cost 12 · hash seed canónico del encargo |
| JWT | HS256 · secret env · role claim |
| Guard mesa | role === REGIDORA |
| Login rate | No es deuda del L1; demo sin brute-force engine |
| Logout | Revoke session + clear client token |
| HTTPS | Obligatorio en deploy; localhost HTTP en dev |
Credenciales demo en docs: nines@manta.plaza / password123. No reutilizar en producción real. [COMPROBADO] demo · [DECISIÓN] rotar fuera del case.
5. Amenazas y mitigaciones L1
| Amenaza | Mitigación |
|---|---|
| POST spam dejar/trato | Validación teléfono + título; L2/L3 rate-limit (no es hueco del slice) |
| Carrera de dos tratos sobre el mismo LIBRE | SELECT FOR UPDATE + 409 al segundo |
| Enumeración de teléfonos | No en API pública |
| JWT robado | Expiración corta + logout; HTTPS en prod |
| IDOR mesa | Guard JWT; sin IDs de trato públicos |
| XSS | Angular escaping; no innerHTML de name/phone |
| SQLi | Parámetros prepared / query builder |
| Leftover MECANICO / ADMIN | Un solo rol REGIDORA |
6. Contenido de teléfono y nombre
phone es recado, no tracking. Se muestra a Nines en mesa. Formato: dígitos, min 9. [DECISIÓN]
No se pide dirección, salud ni datos de terceros sensibles en el form.
name es texto libre corto (min 2, max 80).
7. Cookies y tracking
v1 no incluye analytics de terceros ni banners de cookies de ads. North star es modelo (doc 12). [DECISIÓN]
Token JWT puede vivir en localStorage (XSS risk aceptado en demo) o memory; documentar en handoff.
8. Logs
| Qué sí | Qué no |
|---|---|
| Errores de API sin PII | Passwords, JWT completos |
| code de trasto en logs de dejar/trato | Teléfono completo en logs públicos |
9. Criterios de aceptación
- GET mesa sin Bearer → 401.
- GET trastos no incluye
name,phone,donorNamenidonorPhone. - POST trastos/tratos no exige auth ni pago ni GPS.
- Password solo como hash bcrypt.
.envno versionado con secretos reales.- Copy de success no implica contrato de venta ni de reserva.
- Segundo POST trato sobre el mismo code → 409.
10. Fuera de v1 (L2/L3 / org real, no deuda)
DPO, ROPA formal, exportaciones ARCO automatizadas, SSO, 2FA, WAF, geolocalización. Roadmap L2/L3 si la plaza deja de ser demo (pagos, GPS).
12-analytics.md
12 — Analytics y métricas — MANTA
1. Norte
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | % de visitas a plaza que resuelven «¿sigue ahí la lámpara?» sin un WhatsApp | Oficio de manta: la vecina ve el estado (LIBRE / PEDIDO / ENTREGADO) sin recado |
[COMPROBADO] North star alineada a H1 del day brief.
[DECISIÓN] En v1 es modelo: no hay instrumentación obligatoria ni dashboard. No se afirman porcentajes medidos inventados.
2. Por qué esta north star
| Alternativa descartada | Por qué no |
|---|---|
Pageviews de / | Vanidad; no mide manta |
| Ingresos / GMV | Dejar ≠ vender; no hay e-commerce |
| % de anuncios publicados | MANTA no es Wallapop |
| % de pujas cerradas | Trueque ≠ subasta |
| % de holds IKEA | Llevarse ≠ reservar |
| % de bicis LISTA sin WhatsApp | Eso es PIÑÓN |
| % de noches con butaca | Eso es BOBINA |
El WhatsApp de «¿sigue ahí la lámpara?» es el recado que el plano y la mesa pretenden absorber. [SUPUESTO] operativo de diseño, no dato de campo.
3. Métricas de soporte (modelo)
| Métrica | Definición | Hipótesis |
|---|---|---|
| Activación vecina | 1.er POST /api/trastos o /api/tratos exitoso | H2 |
| Tasa plaza → dejar | / → /dejar | H1 |
| Tasa plaza → trato | / → 201 tratos | H2 |
| Tasa 409 | POST tratos 409 / intentos | Integridad de una pieza |
| Mix de estados | Conteos LIBRE / PEDIDO / ENTREGADO | H1 |
| Integridad auth | 401 en mesa sin token | Seguridad |
| Salud | 5xx rate API | Ops |
4. Eventos (contrato si se instrumenta en un L2/L3)
| Evento | Props | PII |
|---|---|---|
plaza_view | metrics snapshot (conteos) | No |
dejar_submit | — | No nombre, no teléfono |
dejar_success | code | No |
trato_submit | code | No |
trato_success | code | No |
trato_conflict | http:409 | No |
login_success | role | No |
mesa_view | — | No |
[DECISIÓN] Nunca enviar name ni phone a analytics.
Instrumentar eventos no es un hueco del L1: el slice cierra sin tracker. [DECISIÓN]
5. Cálculo north star (modelo)
visitas_plaza = sesiones en /
resuelto_sin_whatsapp =
(no medible en v1: no hay canal WhatsApp en producto)
proxy de diseño = visitas a / o /mesa que cubren el estado
frente a recados paralelos (cualitativo)
[DECISIÓN] v1 no persiste un flag whatsapp_asked. El north star queda como modelo de oficio, no como SQL fingido.
Timezone: Europe/Madrid. [DECISIÓN]
6. Integridad de expectativa (cualitativa)
Señales a vigilar en demo / soporte (no KPIs inventados):
- «¿Lo vendo en Wallapop?»
- «¿Puedo pujar?»
- «¿Lo reservo como en IKEA?»
- «¿Dónde está el carrito?»
- «¿Dónde está el GPS?»
- «¿Esto es el taller de bicis?»
Mitigación: microcopy irrenunciable (doc 09). [HIPÓTESIS H2]
7. Qué no medir en v1
| Vetado | Por qué |
|---|---|
| Heatmaps de terceros sin decisión | Privacidad |
| Funnel de pago | No hay pago |
| DAU de Wallapop | No hay anuncio |
| Estadísticas de Usera inventadas | Ética de verdad |
| Tracking GPS | S3 · L2/L3 |
8. Criterios de aceptación
- Docs y UI no muestran un % inventado como hecho.
- North star documentada y alineada a H1.
- Si hay eventos en un L2/L3, sin PII de tratos.
- Health, 401 mesa y 409 trato son checks de integridad, no vanidad.
9. Relación con seed
Seed tiene 2 LIBRE + 1 PEDIDO + 1 ENTREGADO. Un guión con POST trato sobre MNT-2801 y POST dejar MNT-2805 es el ejemplo narrativo de activación; no es un dato de mercado. [SUPUESTO de demo]
13-qa-test-plan.md
13 — Plan de QA — MANTA
1. Alcance
Smoke y regresión del vertical slice L1: plano, dejar, llevarse, 409, success, login, mesa, empty/error/loading, mobile 390, contraste ink/hueso.
No incluye campo real de Usera ni load test de marketplace.
2. Entornos
| Entorno | URL | Notas |
|---|---|---|
| API local | http://localhost:3028 | Neon fancy-sun-85815074 |
| Web local | http://localhost:4200 | Proxy /api |
| Credenciales | nines@manta.plaza / password123 | Solo demo |
3. Smoke crítico (Must pasar)
| ID | Caso | Pasos | Esperado |
|---|---|---|---|
| S01 | Health | GET /api/health | ok · service: "manta-api" |
| S02 | Plano | GET /api/trastos · abrir / | 4 trastos · 3 métricas · Deriva visible |
| S03 | Métricas seed | Leer datos | 2 libres · 1 pedido · 1 entregado |
| S04 | 409 | POST /api/tratos { code: "MNT-2802", name, phone } | 409 |
| S05 | Llevarse | Sheet lámpara LIBRE + Pilar + teléfono · submit | 201 · /ok/MNT-2801 · status PEDIDO |
| S06 | Copy success | Leer /ok/:code | 4 oposiciones visibles |
| S07 | Dejar | /dejar · título + Pilar + teléfono + color · submit | 201 · /ok/MNT-2805 · LIBRE |
| S08 | Login | /login Nines | JWT · /mesa |
| S09 | Mesa auth | GET /api/mesa con token | mantas + tratos |
| S10 | Mesa 401 | GET /api/mesa sin token | 401 |
| S11 | Mobile | / y /dejar @390 | S-BOTTOM · 4 mantas · targets |
| S12 | Seed | Tras re-seed | 2 LIBRE · 1 PEDIDO · 1 ENTREGADO |
4. Regresión funcional
| ID | Área | Check |
|---|---|---|
| R01 | POST dejar crea LIBRE | Nuevo trasto status LIBRE |
| R02 | POST trato pasa a PEDIDO | MNT-2801 deja de ser LIBRE |
| R03 | Trato ligado | Mesa muestra nombre + teléfono del POST |
| R04 | Nombre vacío dejar | 400 · no navega a ok |
| R05 | Teléfono corto | 400 |
| R06 | Code inventado | /ok/MNT-9999 · 404 UI |
| R07 | Guard ruta | /mesa sin token → login ?next= |
| R08 | Logout | Token limpio · mesa 401 |
| R09 | S-BOTTOM | Plaza / Dejar / Mesa navegables |
| R10 | Público sin teléfonos | JSON trastos sin phone / name / donor |
| R11 | Leftover | 0 pinon-api / bicis / MECANICO / ganchos en UI |
| R12 | 409 ENTREGADO | POST trato MNT-2804 → 409 |
| R13 | Segunda pieza | UI no permite carrito ni array de codes |
5. Accesibilidad (muestra)
| ID | Check |
|---|---|
| A01 | Ink sobre hueso en cuerpo (inspección / contraste) |
| A02 | Focus visible mark en tab order |
| A03 | S-BOTTOM slots ≥ 44×44 |
| A04 | Status con texto, no solo color |
| A05 | prefers-reduced-motion sin parallax |
| A06 | Labels en form dejar, sheet y login |
| A07 | aria-busy en loading plaza |
| A08 | Sheet como dialog |
6. Contenido
| ID | Check |
|---|---|
| C01 | Ningún CTA «Vender» / «Reservar» / «Pujar» / «Añadir al carrito» |
| C02 | Eslogan en plaza |
| C03 | LIBRE = «Libre» no «Disponible» retail |
| C04 | Códigos MNT-XXXX |
| C05 | Cuatro oposiciones en success |
7. Visual / Paper
| ID | Check |
|---|---|
| V01 | Tile plaza a sangre + 3 datos + 4 mantas (no hero 2-col, no bento, no feed) |
| V02 | Mood botanical (no sepia rastro, no grafito taller) |
| V03 | Covers seed cargan (lampara/silla/cuna/maleta) |
| V04 | Mesa = mantas por estado (no kanban de columnas) |
| V05 | S-BOTTOM no top de taller |
8. API negativa
| Caso | HTTP |
|---|---|
| Login malo | 401 |
| Dejar sin nombre | 400 |
| Dejar sin título | 400 |
| Trato sin code | 400 |
| Trato sobre PEDIDO | 409 |
| Trato sobre ENTREGADO | 409 |
| Trato code 404 | 404 |
| Mesa sin auth | 401 |
9. Datos de prueba
| Actor | Dato |
|---|---|
| Vecina | Pilar Ramos · 600123123 |
| Trasto happy LIBRE | MNT-2801 Lámpara crema |
| Trasto 409 | MNT-2802 Silla PEDIDO |
| Trasto ENTREGADO | MNT-2804 |
| Dejar smoke | Espejo óvalo · dorado |
| REGIDORA | nines@manta.plaza |
Tras smoke: re-seed para restaurar las 4 de catálogo. [DECISIÓN]
10. Criterio de salida
Smoke S01–S12 en verde. Sin P0 (health mal, dejar/trato rotos, 409 ausente, mesa abierta sin auth, copy Wallapop ausente en success).
P1 visual puede quedar anotado; no reabre el alcance L1.
11. Fuera de alcance QA v1
Penetration test, auditoría RGPD formal, GPS, pasarela de pago, compatibilidad IE, métricas reales de north star instrumentadas. Eso es L2/L3 u org real, no un agujero de este slice.
14-dev-handoff.md
14 — Handoff a desarrollo — MANTA
1. Contrato vivo
| Artefacto | Path |
|---|---|
| Brief | docs/00-day-brief.md |
| Paper ref | docs/00-paper-reference.md |
| Producto | docs/01-project-definition.md |
| IA / rutas | docs/03-information-architecture.md |
| Flujos | docs/04-user-flows.md |
| Datos | docs/05-data-model.md |
| Stack | docs/06-tech-stack.md |
| DS / tokens | docs/08-design-system.md |
| Copy | docs/09-content-guide.md |
| Build | docs/20-implementation.md |
| App | /Users/cristian/orca/manta-app |
| GH | Criscode2022/manta-app |
| Paper | 01M13JZXPYG2GXDC3HWW5K8X6K |
| API | :3028 · manta-api |
| Neon | fancy-sun-85815074 |
Si código y docs divergen, alinear ambos; no silenciar leftover PIÑÓN como producto. [DECISIÓN]
2. Definition of Done (DoD) L1
| # | Criterio |
|---|---|
| 1 | Rutas / /dejar /ok/:code /login /mesa |
| 2 | Home = Deriva H-MAP (tile plaza + 3 datos + 4 mantas), no H-BENTO ni H-FEED ni H-DATA ni hero 2-col |
| 3 | Chrome S-BOTTOM Plaza · Dejar · Mesa |
| 4 | F-MKT: llevarse una pieza LIBRE (sheet UI-03); 409 si no LIBRE |
| 5 | POST dejar público; success con 4 oposiciones |
| 6 | JWT REGIDORA; mesa 401 sin token |
| 7 | Seed 4 trastos · 2 LIBRE · 1 PEDIDO · 1 ENTREGADO |
| 8 | Health manta-api · puerto 3028 |
| 9 | Tokens botanical + Libre Baskerville / Nunito Sans |
| 10 | Empty / error / loading / 409 |
| 11 | Mobile 390 usable (plaza + dejar) |
| 12 | 0 dominio bicis / MECANICO / pinon-api / ganchos |
El DoD cubre todo el slice. No queda producto in-scope como «siguiente sprint». [DECISIÓN]
3. Mapa Paper → Angular
| UI | Ruta | Componente |
|---|---|---|
| UI-01 / 11 | / | PlazaPage |
| UI-02 / 12 | /dejar | DejarPage |
| UI-03 | / sheet | LlevarseSheet |
| UI-04 | /ok/:code | OkPage |
| UI-05 | /login | LoginPage |
| UI-06 | /mesa | MesaPage |
| UI-07 / 08 / 09 | estados | mismos components |
| UI-10 | theme | Tailwind |
4. API checklist
| Método | Ruta | Auth |
|---|---|---|
| GET | /api/health | No |
| GET | /api/trastos | No |
| GET | /api/trastos/:code | No |
| POST | /api/trastos | No · dejar |
| POST | /api/tratos | No · llevarse · 409 |
| POST | /api/auth/login | No |
| GET | /api/mesa | JWT REGIDORA |
Body dejar: { name: string, phone: string, title: string, color: string }.
Body trato: { code: string, name: string, phone: string }.
Ver algoritmos en doc 05 / 20. [DECISIÓN]
5. Seed y credenciales
| Item | Valor |
|---|---|
nines@manta.plaza | |
| Password | password123 |
| Hash | $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m |
| Codes | MNT-2801…2804 |
| Covers | /assets/trastos/{lampara,silla,cuna,maleta}.jpg |
6. Anti-patrones de implementación
| No hacer | Hacer |
|---|---|
| Puerto 3027 / health pinon-api | 3028 / manta-api |
| Tabla bicis / requests / ganchos | trastos / tratos / mantas |
| Top S-TOP | S-BOTTOM |
| Bento H-BENTO | Plano Deriva H-MAP |
| Kanban mesa | Mantas por estado |
| Pago / Stripe / anuncio | POST nombre + teléfono |
| GPS / Mapbox | Fuera · L2/L3 |
| Hero 2-col marketing | Deriva foto-led |
| Carrito / array de codes | Una pieza · 409 |
/encargo leftover | /dejar + sheet |
7. Assets
Copiar desde case:
assets/trastos/lampara.jpgassets/trastos/silla.jpgassets/trastos/cuna.jpgassets/trastos/maleta.jpgassets/hero.jpg(tile Deriva / cover)
[COMPROBADO] existen en el case.
8. QA mínimo antes de merge
Ejecutar smoke S01–S12 (doc 13). Verificar copy irrenunciable en /ok/:code. Verificar 409 sobre MNT-2802.
9. Open questions (no reabren L1)
| Pregunta | Default ya decidido |
|---|---|
¿Prisma o pg + ensureSchema? | ensureSchema válido |
| ¿localStorage vs memory token? | localStorage demo OK |
| ¿Teléfono maxlength? | 15 dígitos |
| ¿Cover del POST nuevo? | Vacío o placeholder; seed sí tiene foto |
| ¿PATCH status? | No en v1 |
¿Ruta /llevarse/:code? | No · sheet sobre / |
10. Contacto de diseño
Paper file + docs 07–09. No reinventar sepia de rastro ni grafito de taller. Mood botanical. Ground #F4F1E8. Mark #3F6B4A. Geranio #C45C4A poco.
15-roadmap.md
15 — Roadmap — MANTA
1. Horizonte
| Fase | Nombre | Intención |
|---|---|---|
| L1 | Slice actual | Plano + dejar + llevarse + mesa JWT · cerrado en esta iteración |
| L2/L3 | Nice-to-have de otro producto | Solo pagos y GPS, y solo con brief nuevo |
[DECISIÓN] El L1 no deja producto ni código in-scope como «próximos pasos». Este roadmap no es un cajón de deuda. Empty, error, loading, 409, mobile, auth, seed, copy y API están en el slice de hoy.
2. Hecho en L1 (Must · cerrado)
| Pieza | Estado |
|---|---|
| H-MAP Deriva 4 mantas + 3 métricas | Must · cerrado |
| Dejar el trasto sin cuenta | Must · cerrado |
| F-MKT llevarse una pieza + 409 | Must · cerrado |
| Success + 4 oposiciones | Must · cerrado |
| Login REGIDORA | Must · cerrado |
| Mesa de mantas LIBRE / PEDIDO / ENTREGADO | Must · cerrado |
| Empty / error / loading / 390 | Must · cerrado |
| Docs 00–20 + README + executive | Must · cerrado |
| Paper 12 UX + 12 UI (inventario) | Must (ref) · cerrado |
Contrato manta-app · API :3028 · health manta-api | Must · cerrado |
Nada de la tabla se reabre como backlog de «el código ya vendrá». El case L1 cierra en una iteración. [DECISIÓN]
3. L2/L3 only (nice-to-have · otro brief)
| ID | Idea | Por qué L2/L3 | Riesgo |
|---|---|---|---|
| L2-01 | Pagos / escrow / precio | Rompe S3; huele a Wallapop (dejar ≠ vender) | Marketplace disfrazado |
| L3-01 | GPS del trasto / aviso de llegada | Rompe S3; huele a TROCHA (el trasto se deja en plaza, no se reparte) | Flota disfrazada |
Estas dos ideas no completan MANTA. Completarían otro producto. [DECISIÓN]
4. Anti-roadmap (no disfrazar)
| Pedido típico | Respuesta |
|---|---|
| «Pon un anuncio / precio / corazón» | No · Dejar el trasto ≠ vender en Wallapop |
| «Pon GPS» | No en L1 · L3-01 con brief nuevo |
| «Pon pagos» | No en L1 · L2-01 con brief nuevo |
| «Pon subasta» | No · Trueque ≠ subasta |
| «Pon carrito / reserva IKEA» | No · Llevarse ≠ reservar IKEA |
| «Pon búsqueda tipo LOMO» | No · rompe terna H-MAP |
| «Pon kanban» | No · ≠ PREGÓN |
| «Pon bento de ganchos» | No · N−1 ya fue PIÑÓN |
| «Empty / loading / 409 los dejamos para después» | No · están en el L1 de hoy |
| «El código es el próximo paso del case» | No · el contrato L1 está cerrado; no se lista como roadmap de producto |
5. Dependencias del slice cerrado
| Dependencia | Nota |
|---|---|
Neon fancy-sun-85815074 | L1 (DATABASE_URL) |
Paper file 01M13JZXPYG2GXDC3HWW5K8X6K | Diseño; inventario en 00 |
manta-app · GH Criscode2022/manta-app | Contrato de build (doc 20) |
6. Criterios para abrir un L2/L3
- Smoke L1 en verde (doc 13).
- Copy irrenunciable intacto.
- El brief L2/L3 nombra pagos o GPS sin reabrir plano, F-MKT de una pieza ni mesa.
- North star sigue siendo modelo o se instrumenta sin PII.
7. Cierre
L1 está completo en una iteración. El roadmap es un muro contra el anuncio y el GPS, no una lista de lo que «faltó». [DECISIÓN]
16-interaction-specs.md
16 — Especificación de interacción — MANTA
1. Convenciones
| Token | Valor |
|---|---|
| Duración corta | 120–160ms |
| Easing | ease-out |
| Reduced motion | 0ms |
| Target | ≥44×44 |
| Pending | control disabled + aria-busy |
Loading, empty y error viven con los gestos (UI-07 / UI-08 / UI-09). [DECISIÓN]
2. Plaza plano (UI-01) + mobile (UI-11) · H-MAP Deriva
| Gesto | Resultado |
|---|---|
| Primera carga | Loading (UI-09): skeleton tile + 3 datos + 4 fichas card; aria-busy |
| 200 con 4 | Tile de plaza a sangre + 3 datos + 4 mantas. Título, color, estado |
| 200 con 0 | UI-07 empty «Aún no hay mantas.» |
| Error 5xx / red | UI-08 + Reintentar (repite GET trastos) |
| Tap manta LIBRE | Abre sheet llevarse (UI-03) |
| Tap manta PEDIDO / ENTREGADO | Sello; no sheet de envío; copy 409 si se fuerza |
| Tap Dejar (S-BOTTOM o CTA) | /dejar |
| Tap Mesa (S-BOTTOM) | /login o /mesa si hay token |
| Hover ficha desktop | Ring 2px mark. Sin lift excesivo |
AC: título, color y estado visibles sin hover. Tile plaza ≥40 % del recorte 16/10 (AP-21 / D-P1-09). Tres datos con texto («2 libres»), no solo cifra. Cero botones Vender / Reservar / Pujar.
El aviso «MANTA no es Wallapop» es texto, no un CTA de tienda. [DECISIÓN]
390: mismas 4 mantas apiladas. No carousel. S-BOTTOM visible. [DECISIÓN]
3. Dejar (UI-02) + mobile dejar (UI-12)
| Gesto | Resultado |
|---|---|
| Carga | Form vacío; submit disabled si faltan campos |
| Nombre / teléfono / qué es / color vacío + submit | Error de campo · no POST |
| Submit válido | POST /api/trastos · pending en botón |
| 201 | /ok/:code con dejado: true |
| 400 | mark/geranio + mensaje de campo |
| Red | seal + Reintentar; no navega a ok |
| Tap Plaza (S-BOTTOM) | / |
AC: no email, no DNI, no precio, no pago. Dejar el trasto ≠ vender en Wallapop visible.
4. Llevarse (UI-03) · F-MKT
| Gesto | Resultado |
|---|---|
| Abrir desde LIBRE | Sheet dialog · código + título solo lectura |
| Esc / cerrar | Vuelve al plano; foco al pin |
| Submit válido | POST /api/tratos · pending |
| 201 | /ok/:code con trato: true · trasto PEDIDO |
| 409 | «Ese trasto ya no está libre.» · no navega a ok |
| 400 | Campos |
| Red | Reintentar en sheet |
AC: una sola pieza. Cero carrito. Cero segunda línea. Cero hold IKEA.
5. Success (UI-04)
| Gesto | Resultado |
|---|---|
| Entrada desde dejar 201 | «Dejado.» + código MNT-XXXX + 4 oposiciones |
| Entrada desde trato 201 | «Trato.» + código + 4 oposiciones |
| Tap Volver | / |
| Deep link directo | GET /api/trastos/:code; 404 → «Ese trasto no está.» |
AC: las cuatro oposiciones están. No QR. No «anuncio activo». No mapa GPS.
6. Login (UI-05)
| Gesto | Resultado |
|---|---|
| Submit válido | POST login · guarda JWT · /mesa o next |
| 401 | «Email o contraseña no valen.» |
Guest en /mesa | Redirect /login?next=/mesa |
AC: sin signup. Ayuda demo mute.
7. Mesa REGIDORA (UI-06)
| Gesto | Resultado |
|---|---|
| Primera carga | Loading skeletons grupos + tratos |
| 200 | Mantas LIBRE / PEDIDO / ENTREGADO + tratos (name, phone, code, hora) |
| Empty tratos | «No hay tratos.» |
| 401 | Redirect login |
| Salir | Limpia token → / |
| Tap fila | Sin /mesa/:code en v1; lectura |
AC: no columnas Recibido / En curso. No PATCH estado. No split lista|ficha. No mapa. ENTREGADO sí se lista.
8. S-BOTTOM · chrome
| Gesto | Resultado |
|---|---|
| Tap Plaza | / |
| Tap Dejar | /dejar |
| Tap Mesa | Auth → /mesa; guest → login |
| Activo | Mark + aria-current |
| Idle | Mute |
AC: tres slots. No hamburger. No top de taller. Targets ≥44px. Fijo en 390. Safe-area.
9. Empty / Error / Loading (UI-07 / UI-08 / UI-09)
| Estado | UI |
|---|---|
| Loading | Pulse card; aria-busy |
| Empty plaza | Display + mute + sin CTA de Wallapop |
| Empty mesa tratos | Mute |
| Error red | Titular + Reintentar mark |
| 409 | Geranio sello + copy «ya no está libre» |
10. Motion
| Gesto | Default | Reduced |
|---|---|---|
| Aparición plano | Fade 140ms | Instant |
| Hover ring | 120ms | Instant |
| Sheet | Slide-up 160ms | Instant |
| Tile plaza | Estático | Estático |
Sin Ken Burns agresivo sobre Deriva. [DECISIÓN]
11. Guión de interacción demo
/loading → tile + 3 datos + 4 mantas.- Leer MNT-2801 LIBRE / MNT-2802 PEDIDO.
- Tap lámpara → sheet Pilar → pending → success Trato.
- Tap silla → 409.
- Dejar → form → success Dejado.
- S-BOTTOM Mesa → login → mesa con MNT-2801 PEDIDO.
- 390: S-BOTTOM no tapa CTA; sheet por encima; scroll con padding.
12. Criterios de aceptación de interacción
- F-MKT no abre carrito ni segunda pieza.
- POST trato no-LIBRE no navega a ok (409).
- Pending no doble-envía.
- S-BOTTOM siempre alcanzable en 390.
- Focus visible en todo el recorrido teclado.
- Sheet es dialog; Esc cierra.
17-prototype-map.md
17 — Mapa de prototipo — MANTA
1. Fuentes
| Fuente | ID / path |
|---|---|
| Paper | https://app.paper.design/file/01M13JZXPYG2GXDC3HWW5K8X6K |
| File ID | 01M13JZXPYG2GXDC3HWW5K8X6K |
| UX-count | 12 |
| UI-count | 12 |
| App | /Users/cristian/orca/manta-app |
| Case assets | 2026-08-28-manta/assets/ |
[COMPROBADO] conteos y file ID en docs/00-paper-reference.md.
[SUPUESTO] densificación de artboards = gate Paper del mismo día (placeholder en 00).
2. UX process → docs
| UX | Nombre | Doc espejo |
|---|---|---|
| UX-00 | Cover | README · executive · 07 |
| UX-01 | Stakeholders | 02 §3 |
| UX-02 | Personas | 02 §4 |
| UX-03 | JTBD | 02 §5 |
| UX-04 | Stories | 02 §6 |
| UX-05 | Journey | 02 §7 · 04 |
| UX-06 | Blueprint | 02 §8 |
| UX-07 | Site map | 03 |
| UX-08 | Flujos | 04 |
| UX-09 | Datos+permisos | 05 · 01 §5 · 11 |
| UX-10 | Métricas | 12 |
| UX-11 | Research | 02 |
3. UI producto → rutas / componentes
| UI | Nombre | Ruta | Componente Angular |
|---|---|---|---|
| UI-01 | Plaza Deriva | / | PlazaPage |
| UI-02 | Dejar | /dejar | DejarPage |
| UI-03 | Llevarse | / sheet | LlevarseSheet |
| UI-04 | Success | /ok/:code | OkPage |
| UI-05 | Login | /login | LoginPage |
| UI-06 | Mesa | /mesa | MesaPage |
| UI-07 | Empty | mismas rutas | estados |
| UI-08 | Error | mismas rutas | estados · 409 |
| UI-09 | Loading | mismas rutas | estados |
| UI-10 | Tokens | — (theme) | Tailwind config / styles |
| UI-11 | Mobile plaza | / @390 | PlazaPage |
| UI-12 | Mobile dejar | /dejar @390 | DejarPage |
4. Flujo prototipo clickable (orden demo)
UI-01 Plaza Deriva
├─→ UI-03 Llevarse (Lámpara LIBRE)
│ └─→ UI-04 Success (Trato)
├─→ UI-02 Dejar
│ └─→ UI-04 Success (Dejado)
├─→ UI-11 (mismo /, viewport 390)
├─→ UI-12 (mismo /dejar, viewport 390)
└─→ S-BOTTOM Mesa → UI-05 Login → UI-06 Mesa
Estados: UI-07 empty · UI-08 error/409 · UI-09 loading se prueban desconectando API, seed vacío o POST sobre PEDIDO.
Tokens: UI-10.
5. Datos de prototipo = seed
| Code | Trasto | Color | Estado | Cover asset |
|---|---|---|---|---|
| MNT-2801 | Lámpara de pie | crema | LIBRE | trastos/lampara.jpg |
| MNT-2802 | Silla de enea | madera | PEDIDO | trastos/silla.jpg |
| MNT-2803 | Cuna plegable | crudo | LIBRE | trastos/cuna.jpg |
| MNT-2804 | Maleta rígida | verde | ENTREGADO | trastos/maleta.jpg |
Hotspots Paper deben usar estos códigos en labels si muestran URL. [DECISIÓN]
POST trato demo → MNT-2801 (Pilar Ramos).
POST dejar demo → MNT-2805 (Pilar Ramos, Espejo óvalo, dorado).
6. Breakpoints de artboard
| Artboard | Ancho ref |
|---|---|
| Desktop plaza / dejar / mesa | ~1280–1440 |
| Mobile plaza (UI-11) | 390 |
| Mobile dejar (UI-12) | 390 |
| Tokens (UI-10) | según Paper |
7. Terna visible en prototipo
| Código | Evidencia en UI |
|---|---|
| R-CL | Merendero clásico (S-BOTTOM, mantas, wordmark Baskerville) |
| S-BOTTOM | Plaza · Dejar · Mesa en UI-01 / 11 / 02 / 06 |
| H-MAP | UI-01 Deriva: tile plaza + 3 datos + 4 mantas |
| F-MKT | UI-03 una pieza, sin carrito |
8. Gaps conscientes
| Gap | Notas |
|---|---|
| Pagos / GPS | L2/L3 · no son huecos del prototipo L1 |
| PATCH de estado | Fuera · mesa de lectura |
| Analytics en prototipo | Modelo 12 |
| Densificación Paper | Gate del mismo día · 00 placeholder |
Ningún gap es producto in-scope aplazado. [DECISIÓN]
9. Criterios de aceptación del mapa
- Cada UI-01…12 tiene fila en esta tabla.
- Cada ruta Must tiene artboard.
- No hay artboard de
/encargo,/carrito,/subasta, GPS o anuncio. - Mobile 390 cubierto (UI-11, UI-12).
- UX-00…11 cubiertos.
18-completeness-audit.md
18 — Auditoría de cierre — MANTA
1. Alcance L1 · una iteración
El vertical slice cierra en esta iteración. No hay segunda pasada de producto in-scope. Empty, error, loading, 409, mobile, auth, seed, copy y contrato de código forman parte del cierre, no de un roadmap.
| Pieza | Estado |
|---|---|
| Docs 01–20 + README + executive | OK (este set) |
00-day-brief | Intactos (fuente de verdad) |
00-paper-reference | OK · UX-count 12 · UI-count 12 · placeholder hasta gate |
| Paper 12 UX + 12 UI | Inventario en 00 · file 01M13JZXPYG2GXDC3HWW5K8X6K |
App path /Users/cristian/orca/manta-app | OK · GH Criscode2022/manta-app |
API :3028 · health manta-api | Contrato |
| Código trastos + tratos + JWT REGIDORA | Contrato doc 20 |
| Cierre sin deuda del L1 | OK · roadmap solo L2/L3 pagos / GPS |
2. Terna y diversidad
| Check | Evidencia |
|---|---|
| R-CL · S-BOTTOM · H-MAP · F-MKT | Brief + 01 + 07 |
| 0 códigos = PIÑÓN | PIÑÓN era R-HY · S-TOP · H-BENTO · F-CMP |
| ≥2 vs BOBINA / LOMO | Bottom/Map/Mkt vs dock/feed/story y cmd/data/lead |
| S-BOTTOM, H-MAP, F-MKT no en últimos 5 | Brief |
Ground G-BONE #F4F1E8 | 00 + 07 + Tailwind |
| No leftover PIÑÓN | 0 bicis / MECANICO / pinon-api / ganchos en el contrato |
| Mood botanical ≠ sepia rastro | 07 |
| H-MAP ≠ DERIVA | F-MKT de un objeto, no F-MAP de ruta |
| L1 no L2 consecutivo | Brief |
3. Copy irrenunciable
Presente en plaza, dejar, llevarse, success, pie de mesa. Ver doc 09.
- Dejar el trasto ≠ vender en Wallapop
- Trueque ≠ subasta
- Llevarse ≠ reservar IKEA
- MANTA no es Wallapop
4. Anti-patrones vigilados
| AP | Mitigación |
|---|---|
| AP-12 hero 2-col | H-MAP Deriva tile + 3 datos + 4 mantas |
| AP-21 card hueca | Título/color/estado visibles |
| Leftover como estado | Contrato MANTA; no se anota PIÑÓN como producto vivo |
| Entrevistas inventadas | 02 etiquetado |
| bicis/MECANICO/pinon-api/ganchos | 0 en dominio; 05 + 20 |
| H-BENTO / S-TOP / F-CMP | Plano + S-BOTTOM + F-MKT |
| H-FEED / S-DOCK | Plano + S-BOTTOM |
| H-DATA / S-CMD | No mesa de datos ni comando |
| Carrito F-MKT | Una pieza · 409 |
| Kanban | Mesa de mantas |
| Pagos / GPS en L1 | S3 · solo L2/L3 |
| Estadísticas inventadas | Etiquetas [HIPÓTESIS]/[SUPUESTO] |
| Roadmap con deuda L1 | Doc 15 solo pagos / GPS |
5. Seed
4 trastos · 2 LIBRE · 1 PEDIDO · 1 ENTREGADO · Nines REGIDORA · Pilar sin cuenta · Amparo fuera de login.
| code | title | color | status |
|---|---|---|---|
| MNT-2801 | Lámpara de pie | crema | LIBRE |
| MNT-2802 | Silla de enea | madera | PEDIDO |
| MNT-2803 | Cuna plegable | crudo | LIBRE |
| MNT-2804 | Maleta rígida | verde | ENTREGADO |
Métricas: libres 2 · pedidos 1 · entregados 1.
6. Assets
| Archivo | Presente |
|---|---|
assets/hero.jpg | [COMPROBADO] case |
assets/trastos/lampara.jpg | [COMPROBADO] |
assets/trastos/silla.jpg | [COMPROBADO] |
assets/trastos/cuna.jpg | [COMPROBADO] |
assets/trastos/maleta.jpg | [COMPROBADO] |
7. Huecos conscientes (fuera · L2/L3)
Pagos, GPS. Nada más se etiqueta como «faltó del L1».
Login Amparo, email transaccional, instrumentación analytics, PATCH de estado, ficha /mesa/:code, ruta /llevarse no son deuda: son decisiones de corte (S2, S3, D13, D14).
Densificación Paper = gate del mismo día, no backlog de producto. [DECISIÓN]
8. Checklist archivos suite
| Archivo | Estado |
|---|---|
| README.md | OK |
| presentation/executive-summary.md | OK |
| docs/00-day-brief.md | Preexistente |
| docs/00-paper-reference.md | OK |
| docs/01 … docs/20 | OK |
9. Veredicto
Slice L1 cerrado en una iteración. El contrato de manta-app (docs 14 y 20) no se lista como próximo paso de producto: es el mismo alcance, ya definido. Paper file 01M13JZXPYG2GXDC3HWW5K8X6K. Si el repo diverge (leftover PIÑÓN), gana docs 05 + 20 tras alinear ambos.
Cierre: Must cubierto. Roadmap = L2/L3 pagos y GPS únicamente.
10. SCORE ALS-2 (cierre de suite docs)
| Eje | Score | Nota |
|---|---|---|
| Diversidad | 5 | Merendero nuevo; L1 no L2; no taller/bento/top |
| Docs | 4 | Suite 00–20 + brief + presentation |
| Paper craft UI | 5 | 12 UI tokens/plaza Deriva/dejar/llevar/success/login/mesa/empty/error+loading + 2 mobile |
| Paper UX process | 5 | 12 UX |
| Media | 5 | Hero plaza + 4 trastos (lámpara/silla/cuna/maleta) |
| Canvas org | 5 | Bandas §1–§3 origen 0,0 |
| Código E2E | 5 | GET trastos + POST tratos 201/409 + JWT REGIDORA; ng build; thumb no negro |
| Paridad app | 4 | S-BOTTOM + H-MAP Deriva + tokens G-BONE |
| Unicidad estructura | 5 | R-CL · S-BOTTOM · H-MAP · F-MKT |
| Cierre admin | 5 | Registry+Excel+GitHub+Paper gate+portfolio UI-01 |
| Media | ~4.8 |
Gate: node scripts/check-paper-reference.mjs 2026-08-28-manta → OK UX=12 UI=12.
Smoke [COMPROBADO]: health manta-api; GET /api/trastos 4; POST /api/tratos 201 MNT-2801 luego 409; login nines@manta.plaza; ng build 1.58MB; Playwright 1440×900 avgRGB~(189,182,172) dark% 0. API/web apagados (D-P1-06).
19-backlog-completo.md
19 — Backlog completo — MANTA
1. Leyenda
| Estado | Significado |
|---|---|
| Done | Definido y aceptado en la suite ALS L1 (esta iteración) |
| Won’t L1 | Fuera; L2/L3 pagos / GPS u otro case |
No hay columna «Must (después)». El slice no deja producto in-scope a medias. [DECISIÓN]
2. Épica A — Plaza H-MAP Deriva
| ID | Ítem | Estado |
|---|---|---|
| A1 | Deriva tile plaza a sangre + 3 métricas + 4 mantas | Done |
| A2 | Ficha: título, color, status | Done |
| A3 | Tap LIBRE → sheet llevarse | Done |
| A4 | Empty / loading / error | Done |
| A5 | Mobile 390 + assets covers | Done |
| A6 | Búsqueda comando /buscar | Won’t L1 (≠ LOMO) |
| A7 | Bento de ganchos | Won’t L1 (≠ PIÑÓN) |
| A8 | Feed de noches | Won’t L1 (≠ BOBINA) |
3. Épica B — Dejar
| ID | Ítem | Estado |
|---|---|---|
| B1 | /dejar · name + phone + título + color | Done |
| B2 | POST público 201 / 400 | Done |
| B3 | Crea trasto LIBRE | Done |
| B4 | /ok/:code + 4 oposiciones | Done |
| B5 | Precio / anuncio / Wallapop | Won’t L1 (≠ vender) |
| B6 | Signup vecina | Won’t L1 (S2) |
4. Épica C — Llevarse F-MKT
| ID | Ítem | Estado |
|---|---|---|
| C1 | Sheet una pieza sobre / | Done |
| C2 | POST /api/tratos → PEDIDO | Done |
| C3 | 409 si no LIBRE | Done |
| C4 | Copy llevarse ≠ reservar IKEA | Done |
| C5 | Carrito / multi-pieza / hold | Won’t L1 (H2) |
| C6 | Subasta / puja | Won’t L1 |
5. Épica D — Mesa REGIDORA
| ID | Ítem | Estado |
|---|---|---|
| D1 | Login JWT Nines | Done |
| D2 | /mesa LIBRE / PEDIDO / ENTREGADO | Done |
| D3 | GET mesa 401 sin token | Done |
| D4 | Logout | Done |
| D5 | Tratos + donors con name + phone | Done |
| D6 | Kanban columnas | Won’t L1 (≠ PREGÓN) |
| D7 | PATCH estado / ficha pedido | Won’t L1 (mesa de lectura) |
6. Épica E — Chrome S-BOTTOM
| ID | Ítem | Estado |
|---|---|---|
| E1 | Bottom Plaza · Dejar · Mesa | Done |
| E2 | aria-current + targets 44 | Done |
| E3 | Mesa guest → login | Done |
| E4 | Top PIÑÓN / dock BOBINA / comando LOMO | Won’t L1 |
7. Épica F — Design system & a11y
| ID | Ítem | Estado |
|---|---|---|
| F1 | Tokens hueso/ink/card/mark/mute/geranio | Done |
| F2 | Libre Baskerville + Nunito Sans | Done |
| F3 | Contraste ink/hueso AA | Done |
| F4 | Reduced motion | Done |
| F5 | Modo letra grande Amparo | Won’t L1 (corte a11y, no deuda) |
8. Épica G — Plataforma
| ID | Ítem | Estado |
|---|---|---|
| G1 | Nest :3028 · health manta-api | Done |
| G2 | Neon fancy-sun-85815074 schema+seed | Done |
| G3 | Angular rutas + guard | Done |
| G4 | pnpm apps independientes | Done |
| G5 | GPS / Mapbox | Won’t L1 · L2/L3 |
| G6 | Pagos / Stripe | Won’t L1 · L2/L3 |
9. Épica H — Documentación & diseño
| ID | Ítem | Estado |
|---|---|---|
| H1 | docs 00–20 + README + executive | Done |
| H2 | Paper UX 12 + UI 12 inventario | Done |
| H3 | File 01M13JZXPYG2GXDC3HWW5K8X6K | Done (ref · placeholder hasta gate) |
10. Orden de build (mismo alcance, no roadmap)
- Schema + seed + health
- GET trastos + PlazaPage Deriva
- DejarPage + POST trastos
- LlevarseSheet + POST tratos + 409
- OkPage copy
- Auth + MesaPage
- S-BOTTOM + 390 + empty/error/loading
- Pulido tokens / a11y / smoke S01–S12
Ese orden no es «próximos pasos de producto»: es la receta del mismo L1 ya cerrado. [DECISIÓN]
11. Contadores
| Tipo | Count (aprox) |
|---|---|
| Done L1 | ~40 |
| Won’t L1 / L2/L3 | pagos, GPS + analogías vetadas |
| Docs Done | Suite completa |
No se inventan story points ni velocidades de equipo. [DECISIÓN]
20-implementation.md
20 — Implementación — MANTA
1. Resumen ejecutivo técnico
| Campo | Valor |
|---|---|
| App path | /Users/cristian/orca/manta-app |
| GH | Criscode2022/manta-app |
| API | NestJS · puerto 3028 · prefijo /api |
| Web | Angular standalone · puerto 4200 |
| Package | apps independientes (pnpm --filter) |
| DB | Neon PostgreSQL · project fancy-sun-85815074 (DATABASE_URL) |
| Tablas | users, trastos, tratos, sessions |
| Auth | JWT Bearer · role REGIDORA (/mesa); plano y POST públicos |
| Dominio | User, Trasto, Trato |
| Fecha | 2026-08-28 |
| Health | manta-api (leftover pinon-api → sustituir) |
Este documento es la especificación de build del L1 ya cerrado. No es un roadmap: si el repo diverge, gana el contrato de docs 05 + este archivo tras actualizar ambos.
Contrato: trastos + tratos + JWT REGIDORA. Puerto 3028. Health manta-api.
[COMPROBADO] Path, puerto, Neon, GH y Paper salen del encargo.
El repo no debe contener leftover PIÑÓN (bicis, MECANICO, pinon-api, ganchos, puerto 3027) ni leftover BOBINA (sesiones, PROGRAMADOR). Eso no es MANTA.
2. Cómo arrancar
cd /Users/cristian/orca/manta-app
# instalar dependencias por app (pnpm --filter; no npm workspaces)
# apps/api/.env
# DATABASE_URL=<neon fancy-sun-85815074>
# JWT_SECRET=<secret>
# PORT=3028
# schema + seed
# api → http://localhost:3028
# web → http://localhost:4200
Credenciales
| Rol | Password | |
|---|---|---|
| REGIDORA | nines@manta.plaza | password123 |
Hash seed: $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
Vecina / vecina mayor: sin cuenta. Pilar deja en /dejar o se lleva desde /. Amparo no entra por login.
3. Schema
Al boot o vía migrate:
CREATE TABLEdeusers,sessions,trastos,tratos(doc 05).- Índices:
trastos(code),trastos(status),trastos(sort_order),users(email),tratos(trasto_id),tratos(created_at DESC). - Seed idempotente:
- upsert REGIDORA
nines@manta.plaza(hash bcrypt canónico) - upsert
trastosporcode(MNT-2801…MNT-2804) restaurando status, color, cover, donor - upsert 2
tratosseed (Lola Méndez / Toni Vega)
- upsert REGIDORA
- Dominio: solo trastos + tratos + users. [DECISIÓN]
Upsert de trastos por code sí restaura status de catálogo para que el guión sea repetible. [DECISIÓN]
POST de dejar sí genera código nuevo (MNT-2805+). POST de trato reutiliza el code del trasto.
Tablas (recordatorio)
| Tabla | Contenido |
|---|---|
users | REGIDORA Nines Ortega |
trastos | 4 mantas (+ las del POST dejar) |
tratos | Llevarse (seed PEDIDO/ENTREGADO + POST) |
sessions | sid + expires_at |
DROP leftover bicis, requests, sesiones, ejemplares si existen en el mismo Neon. [DECISIÓN] El project es de MANTA.
Seed SQL (modelo)
| code | title | color | status | cover |
|---|---|---|---|---|
| MNT-2801 | Lámpara de pie | crema | LIBRE | /assets/trastos/lampara.jpg |
| MNT-2802 | Silla de enea | madera | PEDIDO | /assets/trastos/silla.jpg |
| MNT-2803 | Cuna plegable | crudo | LIBRE | /assets/trastos/cuna.jpg |
| MNT-2804 | Maleta rígida | verde | ENTREGADO | /assets/trastos/maleta.jpg |
[SUPUESTO de plaza] Objetos demo.
4. Módulos API a implementar
Auth
POST /api/auth/login- Valida email/password; compara bcrypt; emite JWT con
sub, email, role. - Guard JWT +
role === REGIDORAprotege/mesa. - Públicos: health, trastos, trastos/:code, POST trastos, POST tratos, login.
Oficio
| Método | Ruta | Auth | Notas |
|---|---|---|---|
| GET | /api/health | No | { ok: true, service: "manta-api" } |
| GET | /api/trastos | No | metrics + sort_order asc sin name/phone/donor |
| GET | /api/trastos/:code | No | item público |
| POST | /api/trastos | No | INSERT trasto LIBRE; 400 si title/name/phone/color inválidos |
| POST | /api/tratos | No | UPDATE PEDIDO + INSERT trato; 409 si no LIBRE |
| GET | /api/mesa | JWT | mantas agrupadas + tratos con PII de mostrador |
Health (referencia de implementación)
{ "ok": true, "service": "manta-api" }
Cualquier leftover "pinon-api" o "bobina-api" falla el DoD.
POST trastos (dejar) — algoritmo
1. Validar body.title (trim, length >= 2) else 400
2. Validar body.name (trim, length >= 2) else 400
3. Validar body.phone (dígitos >= 9) else 400
4. Validar body.color (trim, length >= 3) else 400
5. code = siguiente MNT-XXXX (max existente + 1, piso MNT-2805)
6. INSERT trastos (code, title, color, status=LIBRE, donor_name, donor_phone)
7. 201 { code, title, color, status: LIBRE, dejado: true }
Transacción única. [DECISIÓN]
POST tratos (llevarse) — algoritmo
1. Validar body.code presente else 400
2. Validar body.name (trim, length >= 2) else 400
3. Validar body.phone (dígitos >= 9) else 400
4. SELECT FOR UPDATE trastos WHERE code = body.code
5. Si no hay fila → 404
6. Si status ≠ LIBRE → 409 { error: "NOT_LIBRE", code }
7. UPDATE trastos SET status = PEDIDO
8. INSERT tratos (trasto_id, code, name, phone)
9. 201 { code, title, color, status: PEDIDO, trato: true }
Transacción única. El segundo concurrente recibe 409. [DECISIÓN]
GET trastos — shape
{
"metrics": { "libres": 2, "pedidos": 1, "entregados": 1 },
"trastos": [ { "code", "title", "color", "status", "cover", "sortOrder" } ]
}
Métricas: count status LIBRE / PEDIDO / ENTREGADO. [DECISIÓN]
GET mesa — shape
{
"metrics": { "libres": n, "pedidos": n, "entregados": n },
"mantas": {
"LIBRE": [ /* trastos + donorName, donorPhone */ ],
"PEDIDO": [ /* … */ ],
"ENTREGADO": [ /* … */ ]
},
"tratos": [ { "id", "code", "name", "phone", "status", "createdAt" } ]
}
Orden tratos: created_at DESC. [DECISIÓN]
5. Frontend Angular
Rutas
| Path | Component | Guard |
|---|---|---|
'' | PlazaPage | — |
dejar | DejarPage | — |
ok/:code | OkPage | — |
login | LoginPage | — |
mesa | MesaPage | authGuard |
** | redirect '' | — |
Servicios
| Service | Responsabilidad |
|---|---|
TrastosApi | GET list/detail · POST dejar |
TratosApi | POST tratos (captura 409) |
AuthApi | login, token store, logout |
MesaApi | GET mesa con Bearer |
BottomNavState | slot activo |
UI Must
PlazaPage— tile + 3 datos + 4 mantas (Deriva), no bento ni tabla.LlevarseSheet— F-MKT una pieza.DejarPage— form público.OkPage— código + 4 oposiciones.LoginPage/MesaPage.BottomNavComponent— S-BOTTOM.- Estados empty/error/loading/409.
Tailwind tokens
ground: #F4F1E8
ink: #1A2B1C
card: #FFFFFF
mark: #3F6B4A
mute: #6E7A70
geranio: #C45C4A
font-display: "Libre Baskerville"
font-sans: "Nunito Sans"
6. Assets en app
Copiar desde el case a apps/web/public/assets/trastos/ (o path equivalente servido):
lampara.jpgsilla.jpgcuna.jpgmaleta.jpg
hero.jpg → tile Deriva (/assets/hero.jpg).
Paths en DB alineados a /assets/trastos/.... [DECISIÓN]
7. Checklist anti-leftover
| Prohibido en runtime | Sustituto |
|---|---|
pinon-api | manta-api |
| puerto 3027 | 3028 |
bicis / requests / ganchos | trastos / tratos / mantas |
| MECANICO | REGIDORA |
| PIN-XXXX | MNT-XXXX |
/encargo | /dejar + sheet |
| ESPERA/EN_TALLER/LISTA | LIBRE/PEDIDO/ENTREGADO |
| Spectral / Sora industrial | Libre Baskerville / Nunito Sans botanical |
G-GRAPHITE #2C3033 | G-BONE #F4F1E8 |
| S-TOP Taller · Encargo · Mesa | S-BOTTOM Plaza · Dejar · Mesa |
8. DoD técnico (merge)
- Smoke S01–S12 (doc 13) en verde.
- Health
manta-api. - Seed idempotente.
- Mesa 401 sin token.
- POST trato no-LIBRE → 409.
- Success muestra las 4 oposiciones.
- 390 + S-BOTTOM usable.
- 0 referencias de producto a bicis/MECANICO/pinon-api/ganchos.
- Ink sobre hueso en cuerpo.
9. Fuera de esta especificación
- Pagos (L2/L3).
- GPS (L2/L3).
- Instrumentación analytics (doc 12 modelo).
- PATCH de estado (mesa de lectura).
Ninguno de esos ítems es un «siguiente paso» del L1. [DECISIÓN]
10. Cierre
Implementación = contrato ejecutable del case 2026-08-28-manta, cerrado en una iteración. [COMPROBADO] alcance L1.