En esta página 00-day-brief 0%

00-day-brief.md

00 — Day brief · 2026-08-28 · MANTA

Decisiones ALS-2 BRIEF

CampoValor
Fecha2026-08-28
NombreMANTA
ComplejidadNivel 1 (no L2 consecutivo tras PIÑÓN)
SectorEconomía circular / merendero de trueque de barrio (plaza de Usera)
TipoPlano de plaza + dejar/llevarse un trasto + mesa REGIDORA JWT
PlataformaWeb responsive (plano en el móvil · mesa en el portátil de la portera)
RegistroR-CL — merendero clásico, no app de marketplace
ShellS-BOTTOM — Plaza · Dejar · Mesa
HomeH-MAP · FOLD-MAP — plaza a sangre con 4 hotspots encima, no panel lateral de cards
FoldFOLD-MAP (CRON §5.9). No FOLD-SPLIT de LOMO ni grid 2×2 al lado del hero.
FlujoF-MKT — llevarse un trasto (una pieza, sin carrito)
Por qué no PIÑÓNNo S-TOP / H-BENTO / F-CMP; no taller; no ganchos
Por qué no BOBINANo S-DOCK / H-FEED / F-STORY; no cineclub
Por qué no LOMONo S-CMD / H-DATA / F-LEAD; no mesa de ejemplares
Por qué no DERIVADERIVA era paseo turístico F-MAP; aquí F-MKT de un objeto, no una ruta
Por qué no CESTACESTA era tabla de necesidades ONG; aquí plano de mantas, no despensa
Por qué no PLIEGONo 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:
    • #F4F1E8 hueso de muro (ground)
    • #1A2B1C musgo profundo (ink)
    • #FFFFFF ficha
    • #3F6B4A musgo (mark)
    • #6E7A70 mute
    • #C45C4A geranio (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

  1. Home plano foto-led: 4 mantas + 3 métricas
  2. Dejar un trasto (nombre, teléfono, qué es, color)
  3. Llevarse un trasto (F-MKT, una pieza, sin carrito)
  4. Success con código
  5. Login JWT REGIDORA
  6. Mesa de mantas (LIBRE / PEDIDO / ENTREGADO) — no kanban
  7. Empty / error / loading / mobile
  8. ≥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

IDSeñal
H1Un plano de mantas reduce «¿sigue ahí la lámpara?» por WhatsApp
H2Una pieza por vez evita el carrito que convierte el trueque en tienda
H3Cuatro trastos bastan; no hace falta el catálogo de Wallapop

Seed demo

CódigoTrastoColorEstado
MNT-2801Lámpara de piecremaLIBRE
MNT-2802Silla de eneamaderaPEDIDO
MNT-2803Cuna plegablecrudoLIBRE
MNT-2804Maleta rígidaverdeENTREGADO

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

URLhttps://app.paper.design/file/01M13JZXPYG2GXDC3HWW5K8X6K
File ID01M13JZXPYG2GXDC3HWW5K8X6K

UX-count: 12 UI-count: 12

UX process (prefijo UX- · mínimo 12)

IDNombreContenido
UX-00CoverIdentidad botanical, terna, foto plaza
UX-01StakeholdersNines REGIDORA, Pilar VECINA
UX-02PersonasPilar 62 / Nines 48
UX-03JTBDFuncional / emocional / social
UX-04StoriesMust dejar / llevar / mesa
UX-05JourneyDescubrir → manta → trato → código
UX-06BlueprintFrontstage / mesa / Neon / 409
UX-07Site mapS-BOTTOM Plaza · Dejar · Mesa
UX-08FlujosPOST trastos + tratos + JWT
UX-09Datos + permisosTrasto / Trato / User
UX-10MétricasNorth star trastos recogidos
UX-11Research notesCOMPROBADO / SUPUESTO / HIPÓTESIS / DECISIÓN

UI producto (prefijo UI- · mínimo 10)

IDNombreFlujo
UI-01Plaza Deriva foto-ledHome H-MAP ≥40 %
UI-02Dejar trastoF-MKT dejar
UI-03LlevarseF-MKT una pieza
UI-04SuccessMNT-2805 copy duro
UI-05LoginJWT REGIDORA
UI-06MesaLIBRE / PEDIDO / ENTREGADO
UI-07EmptyNo hay mantas
UI-08Error409 no libre
UI-09LoadingSkeletons
UI-10TokensG-BONE botanical
UI-11Mobile plazaCore 390
UI-12Mobile dejarForm 390

01-project-definition.md

01 — Definición de proyecto — MANTA

1. Identidad

CampoValor
NombreMANTA
SignificadoLa 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 frasePlano foto-led de plaza + dejar/llevarse un trasto + mesa REGIDORA JWT.
SectorEconomía circular / merendero de trueque de barrio (plaza de Usera, Madrid)
TipoWeb L1 — plano H-MAP Deriva + chrome S-BOTTOM + mercado F-MKT de una pieza + mesa JWT — Nivel 1, vertical slice de merendero
PlataformaWeb responsive (plano en el móvil · mesa en el portátil de la portera)
Mercado demoEspaña · Madrid · Usera (una plaza, no Wallapop)
Idiomaes-ES
Fecha caso2026-08-28
TernaR-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

ProblemaQuién lo sufreEfecto
«¿Sigue ahí la lámpara?» por WhatsAppVECINA (Pilar)Pregunta, espera, pasa de ir a la plaza
Dejar se lee como venderPilar + NinesEsperan anuncio, precio, puja
Trueque se lee como subastaPilarEsperan timer, mejor oferta
Llevarse se lee como reservar IKEAPilar + AmparoEsperan carrito, hold, click & collect
La mesa REGIDORA se lee como kanbanREGIDORA (Nines)Esperan Recibido / En curso / Cerrado
El dueño pide pagos y GPS el día 1PlazaEl 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

IDHipótesisSeñal de validación (futura)
H1Un plano de mantas reduce «¿sigue ahí la lámpara?» por WhatsApp% de visitas a / que consultan estado sin mensaje
H2Una pieza por vez evita el carrito que convierte el trueque en tiendaPOST /api/tratos de un código; 0 carrito
H3Cuatro trastos bastan; no hace falta el catálogo de Wallapop0 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

ParaValor
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 MANTAUna superficie mínima: plano + dejar + llevarse + mesa, sin Wallapop y sin GPS.

No es MANTA

ExcluidoPor qué
Anuncio / venta / precioDejar el trasto ≠ vender en Wallapop
Subasta / puja / timerTrueque ≠ subasta
Carrito / hold / click & collectLlevarse ≠ reservar IKEA
Wallapop / marketplaceMANTA no es Wallapop
Catálogo completo / miles de SKUH3 · S1
Chat de vecinos / kanbanEso fue PREGÓN (H-CHAT / F-KAN)
Flota de última milla / GPSEso fue TROCHA
Taller de bicis / ganchosEso fue PIÑÓN (S-TOP / H-BENTO / F-CMP)
Paseo turístico / rutaEso fue DERIVA (F-MAP, no F-MKT de un objeto)
Tabla de necesidades ONGEso fue CESTA (H-TABLE, despensa)
Lookbook de atelierEso fue PLIEGO
Hero 2-col + 3 cards de «tu rastro»Anti-patrón AP-12; contradice H-MAP Deriva
App de 40.000 anunciosL1 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

RolObjetivo medible en demo
VECINAVer 4 mantas, dejar un trasto o llevarse uno y ver el success en < 90 s, sin cuenta
REGIDORAEntrar a mesa, ver LIBRE / PEDIDO / ENTREGADO en < 45 s
VECINA MAYORNo 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ónAnónimo (vecina)REGIDORAVECINA MAYOR
Ver plaza /Sin cuenta; usa la pública
Ver dejar /dejarSí (no es el job)
POST dejar trastoSí (no es el job)Sí (mismo form público)
POST llevarse (trato) si LIBRESí (no es el job)
Ver success /ok/:code (código en URL)
Ver mesa /mesaNo (401 / redirect)No
GET /api/mesa401
Ver teléfonos de tratos / dejasNoSí (mesa)
Cobrar / pujarNo (no existe)NoFuera
GPS / repartoCopy: fueraCopy: fueraOficio 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)

TipoMétricaDefinición
North Star% de visitas a plaza que resuelven «¿sigue ahí la lámpara?» sin WhatsAppOficio de manta, no pageviews
Activación vecina1.er POST /api/trastos o /api/tratos con codeH2
Integridad de expectativaReclamaciones «¿lo vendo?» / «¿subo puja?» / «¿lo reservo?»H2 + microcopy
Integridad de authGET /api/mesa sin token → 401; POST trastos/tratos sin token → 201/409Plano público + mesa REGIDORA cerrada
Integridad de mercadoPOST /api/tratos sobre no-LIBRE → 409H2 · una pieza
SaludError rate API trastos / tratos4xx/5xx

7. Alcance funcional v1 (L1)

MóduloIncluido
Home planoGET /api/trastos · tile de plaza a sangre + 3 métricas + 4 mantas
Dejar/dejar · nombre, teléfono, qué es, color · POST /api/trastos
LlevarseF-MKT sobre / · una pieza · POST /api/tratos · 409 si no LIBRE
Success/ok/:code · código + 4 oposiciones
AuthPOST /api/auth/login → JWT REGIDORA
Mesa REGIDORAGET /api/mesa JWT · LIBRE / PEDIDO / ENTREGADO, no kanban
Estados UIEmpty (0 trastos), loading skeleton, error de red, 409
MobilePlaza ~390px · S-BOTTOM Plaza · Dejar · Mesa · targets ≥44px
Seed1 REGIDORA, 4 trastos (2 LIBRE, 1 PEDIDO, 1 ENTREGADO)
SaludGET /api/health{ ok: true, service: "manta-api" }

8. Criterios de aceptación de producto

  1. / 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.
  2. Una vecina puede ver 4 trastos, dejar uno y obtener success en /ok/MNT-XXXX, o llevarse uno LIBRE.
  3. /ok/:code dice explícitamente que dejar el trasto no es vender en Wallapop y que trueque no es subasta.
  4. La UI dice explícitamente que llevarse no es reservar IKEA y que MANTA no es Wallapop.
  5. Sin token, GET /api/mesa responde 401. POST /api/trastos, POST /api/tratos y GET /api/trastos son públicos.
  6. Un POST de dejar no crea user, no cobra, no abre anuncio, no mueve kanban, no enciende GPS.
  7. Un POST de llevarse sobre no-LIBRE responde 409. Una pieza. Sin carrito.
  8. Una REGIDORA inicia sesión y ve 4 trastos (2 LIBRE, 1 PEDIDO, 1 ENTREGADO) en el seed.
  9. El tablero autenticado es una mesa de mantas. No es un kanban de 3 columnas. No es un split lista | ficha.
  10. Fotos reales en las cubiertas seed (assets trastos/*).
  11. Chrome S-BOTTOM: Plaza · Dejar · Mesa. Home sin top de taller y sin dock de cineclub.
  12. Rutas solo las del doc 03. No existen /encargo, /buscar, /carrito, /subasta, /gps.
  13. GET /api/health devuelve service: "manta-api" (no pinon-api, no bobina-api).
  14. El plano público no muestra teléfonos de otras vecinas; la mesa REGIDORA sí muestra dejas y tratos con nombre y teléfono.
  15. MNT-2801 y MNT-2803 aparecen LIBRE; MNT-2802 PEDIDO; MNT-2804 ENTREGADO; no se vende ninguno.

9. Stack y artefactos

CapaDetalle
FrontendAngular + Tailwind · puerto 4200
BackendNestJS · puerto 3028
DBNeon PostgreSQL · project fancy-sun-85815074 (DATABASE_URL)
AuthJWT (REGIDORA)
DiseñoPaper 01M13JZXPYG2GXDC3HWW5K8X6K
Repo app/Users/cristian/orca/manta-app/ · GH Criscode2022/manta-app
Packagepnpm

[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

RiesgoImpactoMitigación v1
Expectativa de Wallapop«¿Lo vendo?»Copy «Dejar el trasto ≠ vender en Wallapop»
Expectativa de subastaPuja, timerCopy «Trueque ≠ subasta»
Expectativa de IKEACarrito, holdCopy «Llevarse ≠ reservar IKEA»
Expectativa de marketplaceCatálogo, SKUCopy «MANTA no es Wallapop»
Expectativa de kanbanRecibido / En cursoMesa de mantas, no columnas de flujo
Leftover PIÑÓNbicis, MECANICO, pinon-api, ganchosContrato MANTA; health manta-api; 0 copy de taller
Leftover BOBINA / LOMOsesiones, ejemplaresDominio trastos + tratos + REGIDORA
Pagos el día 1Alcance L2/L3 disfrazadoS3; H3: cuatro mantas
GPS el día 1Alcance TROCHAS3; roadmap L2/L3
Cuenta de vecinaRompe S2Sin signup; POST público con nombre + teléfono
Home percibida como landing de rastroPérdida de H-MAP / AP-12Deriva tile + 3 datos + 4 mantas
Home percibida como mapa turísticoConfundir con DERIVAF-MKT de un objeto, no F-MAP de ruta
Home percibida como bento de ganchosConfundir con PIÑÓNPlano de plaza, no H-BENTO
Home percibida como tabla ONGConfundir con CESTAPlano, no despensa
Carrito en F-MKTRompe H2Una pieza; 409 si no LIBRE
0 trastosPlano vacío sin oficioEmpty «Aún no hay mantas.»
WhatsApp paraleloH1 no se mideNorth star etiquetada como modelo
Geranio como texto de párrafoContraste WCAGGeranio pinta sello PEDIDO/error; ink escribe

11. Glosario

TérminoDefinición en MANTA
MantaSuelo del merendero; superficie del plano; el producto, no el anuncio
TrastoObjeto en manta (trastos); no es un anuncio de Wallapop
CódigoMNT-XXXX; identifica el trasto / el trato
DejarPOST /api/trastos; no es vender
LlevarsePOST /api/tratos; no es reservar IKEA
TratoAcción de llevarse una pieza; no es subasta
PlazaSuperficie H-MAP pública de mantas; plano sobre foto de plaza
Mesa (REGIDORA)Superficie JWT de Nines (mantas por estado, no kanban)
LibreEstado LIBRE; se puede llevar
PedidoEstado PEDIDO; ya hay un trato esta mañana
EntregadoEstado ENTREGADO; ya no está en la manta
SuccessCódigo (MNT-XXXX); no es un ticket de tienda
S-BOTTOMChrome: Plaza · Dejar · Mesa
REGIDORAUsuario autenticado que opera la mesa
VECINAAutora del dejar / llevarse; no tiene fila en users
VECINA MAYORPersona de docs / a11y; fuera del login
WallapopMarketplace; fuera. Dejar ≠ vender
SubastaPuja; fuera. Trueque ≠ subasta
IKEAReserva / carrito; fuera. Llevarse ≠ reservar
BotanicalMood: geranio, plátano de sombra, hueso de muro; no sepia de rastro
GroundHueso de muro #F4F1E8
InkMusgo profundo #1A2B1C
CardFicha #FFFFFF
MarkMusgo #3F6B4A
Mute#6E7A70
Geranio#C45C4A, poco
DerivaHome foto-led: tile de plaza a sangre + 3 datos + 4 mantas

12. Decisiones de diseño (cierre de brief)

IDDecisiónAlternativa descartada
D1Home = plano foto-led Deriva (H-MAP)Hero 2-col + 3 cards (AP-12) · bento (PIÑÓN) · feed (BOBINA) · tabla (CESTA)
D2Shell bottom Plaza · Dejar · Mesa (S-BOTTOM)Top de taller · dock de cineclub · comando de archivo
D3Registro clásico: merendero, no app de marketplace (R-CL)Sepia rastro vintage (primer instinto) · industrial PIÑÓN
D4Flujo F-MKT (llevarse un trasto, una pieza, sin carrito)F-CMP, F-MAP turístico, F-LEAD, carrito checkout
D5Mood botanicalRastro vintage sepia (primer instinto), arid/dust, rusted, pastoral
D6Un rol autenticado REGIDORAMulti-rol vecina / portera / dueño
D7Status LIBRE / PEDIDO / ENTREGADOKanban; «vendido»; «en ruta»; ESPERA / EN_TALLER
D8Vecina sin cuentaSignup, socio, carnet de merendero
D9Plano público no lista teléfonosTablero público enumerable
D10POST público de dejar con nombre + teléfono + qué es + colorFormulario de DNI + pago + precio
D11Ground G-BONE #F4F1E8G-GRAPHITE, G-VELVET, G-STONE, sepia de rastro
D12Success en /ok/:codeToast único sin pantalla
D13Dejar en /dejar; llevarse sheet sobre / (sin quinta ruta)/llevarse/:code; carrito /checkout
D14Mesa REGIDORA = mantas por estado, no kanban ni splitRecibido / En curso / Cerrado; lista | ficha RAMAL
D15Plano público + mesa JWT (no auth-first total)Todo cerrado (rompería S2) · todo abierto (rompería mesa)
D16Sin pagos / GPSPrecio + tracking
D17Leftover PIÑÓN no es el productoMantener bicis / MECANICO / pinon-api / ganchos
D18Health manta-api · puerto 3028leftover pinon-api · :3027
D19Llevarse = una pieza; 409 si no LIBRECarrito multi-SKU; hold IKEA
D20POST tratos sobre LIBRE → PEDIDOPasa a ENTREGADO (saltaría el recado de plaza)

13. Relación con el día anterior

CaseTernaPor qué MANTA no lo copia
PIÑÓN (N−1)R-HY · S-TOP · H-BENTO · F-CMPNo taller, no ganchos, no bento, no configurador, no MECANICO
BOBINA (N−2)R-IN · S-DOCK · H-FEED · F-STORYNo cineclub, no feed, no dock, no butaca
LOMO (N−3)R-CL · S-CMD · H-DATA · F-LEADComparte R-CL; no archivo, no ejemplares, no comando, no mesa de datos
DERIVAR-IN · S-SPLIT · H-MAP · F-MAPComparte H-MAP; aquí F-MKT de un objeto, no ruta turística
CESTAR-CL · S-RAIL · H-TABLE · F-LEADPlano de mantas, no despensa / tabla de necesidades
PLIEGONo lookbook; no se vende ropa nueva
MATIZR-HY · S-BOTTOM · H-BENTO · F-EDITComparte 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)

ObjetivoMétodo en este casoSalida
Entender actores del merendero de barrioModelado 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-MKTJourney + service blueprint§7–8
Traducir a requisitos L1 plano + dejar + llevarse + mesaMatriz 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

ProhibidoPermitido
«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 realQuotes de persona etiquetadas como constructo de diseño
Volumen medido «18 lámparas/semana» como KPI de mercadoTrastos de seed de producto, etiquetados como demo
Merendero municipal oficial en Usera 2026Plaza 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

StakeholderInfluenciaInterésNecesidad principal
REGIDORA (Nines)AltaMuy altaVer mantas sin kanban ni anuncio
VECINA (Pilar)Alta en el gestoMuy altaDejar o llevarse un trasto y saber el código, sin cuenta
VECINA MAYOR (Amparo)Media formal, baja en producto día 1AltaLeer el plano con contraste y targets; sin login forzado
Plaza / merendero de barrioAlta formalAltaQue se vea qué hay en la manta; que no se confunda con Wallapop
Wallapop / marketplaceCompetencia / analogía falsaFuera de alcance; no clonar anuncio
Subasta / pujaAnalogía falsa de truequeFuera; Trueque ≠ subasta
IKEA / carrito / holdAnalogía falsa de llevarseFuera; Llevarse ≠ reservar IKEA
PIÑÓN / tallerAnti-patrón N−1Fuera; no bicis, no ganchos, no MECANICO
DERIVA / paseoAnalogía falsa de H-MAPFuera; F-MKT de un objeto, no ruta
CESTA / despensaAnalogía falsa de merenderoFuera; plano de mantas, no tabla de necesidades
Grupo de WhatsApp del portalCanal paraleloNo es el backoffice; H1 apunta a reducirlo
Dueño de puesto / transportistaFueraFuera 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

CampoDetalle
Edad / contexto54 años; regidora del merendero MANTA en plaza de Usera; mesa de mantas, no de anuncios. Edad = constructo.
DigitalFluida en el portátil de la portería; el plano público no es su herramienta principal, pero lo mira
GoalsVer qué trastos están libres, cuáles tienen pedido, cuáles ya se entregaron
PainsWhatsApp 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 demonines@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

CampoDetalle
Edad / contexto47 años; vive en Usera; deja un trasto el domingo o se lleva uno; no quiere «otra cuenta de Wallapop». Edad = constructo.
DigitalMóvil desde el banco de la plaza o el sofá; no se registra si puede evitarlo
GoalsVer qué hay en las mantas; dejar un trasto; llevarse uno; llevarse un código
PainsEl 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)

CampoDetalle
Edad / contexto71 años; vecina de Usera; lee el plano con calma; contraste y tamaño importan. Edad = constructo de la serie a11y.
DigitalNo tiene login en el slice L1; usa la superficie pública si el contraste y los targets aguantan
GoalsEntender cómo dejar o llevarse un trasto, sin mistificarse con Wallapop ni con un carrito
PainsTexto 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

JobPor qué no
Vender un trastoDejar el trasto ≠ vender en Wallapop · S3
Pujar / subastarTrueque ≠ subasta
Reservar / hold / carritoLlevarse ≠ reservar IKEA
Sustituir a WallapopMANTA 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)

IDComoQuieroPara
US-01VecinaVer plano foto-led de 4 mantas + 3 métricasDistinguir merendero de Wallapop / feed / tabla / bento
US-02VecinaDejar un trasto (nombre, teléfono, qué es, color) y ver success MNT-XXXXDejar constancia, no vender
US-03VecinaLlevarse un trasto LIBRE (F-MKT, sin carrito)Evitar tienda
US-04VecinaRecibir 409 si el trasto no está LIBRENo «reservar» lo que ya no está
US-05RegidoraEntrar con JWTAbrir la mesa de mantas
US-06RegidoraVer LIBRE / PEDIDO / ENTREGADO + tratosOficio sin kanban
US-07AmbosVer empty / error / loadingNo quedarse en blanco
US-08VecinaUsar S-BOTTOM en 390Plaza · Dejar · Mesa sin hamburger

Could (fuera de L1, solo L2/L3): pagos, GPS, login de Amparo, chat, cuenta de vecina, carrito.

7. Journey (resumen)

  1. Pilar abre /. Ve tile de plaza a sangre + 3 datos (libres / pedidos / entregados) + 4 mantas. MNT-2801 LIBRE; MNT-2802 PEDIDO. [H1]
  2. 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]
  3. Alternativa: toca Dejar → /dejar. Nombre, teléfono, qué es, color. POST /api/trastos/ok/MNT-2805.
  4. Intento de silla PEDIDO → 409 «Ese trasto ya no está libre.»
  5. Nines entra a /login/mesa. Mantas por estado + tratos.
  6. 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)

CapaQué 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.
SoporteNest · Neon fancy-sun-85815074 · JWT REGIDORA · Paper botanical

9. Matriz hallazgo → requisito → feature

Hallazgo (etiquetado)RequisitoFeature v1
[HIPÓTESIS H1] Plano de mantas reduce WhatsApp4 trastos + 3 métricas en fold sobre tile/ H-MAP Deriva
[HIPÓTESIS H2] Una pieza evita el carritoPOST tratos de un código; 409 si no LIBREUI-03 · POST /api/tratos
[HIPÓTESIS H3] Cuatro trastos bastanSin catálogo WallapopSeed 4 · no marketplace
[SUPUESTO S2] Sin cuenta de vecinaPOST públicoPOST /api/trastos + /api/tratos
[SUPUESTO S1] 4 / mañanaDemo 4Seed MNT-2801…2804
[DECISIÓN S3] Sin pagos / GPS / chat / kanbanNo cobro, no tracking, no hilo, no columnasFuera 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

PrincipioAplicación
Plano firstLa 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 / mesaPilar deja o se lleva sin cuenta; Nines entra con JWT
Dejar | llevarse → successProfundidad 1–2 desde el plano hasta el código (F-MKT)
El núcleo es una piezaF-MKT: un trasto LIBRE, sin carrito
Mesa REGIDORA = mantasLIBRE / PEDIDO / ENTREGADO en una mesa; no kanban, no split lista | ficha
Lenguaje de dominioTrasto, manta, trato, plaza, mesa — no «SKU», «anuncio», «gancho», «bici»
Dejar no es venderEl success no tiene precio ni anuncio
Plaza no es WallapopNo hay puja, no hay carrito, no hay catálogo infinito
Chrome de merenderoS-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

AudienciaNodos relevantes
VECINAPlaza → Dejar o Llevarse (sheet) → Ok. No ve /mesa
REGIDORALogin → Mesa · (puede leer la plaza y dejar)
VECINA MAYORPlaza / 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)

SlotDestinoVisibilidadNotas
Plaza/TodosVuelve al plano Deriva. No es hero de marca
Dejar/dejarTodosEntra al form de dejar
Mesa/mesaREGIDORA; si guest → /login?next=/mesaOficio 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)

ElementoDestinoNotas
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 datosLibres / Pedidos / Entregados (números del seed)
Pin / ficha de mantasheet llevarse si LIBRE4 mantas; título, color, estado
Tap LIBREUI-03 sheetArranque de F-MKT
Tap PEDIDO / ENTREGADOsello + copy; no POST409 si se fuerza
CTA Dejar/dejarS-BOTTOM o lead
Slot Mesa (mute)/login o /mesa si hay tokenOficio, 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)

SlotDestinoNotas
← Plaza/Un paso atrás, no stepper de 5
Form/dejarNombre, teléfono, qué es, color
EnviarPOST → /ok/:codeUna acción

[DECISIÓN] Dejar no es un modal efímero sin URL. No hay wizard de criterios.

Chrome de llevarse (sheet sobre /)

SlotDestinoNotas
Cerrar/Conserva el plano
Formmismo pathNombre, teléfono; código en solo lectura
EnviarPOST /api/tratos/ok/:codeUna pieza
No LIBRE409 / disabled«Ese trasto ya no está libre.»

Chrome de mesa (/mesa autenticado)

SlotDestinoVisibilidadNotas
Mesa/mesaAuthTitular de oficio
MantasAuthAgrupadas LIBRE / PEDIDO / ENTREGADO
TratosAuthNombre + teléfono + código; no columnas de flujo
Plaza/AuthSecundario vía S-BOTTOM
Salirlimpia token → /AuthCabecera 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)

ConceptoLabel
HomePlaza (no «Inicio», no «Taller», no «Cartelera», no «Mapa turístico»)
Flujo dejarDejar (no «vender», no «publicar anuncio»)
Flujo mercadoLlevarse (no «reservar», no «añadir al carrito», no «pujar»)
SuccessDejado / Trato / código
StaffMesa (no «Backoffice», no «Kanban», no «Hoy» JWT)
AuthRegidora (no «Área cliente», no «Mecánica»)
CTA dejarDejar el trasto (no «Vender», no «Publicar»)
CTA llevarseLlevarse (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

RutaQué hayQué no hay
/Tile de plaza, eslogan, 3 métricas, 4 mantas, S-BOTTOM, sheet llevarsePrecios, login de vecina, carrito, GPS, ganchos
/dejarNombre, teléfono, qué es, color, disclaimerDNI, email, pago, precio, socio
/ok/:codeCódigo + 4 oposicionesContrato, ticket, «ya está publicado», QR de tienda
/loginEmail / clave REGIDORASignup de vecina
/mesaMantas de 4 + tratosColumnas 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.

EstadoSuperficie
LoadingSkeletons 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 incompletoCTA 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

PiezaForma
TrastoMNT-2801MNT-2804 (MNT versales, guion, 4 dígitos)
Dejar nuevoMNT-2805+ secuencial al POST /api/trastos
Tratomismo code del trasto LIBRE
Success/ok/MNT-2801 o /ok/MNT-2805

9. Mapa Paper → rutas

ArtboardRutaComponente
UI-01 Plaza Deriva/PlazaPage
UI-11 Mobile plaza/ @390PlazaPage
UI-02 Dejar/dejarDejarPage
UI-12 Mobile dejar/dejar @390DejarPage
UI-03 Llevarse/ sheetLlevarseSheet en PlazaPage
UI-04 Success/ok/:codeOkPage
UI-05 Login/loginLoginPage
UI-06 Mesa/mesaMesaPage
UI-07 Emptymismas rutasestados
UI-08 Errormismas rutasestados
UI-09 Loadingmismas rutasestados
UI-10 TokensthemeTailwind

[COMPROBADO] Mapeo alineado a docs/00-paper-reference.md.

04-user-flows.md

04 — Flujos de usuario — MANTA

1. Convenciones

TokenSignificado
F-MKTLlevarse un trasto LIBRE; la home es el plano, no el form
MesaMantas REGIDORA, JWT
201Dejado (trasto LIBRE nuevo) o trato (trasto pasa a PEDIDO)
400Nombre / teléfono / título / color inválidos
401Mesa sin token
404Código inexistente
409Llevarse 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-2801 muestra 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-2805 dice «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, /mesa redirige a /login?next=/mesa.
  • GET /api/mesa sin 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 aparece (oficio de cierre de mañana). [DECISIÓN] distinto de PIÑÓN, donde ENTREGADA se ocultaba.

6. F5 — Estados de sistema

EstadoTriggerUI
Loading plazaGET trastos en vueloSkeletons de tile + 3 datos + 4 fichas (UI-09)
Empty plaza200 { trastos: [] }«Aún no hay mantas.» (UI-07)
Error plaza5xx / redReintentar (UI-08)
Loading dejarForm listo; submit pending (UI-09)
Loading llevarsePOST en vuelopending en CTA
409no LIBRE«Ese trasto ya no está libre.» (UI-08)
Loading mesaGET mesa en vueloSkeletons de manta + tratos
Empty mesa tratos200 { tratos: [] }«No hay tratos.» (las 4 mantas seed pueden existir)
Login 401credenciales«Email o contraseña no valen.»
404 successcódigo inexistente«Ese trasto no está.»

7. Flujos que no existen

FlujoPor qué
Signup vecinaS2 · Dejar ≠ socio
Vender / publicar anuncioS3 · Dejar ≠ vender en Wallapop
Subasta / puja / timerTrueque ≠ subasta
Carrito / hold / click & collectLlevarse ≠ 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 AmparoSlice L1 · docs / a11y
PATCH estado de trastoNines lee mantas; no mueve columnas en v1
Catálogo WallapopH3 · S3
Búsqueda ?q=Sin S-CMD
Multi-pieza / checkoutRompe H2

8. Tiempos de demo (modelo)

ActorRecorridoTecho
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
NinesLogin → 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

  1. / — tile de plaza a sangre + 3 datos (2 libres / 1 pedido / 1 entregado) + 4 mantas. Eslogan. S-BOTTOM.
  2. Lectura rápida: MNT-2801 Lámpara crema LIBRE; MNT-2802 Silla enea PEDIDO; MNT-2803 Cuna crudo LIBRE; MNT-2804 Maleta verde ENTREGADO.
  3. Llevarse — tap lámpara · Pilar Ramos · teléfono · POST → /ok/MNT-2801. Copy ×4.
  4. Reintento lámpara → 409.
  5. Dejar — /dejar · Espejo óvalo · dorado · /ok/MNT-2805.
  6. /loginnines@manta.plaza / password123.
  7. /mesa — mantas LIBRE / PEDIDO / ENTREGADO; MNT-2801 PEDIDO si se hizo el trato; trato de Pilar visible.
  8. 390: plano + S-BOTTOM; no carousel; targets ≥44px.
  9. API down: error + Reintentar.

10. Contratos de error de API (flujo)

CasoHTTPUI
POST dejar, título vacío400«Escribe qué dejas.»
POST dejar, nombre vacío400«Escribe un nombre.»
POST dejar, teléfono vacío / corto400«Escribe un teléfono.»
POST dejar, color vacío400«Di el color.»
POST trato, code ausente400«Elige un trasto.»
POST trato, no LIBRE409«Ese trasto ya no está libre.»
POST trato, nombre / teléfono inválido400Campos
POST, redmark + Reintentar; no navega a ok
GET mesa sin JWT401redirect login
Login malo401copy de login
GET /ok code 404404«Ese trasto no está.»

11. S-BOTTOM en flujo

DesdeSlotComportamiento
/Plazaaria-current
/Dejar/dejar
/dejarDejararia-current
/ok/:codePlazaVuelve al plano
/ guestMesa/login?next=/mesa
/ con tokenMesa/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:

EntidadTabla SQLPropósito
UserusersIdentidad de oficio (rol REGIDORA)
SessionsessionsSesión JWT / token persistido
TrastotrastosObjeto en manta (código MNT-XXXX, título, color, estado, cover, quien deja)
TratotratosLlevarse 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

ValorDescripción
REGIDORARegidora de la mesa; único rol autenticado v1

TrastoStatus

ValorDescripción
LIBREEn la manta; se puede llevar
PEDIDOHay un trato esta mañana; ya no está libre
ENTREGADOYa 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 ≠ LIBRE409. [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_name es quien deja (oral), no una cuenta.
tratos.name es quien se lleva.
Teléfonos no se pintan en el plano público.

4. Tablas

users

ColumnaTipoNotas
idBIGSERIAL PK
emailTEXT UNIQUEnines@manta.plaza
password_hashTEXTbcrypt 12 · seed $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
nameTEXTNines Ortega
roleTEXTREGIDORA
created_atTIMESTAMPTZ

sessions

ColumnaTipoNotas
idUUID PKsid del JWT
user_idBIGINT FK
expires_atTIMESTAMPTZ
revoked_atTIMESTAMPTZlogout
created_atTIMESTAMPTZ

trastos

ColumnaTipoNotas
idBIGSERIAL PK
codeTEXT UNIQUEMNT-2801
titleTEXTLámpara de pie · Silla de enea · Cuna plegable · Maleta rígida · o el del form
colorTEXTcrema / madera / crudo / verde / el del form
statusTEXTLIBRE | PEDIDO | ENTREGADO
coverTEXT/assets/trastos/lampara.jpg (seed); POST nuevo puede ir sin cover
donor_nameTEXTQuien deja; no público
donor_phoneTEXTRecado de quien deja; no público
sort_orderINTEGER1 = primer pin del plano
created_at / updated_atTIMESTAMPTZ

tratos

ColumnaTipoNotas
idBIGSERIAL PK
trasto_idBIGINT FK
codeTEXTDenorm MNT-2801 para mesa sin join extra
nameTEXTNombre de quien se lleva (Pilar Ramos)
phoneTEXTTeléfono de recado
created_atTIMESTAMPTZ

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

codetitlecolorstatuscoverdonor_name
MNT-2801Lámpara de piecremaLIBRE/assets/trastos/lampara.jpgCarmen Soto
MNT-2802Silla de eneamaderaPEDIDO/assets/trastos/silla.jpgDiego Rueda
MNT-2803Cuna plegablecrudoLIBRE/assets/trastos/cuna.jpgInma Paz
MNT-2804Maleta rígidaverdeENTREGADO/assets/trastos/maleta.jpgRafael 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

codenamephoneNotas
MNT-2802Lola Méndez612440282Silla ya pedida
MNT-2804Toni Vega625118904Maleta 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 ≠ LIBRE409; 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

ReglaDetalle
Unicidad de códigotrastos.code UNIQUE
Trato solo LIBRESi status ≠ LIBRE → 409
Dejar siempre LIBREPOST trastos no escribe PEDIDO / ENTREGADO
Sin user en trato / donanteNo FK a users desde trastos ni tratos
Mesa privadaGET /api/mesa exige JWT role REGIDORA
Plano públicoGET /api/trastos sin auth
Teléfono no públicoGET /api/trastos sin phone ni name ni donor
Una piezaBody de trato = un code; no array

8. Fuera del modelo v1

ConceptoPor qué fuera
Precio / pago / SKU / pujaDejar ≠ vender · trueque ≠ subasta
Email de la vecinaMinimización; S2. El recado es el teléfono
GPS / lat-lng / rutaS3 · L2/L3
Tabla bicis / requestsLeftover PIÑÓN
Tabla sesiones / ejemplaresLeftover BOBINA / LOMO
PATCH statusMesa de lectura; no kanban
Carrito / líneasH2
Multi-tenant plazaL1 compacto

9. Naming vs leftover

Prohibido (leftover)Contrato MANTA
bicis / requests / ganchostrastos / tratos / mantas
MECANICOREGIDORA
pinon-apimanta-api
PIN-XXXXMNT-XXXX
ESPERA / EN_TALLER / LISTALIBRE / PEDIDO / ENTREGADO
puerto 30273028
/encargo/dejar + sheet llevarse

06-tech-stack.md

06 — Stack técnico — MANTA

1. Resumen

CapaElecciónNotas
FrontendAngular (standalone) + TailwindPuerto 4200
BackendNestJSPuerto 3028 · prefijo /api
DBNeon PostgreSQLProject fancy-sun-85815074 · DATABASE_URL
AuthJWT BearerRol REGIDORA
PackagepnpmApps independientes (pnpm --filter)
DiseñoPaperFile 01M13JZXPYG2GXDC3HWW5K8X6K
Repo/Users/cristian/orca/manta-appGH 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ónRazónAlternativa descartada
Angular standaloneCoherencia serie ALS-2 dailyNext/React (rompería espejo de cases)
NestJSMismo contrato API que PIÑÓN/BOBINAExpress suelto sin módulos
NeonPostgres managed; project dedicado MANTASQLite local (no portfolio cloud)
TailwindTokens botanical rápidosCSS modules sin design tokens
JWTMesa cerrada; plano abiertoSession cookie-only sin Bearer documentado
pnpm filterMonorepo ligero sin npm workspacesTurborepo pesado para L1

3. Puertos y health

ServicioPuertoHealth
API3028GET /api/health{ ok: true, service: "manta-api" }
Web4200Angular 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 (/apihttp://localhost:3028). [DECISIÓN]

5. Variables de entorno (API)

VariableUso
DATABASE_URLNeon connection string (project fancy-sun-85815074)
JWT_SECRETFirma HS256
PORT3028
NODE_ENVdevelopment / production

No commitear secretos. .env local; ejemplo en .env.example sin credenciales reales. [DECISIÓN]

6. Auth

PiezaDetalle
LoginPOST /api/auth/login { email, password }
Hashbcrypt 12 · seed fijo del encargo
TokenJWT · claims sub, email, role: REGIDORA
GuardBearer en GET /api/mesa
Públicohealth, trastos, trastos/:code, POST trastos, POST tratos, login
Storage weblocalStorage o memory + interceptor; logout limpia

[COMPROBADO] Credenciales demo: nines@manta.plaza / password123.

7. Endpoints (contrato)

MétodoRutaAuthRespuesta clave
GET/api/healthNomanta-api
GET/api/trastosNometrics + array 4
GET/api/trastos/:codeNoitem · soporte success [DECISIÓN]
POST/api/trastosNo201 / 400 · dejar
POST/api/tratosNo201 / 400 / 409 · llevarse
POST/api/auth/loginNo{ accessToken }
GET/api/mesaJWTmantas + tratos

CORS: origen http://localhost:4200 en dev. [DECISIÓN]

8. Frontend — rutas y componentes

RutaComponenteGuard
/PlazaPage (+ LlevarseSheet)
/dejarDejarPage
/ok/:codeOkPage
/loginLoginPage
/mesaMesaPageauthGuard REGIDORA

Chrome: BottomNavComponent (S-BOTTOM). Tokens Tailwind: ground, ink, card, mark, mute, geranio.

9. Assets

Origen caseDestino app
2026-08-28-manta/assets/hero.jpgTile Deriva / cover
assets/trastos/*.jpgapps/web/public/assets/trastos/ o equivalente

Covers en DB como paths /assets/trastos/lampara.jpg etc. [DECISIÓN]

10. Calidad y toolchains

HerramientaUso v1
TypeScriptStrict en api y web
ESLint / PrettierSerie daily
Vitest / JestSmoke API del slice
PlaywrightSmoke S01–S12 del plan QA (doc 13)

11. Anti-stack (no introducir)

TecnologíaPor qué no
Prisma obligatorioBrief no lo exige; ensureSchema + pg válido
Stripe / pagoDejar ≠ vender
Firebase AuthJWT propio REGIDORA
GraphQLREST L1
Socket.io / chat≠ PREGÓN
Mapbox / GPS≠ TROCHA · L2/L3
Carrito persistenteRompe H2
Leftover Nest modules bicis≠ PIÑÓN

12. Criterios de aceptación técnicos

  1. GET /api/healthservice: "manta-api".
  2. Seed idempotente: 1 REGIDORA + 4 trastos + 2 tratos seed.
  3. POST dejar crea trasto LIBRE y devuelve MNT-XXXX.
  4. POST trato sobre LIBRE → 201 PEDIDO; sobre no-LIBRE → 409.
  5. GET mesa sin token → 401.
  6. Web en 4200 consume API 3028 sin mixed-content local.
  7. 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

EjeNo
SuperficieHueso #F4F1E8, ink #1A2B1C, card #FFFFFF, mark #3F6B4AGrafito PIÑÓN, velvet BOBINA, caliza LOMO, sepia de rastro
TipoLibre Baskerville + Nunito SansSpectral+Sora (PIÑÓN), Cormorant+Manrope (BOBINA), Source Serif+Outfit (LOMO)
FotoPlaza, manta, trasto de barrio, UseraSepia El Rastro, lineal IKEA, mock Wallapop, gancho de taller
GridDeriva: tile plaza ≥40 % 16/10 + 3 datos + 4 mantasHero 2-col + 3 cards (AP-12) · bento (PIÑÓN) · feed · tabla CESTA
AcentoMark en CTA/foco/slot activo; geranio en PEDIDO/errorNaranja reflector PIÑÓN, brass de sala, cinta amarilla
ChromeS-BOTTOM Plaza · Dejar · MesaTop taller, dock cineclub, comando archivo

3. Paleta

TokenHexRol
Ground / G-BONE#F4F1E8Hueso de muro. Fondo de página.
Ink#1A2B1CMusgo profundo. Texto primario.
Card#FFFFFFFicha / manta. Superficie elevada.
Mark#3F6B4AMusgo: CTA Dejar/Llevarse, foco, wordmark.
Mute#6E7A70Meta, labels, estado secundario, idle S-BOTTOM
Geranio#C45C4APoco: 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

UsoFamiliaTamaños de referencia
WordmarkLibre Baskerville 60024–28 desktop · 22 mobile
Titular de plaza / mesaLibre Baskerville 60032–44
Código MNT-XXXXLibre Baskerville 60028–36
Título de trastoLibre Baskerville 60022–28
Cuerpo / disclaimersNunito Sans 40016–17 / 26–28 lh
UI, S-BOTTOM, form, listaNunito Sans 400/500/60014 / 16
Meta (color, status)Nunito Sans 50012–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 entran: el brief los fija. [COMPROBADO]

5. Fotografía

AssetDebeNo debe
hero.jpgPlaza de barrio: manta, luz de domingo, Usera, hueso y sombraSepia El Rastro, stock de flea market vintage, gancho de taller
lampara.jpgLámpara de pie crema; LIBRE se lee en UIAnuncio Wallapop con precio
silla.jpgSilla de enea; PEDIDO se lee en UIThumbnail de e-commerce
cuna.jpgCuna plegable crudo; merenderoBanner IKEA
maleta.jpgMaleta rígida verde; ENTREGADO se lee en UIFoto 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

MoodPor qué no
Rastro vintage sepiaPrimer instinto; es El Rastro de postal
Industrial / grafitoFue PIÑÓN
Candlelit / velvetFue BOBINA
Mineral / calizaFue LOMO
Signage / cinta amarillaFue ONDA
Ice institucionalFue RAMAL
Chapel amatistaFue MATIZ
Dusk cartográficoFue 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

GestoTratamiento
Entrada planoFade corto 120–160ms; tile estático (no Ken Burns agresivo)
Hover ficha desktopRing mark 2px; sin lift excesivo
S-BOTTOM activoMark en label; idle mute
Sheet llevarseSlide-up 160ms; reduced = instant
Reduced motion0ms; 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

TokenValorUso
--ground#F4F1E8Fondo de página (hueso de muro)
--ink#1A2B1CTexto primario, títulos
--card#FFFFFFTarjeta de manta, form, mesa
--mark#3F6B4ACTA, foco, S-BOTTOM activo
--mute#6E7A70Meta, idle
--geranio#C45C4ASello PEDIDO, error, poco
--font-displayLibre BaskervilleTitulares
--font-sansNunito SansUI
--target44×44 minToques

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)

ParUsoNota
Ink #1A2B1C sobre Hueso #F4F1E8Cuerpo y títulosDebe pasar WCAG 2.2 AA
Ink sobre Card #FFFFFFTexto en tarjetaVerificar AA
Mark sobre HuesoCTA fill + texto cream/hueso invertido en botónNo sustituye ink en párrafo
Mute sobre HuesoMeta corta; no cuerpoEvitar párrafos mute
Geranio sobre HuesoSello / error cortoNo 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

RolSize / leading
Display plazaclamp(2.2rem, 5vw, 3.6rem) / 0.95
H1 mesa / success2.5rem / 1
H2 título trasto28px / 32px
Cuerpo16–17 / 26
Meta12–13 / 16, tracking 0.08em
S-BOTTOM12–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

SuperficieGrid
Plaza 1440Tile plaza full-bleed 16/10; 3 datos en fila; 4 fichas 2×2 sobre/bajo el plano; S-BOTTOM
Plaza 390Tile + 3 datos wrap + stack de 4; S-BOTTOM fijo inferior
Dejar / Ok / loginColumna max-w-lg
Mesa REGIDORAGrupos + tratos; stacked < lg
Sheet llevarseBottom 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

EstadoTratamiento
DefaultCard + ink
HoverRing mark 2px
Focus visibleOutline mark 2px offset 2
Active / pressedMark fill breve
DisabledOpacity 0.45 · no hit · aria-disabled
Pendingdisabled + aria-busy
ErrorBorde geranio + mensaje
LIBRE seleccionadaRing mark
No LIBRESello; 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

SuperficieTratamiento
Card sobre huesoSombra suave 0 1px 2px ink/8; borde 1px mute/20
S-BOTTOMBarra card; filete mute 1px superior; no material neón
SheetOverlay ink/40 + card; no modal centrado de SaaS
Modal extraNo en v1 Must

9. Mapa a Paper UI

UIComponentes clave
UI-01 / 11Tile plaza + 3 datos + 4 mantas + S-BOTTOM
UI-02 / 12Form dejar
UI-03Sheet llevarse
UI-04Success
UI-05Login
UI-06Mesa mantas
UI-07Empty
UI-08Error / 409
UI-09Loading
UI-10Tokens

[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.

EjeNo
TonoSeco, breve, de barrioCorporativo Wallapop, hype de subasta
Persona«Dejamos el trasto» / tuteo de plaza«Publica tu anuncio» / «reserva tu artículo»
RitmoFrases cortas. Una idea por línea en disclaimersPárrafos legales de marketplace
HumorSeco, pocoMemes, 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ónCopy canónico
Dejar vs venderDejar el trasto ≠ vender en Wallapop.
Trueque vs subastaTrueque ≠ subasta.
Llevarse vs reservarLlevarse ≠ reservar IKEA.
Barrio vs marketplaceMANTA no es Wallapop.

No se parafrasean hasta diluirlas. Pueden acortarse en UI estrecha manteniendo ≠. [DECISIÓN]

3. Glosario UI

ConceptoLabel canónicoEvitar
HomePlazaInicio, Taller, Cartelera, Mapa, Catálogo
ItemTrasto / MantaSKU, anuncio, gancho, bici
Flujo dejarDejarVender, publicar, subir anuncio
Flujo mercadoLlevarseReservar, añadir al carrito, pujar
CTA dejarDejar el trastoPublicar, Vender
CTA llevarseLlevarseReservar, Comprar, Hold
SuccessDejado / TratoConfirmación de compra, Anuncio activo
StaffMesaBackoffice, Admin, Kanban
EstadoLibre / Pedido / EntregadoDisponible / Agotado (retail), En ruta (TROCHA), En taller (PIÑÓN)
Persona authRegidoraMecánica, Programadora, Admin
Error 409Ya no está libreAgotado, Sold, Reserved

4. Pantalla a pantalla

Plaza /

SlotCopy
WordmarkMANTA
EsloganLa manta, no el anuncio.
Dato 1{n} libres
Dato 2{n} pedidos
Dato 3{n} entregados
CTA bottomDejar
EmptyAún no hay mantas.
ErrorLa red no responde. · Reintentar

Dejar /dejar (UI-02)

SlotCopy
TítuloDejar el trasto
Label nombreTu nombre
Label teléfonoTeléfono
Label títuloQué es
Label colorColor
SubmitDejar el trasto
DisclaimerNo es un anuncio. No hay puja. Llevarse ≠ reservar IKEA.
Error nombreEscribe un nombre.
Error teléfonoEscribe un teléfono.
Error títuloEscribe qué dejas.
Error colorDi el color.

Llevarse sheet (UI-03)

SlotCopy
TítuloLlevarse
Meta{title} · {color} · {code}
Label nombreTu nombre
Label teléfonoTeléfono
SubmitLlevarse
Disabled / 409Ese trasto ya no está libre.
DisclaimerUna pieza. No es una reserva. MANTA no es Wallapop.

Success /ok/:code

SlotCopy
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.
OposicionesLas cuatro líneas irrenunciables
VolverVolver a la plaza

Login /login

SlotCopy
TítuloMesa
AyudaSolo regidora.
Demonines@manta.plaza
ErrorEmail o contraseña no valen.

Mesa /mesa

SlotCopy
TítuloMesa
GruposLibre · Pedido · Entregado
Empty tratosNo hay tratos.
SalirSalir
PieDejar el trasto ≠ vender en Wallapop.

5. Alt text de imágenes

AssetAlt (modelo)
heroPlaza de barrio con mantas, luz de domingo, Usera
lamparaLámpara de pie crema en la manta
sillaSilla de enea, ya con pedido
cunaCuna plegable crudo en la manta
maletaMaleta 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

CasoCopy
RedLa red no responde.
404Ese trasto no está.
409Ese trasto ya no está libre.
400 títuloEscribe qué dejas.
401 mesaEntra como regidora.

Sin culpa al usuario. Sin jerga HTTP en UI.

8. Anti-copy (vetado)

VetadoPor qué
Vender / anuncio / precio / SKU / corazónWallapop
Pujar / subasta / timer / pujaSubasta
Reservar / carrito / hold / click & collectIKEA
En ruta / GPS / paradaTROCHA
Gancho / bici / encargo / mecánicaPIÑÓN
Pedir butaca / sesión / taquillaBOBINA
Recibido / En curso / CerradoPREGÓN kanban
Compromiso / despensaCESTA
«El 80% de vecinas…»Estadística inventada
Añadir otra piezaRompe H2

9. Criterios de aceptación de contenido

  1. Las cuatro oposiciones aparecen al menos en success y en una superficie de plaza o dejar/llevarse.
  2. Ningún CTA dice Vender / Reservar / Pujar / Añadir al carrito.
  3. LIBRE se etiqueta «Libre», no «Disponible» retail.
  4. Códigos se muestran como MNT-XXXX en versales.
  5. 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

ParRatio objetivoUso
#1A2B1C sobre #F4F1E8≥ 4.5:1 (texto) / ≥ 3:1 (UI grande)Cuerpo, títulos
#1A2B1C sobre #FFFFFF≥ 4.5:1Texto en card
#3F6B4A sobre #F4F1E8≥ 3:1 para UI; texto de párrafo noFoco, iconos
#F4F1E8 o #FFFFFF sobre #3F6B4A≥ 4.5:1 en CTALabel del botón
#6E7A70 sobre #F4F1E8Verificar; limitar a meta cortaLabels
#C45C4A sobre #F4F1E8Sello / error cortoGeranio; 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

ReglaAplicación
Cuerpo ≥ 16pxNunito Sans 16–17
Display no < 18pxLibre Baskerville solo en titulares
Line-height ≥ 1.5 en cuerpo26–28 lh
Zoom 200%Layout no rompe S-BOTTOM ni form
Sin justificado forzadoAlineación start

4. Targets y pointer

ElementoMínimo
Slots S-BOTTOM44×44 CSS px
CTA Dejar el trasto / Llevarse≥ 44 px alto
Ficha de mantaHit area completa ≥ 44 alto
Inputs≥ 44 alto
Cerrar sheet≥ 44

Spacing entre slots del bottom ≥ 8px. [DECISIÓN]

5. Teclado y foco

SuperficieComportamiento
PlazaTab por S-BOTTOM → fichas LIBRE → Dejar
Sheet llevarseNombre → teléfono → submit; Esc cierra
Form dejarNombre → teléfono → qué es → color → submit
LoginEmail → password → entrar
MesaGrupos legibles; salir alcanzable
Focus visibleOutline 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

UIRol / nombre
S-BOTTOMnavigation · aria-label «MANTA»
Slot activoaria-current="page"
3 datoslist o group «Mantas» · cada dato con texto «{n} libres» no solo el número
Fichas trastoarticle «{title} {color}» + status en texto
Sheetdialog · aria-modal · labelledby título
Formlabel asociado; errores con aria-live="polite"
Loadingaria-busy="true" en región
Success códigoTexto real, no solo imagen
409aria-live="assertive"

7. Imágenes y tile

CasoTratamiento
Tile Derivaalt descriptivo corto o alt="" si puro decorativo y el plano encima lleva el oficio
Covers trastoAlt «{title} {color}»
Iconos S-BOTTOMaria-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

PreferenciaComportamiento
prefers-reduced-motion: reduceTransiciones 0ms; sin parallax del tile; sheet instant
Default120–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).
  • /mesa redirige 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: autocomplete name on; tel tel; password current-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

  1. Ink sobre hueso usado en cuerpo; mute limitado a meta.
  2. Targets S-BOTTOM y CTA ≥ 44×44.
  3. Focus visible mark en todos los interactivos.
  4. Status y métricas con texto, no solo color o número huérfano.
  5. Reduced motion respetado.
  6. Form con labels y errores anunciables.
  7. Ningún toast único sin pantalla como único success (hay /ok/:code).
  8. Sheet llevarse es dialog alcanzable 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

PrincipioAplicación v1
MinimizaciónDejar = nombre + teléfono + título + color; trato = nombre + teléfono + code; sin email, DNI, GPS, precio
Separación público / oficioPlano y POST públicos; mesa JWT
Sin cuenta de vecinaPilar y Amparo no se registran
Transparencia de copySuccess dice que no es venta ni reserva
Secretos fuera del repoDATABASE_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

DatoDóndeBase operativa (modelo)Retención v1
Nombre de quien dejatrastos.donor_namePrestación del merendero (apuntar quién deja)Mientras el seed/demo viva; sin política de mercado afirmada
Teléfono de quien dejatrastos.donor_phoneRecadoIgual
Nombre de tratotratos.nameQuién se llevaIgual
Teléfono de tratotratos.phoneRecado cuando está PEDIDOIgual
Título / colortrastosOficio de la mantaIgual
Email REGIDORAusers.emailCuenta de oficioCuenta demo
Password hashusers.password_hashAuthbcrypt 12
JWT sidsessionsSesión de mesaExpiració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

SuperficiePúblicoPrivado
GET /api/trastosSí · sin nombres ni teléfonos
GET /api/trastos/:codeSí · sin teléfono
POST trastos / tratosSí · crea fila
GET /api/mesaNo · 401Sí · donor + tratos con name + phone
Plaza UISin listar quién dejó
Mesa UILista dejas y tratos

[DECISIÓN] Enumerar teléfonos en el plano rompería privacidad de plaza; solo Nines ve recados.

4. AuthN / AuthZ

ControlDetalle
Passwordbcrypt cost 12 · hash seed canónico del encargo
JWTHS256 · secret env · role claim
Guard mesarole === REGIDORA
Login rateNo es deuda del L1; demo sin brute-force engine
LogoutRevoke session + clear client token
HTTPSObligatorio 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

AmenazaMitigación
POST spam dejar/tratoValidación teléfono + título; L2/L3 rate-limit (no es hueco del slice)
Carrera de dos tratos sobre el mismo LIBRESELECT FOR UPDATE + 409 al segundo
Enumeración de teléfonosNo en API pública
JWT robadoExpiración corta + logout; HTTPS en prod
IDOR mesaGuard JWT; sin IDs de trato públicos
XSSAngular escaping; no innerHTML de name/phone
SQLiParámetros prepared / query builder
Leftover MECANICO / ADMINUn 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 PIIPasswords, JWT completos
code de trasto en logs de dejar/tratoTeléfono completo en logs públicos

9. Criterios de aceptación

  1. GET mesa sin Bearer → 401.
  2. GET trastos no incluye name, phone, donorName ni donorPhone.
  3. POST trastos/tratos no exige auth ni pago ni GPS.
  4. Password solo como hash bcrypt.
  5. .env no versionado con secretos reales.
  6. Copy de success no implica contrato de venta ni de reserva.
  7. 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

TipoMétricaDefinición
North Star% de visitas a plaza que resuelven «¿sigue ahí la lámpara?» sin un WhatsAppOficio 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 descartadaPor qué no
Pageviews de /Vanidad; no mide manta
Ingresos / GMVDejar ≠ vender; no hay e-commerce
% de anuncios publicadosMANTA no es Wallapop
% de pujas cerradasTrueque ≠ subasta
% de holds IKEALlevarse ≠ reservar
% de bicis LISTA sin WhatsAppEso es PIÑÓN
% de noches con butacaEso 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étricaDefiniciónHipótesis
Activación vecina1.er POST /api/trastos o /api/tratos exitosoH2
Tasa plaza → dejar//dejarH1
Tasa plaza → trato/ → 201 tratosH2
Tasa 409POST tratos 409 / intentosIntegridad de una pieza
Mix de estadosConteos LIBRE / PEDIDO / ENTREGADOH1
Integridad auth401 en mesa sin tokenSeguridad
Salud5xx rate APIOps

4. Eventos (contrato si se instrumenta en un L2/L3)

EventoPropsPII
plaza_viewmetrics snapshot (conteos)No
dejar_submitNo nombre, no teléfono
dejar_successcodeNo
trato_submitcodeNo
trato_successcodeNo
trato_conflicthttp:409No
login_successroleNo
mesa_viewNo

[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

VetadoPor qué
Heatmaps de terceros sin decisiónPrivacidad
Funnel de pagoNo hay pago
DAU de WallapopNo hay anuncio
Estadísticas de Usera inventadasÉtica de verdad
Tracking GPSS3 · L2/L3

8. Criterios de aceptación

  1. Docs y UI no muestran un % inventado como hecho.
  2. North star documentada y alineada a H1.
  3. Si hay eventos en un L2/L3, sin PII de tratos.
  4. 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

EntornoURLNotas
API localhttp://localhost:3028Neon fancy-sun-85815074
Web localhttp://localhost:4200Proxy /api
Credencialesnines@manta.plaza / password123Solo demo

3. Smoke crítico (Must pasar)

IDCasoPasosEsperado
S01HealthGET /api/healthok · service: "manta-api"
S02PlanoGET /api/trastos · abrir /4 trastos · 3 métricas · Deriva visible
S03Métricas seedLeer datos2 libres · 1 pedido · 1 entregado
S04409POST /api/tratos { code: "MNT-2802", name, phone }409
S05LlevarseSheet lámpara LIBRE + Pilar + teléfono · submit201 · /ok/MNT-2801 · status PEDIDO
S06Copy successLeer /ok/:code4 oposiciones visibles
S07Dejar/dejar · título + Pilar + teléfono + color · submit201 · /ok/MNT-2805 · LIBRE
S08Login/login NinesJWT · /mesa
S09Mesa authGET /api/mesa con tokenmantas + tratos
S10Mesa 401GET /api/mesa sin token401
S11Mobile/ y /dejar @390S-BOTTOM · 4 mantas · targets
S12SeedTras re-seed2 LIBRE · 1 PEDIDO · 1 ENTREGADO

4. Regresión funcional

IDÁreaCheck
R01POST dejar crea LIBRENuevo trasto status LIBRE
R02POST trato pasa a PEDIDOMNT-2801 deja de ser LIBRE
R03Trato ligadoMesa muestra nombre + teléfono del POST
R04Nombre vacío dejar400 · no navega a ok
R05Teléfono corto400
R06Code inventado/ok/MNT-9999 · 404 UI
R07Guard ruta/mesa sin token → login ?next=
R08LogoutToken limpio · mesa 401
R09S-BOTTOMPlaza / Dejar / Mesa navegables
R10Público sin teléfonosJSON trastos sin phone / name / donor
R11Leftover0 pinon-api / bicis / MECANICO / ganchos en UI
R12409 ENTREGADOPOST trato MNT-2804 → 409
R13Segunda piezaUI no permite carrito ni array de codes

5. Accesibilidad (muestra)

IDCheck
A01Ink sobre hueso en cuerpo (inspección / contraste)
A02Focus visible mark en tab order
A03S-BOTTOM slots ≥ 44×44
A04Status con texto, no solo color
A05prefers-reduced-motion sin parallax
A06Labels en form dejar, sheet y login
A07aria-busy en loading plaza
A08Sheet como dialog

6. Contenido

IDCheck
C01Ningún CTA «Vender» / «Reservar» / «Pujar» / «Añadir al carrito»
C02Eslogan en plaza
C03LIBRE = «Libre» no «Disponible» retail
C04Códigos MNT-XXXX
C05Cuatro oposiciones en success

7. Visual / Paper

IDCheck
V01Tile plaza a sangre + 3 datos + 4 mantas (no hero 2-col, no bento, no feed)
V02Mood botanical (no sepia rastro, no grafito taller)
V03Covers seed cargan (lampara/silla/cuna/maleta)
V04Mesa = mantas por estado (no kanban de columnas)
V05S-BOTTOM no top de taller

8. API negativa

CasoHTTP
Login malo401
Dejar sin nombre400
Dejar sin título400
Trato sin code400
Trato sobre PEDIDO409
Trato sobre ENTREGADO409
Trato code 404404
Mesa sin auth401

9. Datos de prueba

ActorDato
VecinaPilar Ramos · 600123123
Trasto happy LIBREMNT-2801 Lámpara crema
Trasto 409MNT-2802 Silla PEDIDO
Trasto ENTREGADOMNT-2804
Dejar smokeEspejo óvalo · dorado
REGIDORAnines@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

ArtefactoPath
Briefdocs/00-day-brief.md
Paper refdocs/00-paper-reference.md
Productodocs/01-project-definition.md
IA / rutasdocs/03-information-architecture.md
Flujosdocs/04-user-flows.md
Datosdocs/05-data-model.md
Stackdocs/06-tech-stack.md
DS / tokensdocs/08-design-system.md
Copydocs/09-content-guide.md
Builddocs/20-implementation.md
App/Users/cristian/orca/manta-app
GHCriscode2022/manta-app
Paper01M13JZXPYG2GXDC3HWW5K8X6K
API:3028 · manta-api
Neonfancy-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
1Rutas / /dejar /ok/:code /login /mesa
2Home = Deriva H-MAP (tile plaza + 3 datos + 4 mantas), no H-BENTO ni H-FEED ni H-DATA ni hero 2-col
3Chrome S-BOTTOM Plaza · Dejar · Mesa
4F-MKT: llevarse una pieza LIBRE (sheet UI-03); 409 si no LIBRE
5POST dejar público; success con 4 oposiciones
6JWT REGIDORA; mesa 401 sin token
7Seed 4 trastos · 2 LIBRE · 1 PEDIDO · 1 ENTREGADO
8Health manta-api · puerto 3028
9Tokens botanical + Libre Baskerville / Nunito Sans
10Empty / error / loading / 409
11Mobile 390 usable (plaza + dejar)
120 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

UIRutaComponente
UI-01 / 11/PlazaPage
UI-02 / 12/dejarDejarPage
UI-03/ sheetLlevarseSheet
UI-04/ok/:codeOkPage
UI-05/loginLoginPage
UI-06/mesaMesaPage
UI-07 / 08 / 09estadosmismos components
UI-10themeTailwind

4. API checklist

MétodoRutaAuth
GET/api/healthNo
GET/api/trastosNo
GET/api/trastos/:codeNo
POST/api/trastosNo · dejar
POST/api/tratosNo · llevarse · 409
POST/api/auth/loginNo
GET/api/mesaJWT 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

ItemValor
Emailnines@manta.plaza
Passwordpassword123
Hash$2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
CodesMNT-2801…2804
Covers/assets/trastos/{lampara,silla,cuna,maleta}.jpg

6. Anti-patrones de implementación

No hacerHacer
Puerto 3027 / health pinon-api3028 / manta-api
Tabla bicis / requests / ganchostrastos / tratos / mantas
Top S-TOPS-BOTTOM
Bento H-BENTOPlano Deriva H-MAP
Kanban mesaMantas por estado
Pago / Stripe / anuncioPOST nombre + teléfono
GPS / MapboxFuera · L2/L3
Hero 2-col marketingDeriva foto-led
Carrito / array de codesUna pieza · 409
/encargo leftover/dejar + sheet

7. Assets

Copiar desde case:

  • assets/trastos/lampara.jpg
  • assets/trastos/silla.jpg
  • assets/trastos/cuna.jpg
  • assets/trastos/maleta.jpg
  • assets/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)

PreguntaDefault 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

FaseNombreIntención
L1Slice actualPlano + dejar + llevarse + mesa JWT · cerrado en esta iteración
L2/L3Nice-to-have de otro productoSolo 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)

PiezaEstado
H-MAP Deriva 4 mantas + 3 métricasMust · cerrado
Dejar el trasto sin cuentaMust · cerrado
F-MKT llevarse una pieza + 409Must · cerrado
Success + 4 oposicionesMust · cerrado
Login REGIDORAMust · cerrado
Mesa de mantas LIBRE / PEDIDO / ENTREGADOMust · cerrado
Empty / error / loading / 390Must · cerrado
Docs 00–20 + README + executiveMust · cerrado
Paper 12 UX + 12 UI (inventario)Must (ref) · cerrado
Contrato manta-app · API :3028 · health manta-apiMust · 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)

IDIdeaPor qué L2/L3Riesgo
L2-01Pagos / escrow / precioRompe S3; huele a Wallapop (dejar ≠ vender)Marketplace disfrazado
L3-01GPS del trasto / aviso de llegadaRompe 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ípicoRespuesta
«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

DependenciaNota
Neon fancy-sun-85815074L1 (DATABASE_URL)
Paper file 01M13JZXPYG2GXDC3HWW5K8X6KDiseño; inventario en 00
manta-app · GH Criscode2022/manta-appContrato de build (doc 20)

6. Criterios para abrir un L2/L3

  1. Smoke L1 en verde (doc 13).
  2. Copy irrenunciable intacto.
  3. El brief L2/L3 nombra pagos o GPS sin reabrir plano, F-MKT de una pieza ni mesa.
  4. 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

TokenValor
Duración corta120–160ms
Easingease-out
Reduced motion0ms
Target≥44×44
Pendingcontrol 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

GestoResultado
Primera cargaLoading (UI-09): skeleton tile + 3 datos + 4 fichas card; aria-busy
200 con 4Tile de plaza a sangre + 3 datos + 4 mantas. Título, color, estado
200 con 0UI-07 empty «Aún no hay mantas.»
Error 5xx / redUI-08 + Reintentar (repite GET trastos)
Tap manta LIBREAbre sheet llevarse (UI-03)
Tap manta PEDIDO / ENTREGADOSello; 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 desktopRing 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)

GestoResultado
CargaForm vacío; submit disabled si faltan campos
Nombre / teléfono / qué es / color vacío + submitError de campo · no POST
Submit válidoPOST /api/trastos · pending en botón
201/ok/:code con dejado: true
400mark/geranio + mensaje de campo
Redseal + 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

GestoResultado
Abrir desde LIBRESheet dialog · código + título solo lectura
Esc / cerrarVuelve al plano; foco al pin
Submit válidoPOST /api/tratos · pending
201/ok/:code con trato: true · trasto PEDIDO
409«Ese trasto ya no está libre.» · no navega a ok
400Campos
RedReintentar en sheet

AC: una sola pieza. Cero carrito. Cero segunda línea. Cero hold IKEA.


5. Success (UI-04)

GestoResultado
Entrada desde dejar 201«Dejado.» + código MNT-XXXX + 4 oposiciones
Entrada desde trato 201«Trato.» + código + 4 oposiciones
Tap Volver/
Deep link directoGET /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)

GestoResultado
Submit válidoPOST login · guarda JWT · /mesa o next
401«Email o contraseña no valen.»
Guest en /mesaRedirect /login?next=/mesa

AC: sin signup. Ayuda demo mute.


7. Mesa REGIDORA (UI-06)

GestoResultado
Primera cargaLoading skeletons grupos + tratos
200Mantas LIBRE / PEDIDO / ENTREGADO + tratos (name, phone, code, hora)
Empty tratos«No hay tratos.»
401Redirect login
SalirLimpia token → /
Tap filaSin /mesa/:code en v1; lectura

AC: no columnas Recibido / En curso. No PATCH estado. No split lista|ficha. No mapa. ENTREGADO se lista.


8. S-BOTTOM · chrome

GestoResultado
Tap Plaza/
Tap Dejar/dejar
Tap MesaAuth → /mesa; guest → login
ActivoMark + aria-current
IdleMute

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)

EstadoUI
LoadingPulse card; aria-busy
Empty plazaDisplay + mute + sin CTA de Wallapop
Empty mesa tratosMute
Error redTitular + Reintentar mark
409Geranio sello + copy «ya no está libre»

10. Motion

GestoDefaultReduced
Aparición planoFade 140msInstant
Hover ring120msInstant
SheetSlide-up 160msInstant
Tile plazaEstáticoEstático

Sin Ken Burns agresivo sobre Deriva. [DECISIÓN]


11. Guión de interacción demo

  1. / loading → tile + 3 datos + 4 mantas.
  2. Leer MNT-2801 LIBRE / MNT-2802 PEDIDO.
  3. Tap lámpara → sheet Pilar → pending → success Trato.
  4. Tap silla → 409.
  5. Dejar → form → success Dejado.
  6. S-BOTTOM Mesa → login → mesa con MNT-2801 PEDIDO.
  7. 390: S-BOTTOM no tapa CTA; sheet por encima; scroll con padding.

12. Criterios de aceptación de interacción

  1. F-MKT no abre carrito ni segunda pieza.
  2. POST trato no-LIBRE no navega a ok (409).
  3. Pending no doble-envía.
  4. S-BOTTOM siempre alcanzable en 390.
  5. Focus visible en todo el recorrido teclado.
  6. Sheet es dialog; Esc cierra.

17-prototype-map.md

17 — Mapa de prototipo — MANTA

1. Fuentes

FuenteID / path
Paperhttps://app.paper.design/file/01M13JZXPYG2GXDC3HWW5K8X6K
File ID01M13JZXPYG2GXDC3HWW5K8X6K
UX-count12
UI-count12
App/Users/cristian/orca/manta-app
Case assets2026-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

UXNombreDoc espejo
UX-00CoverREADME · executive · 07
UX-01Stakeholders02 §3
UX-02Personas02 §4
UX-03JTBD02 §5
UX-04Stories02 §6
UX-05Journey02 §7 · 04
UX-06Blueprint02 §8
UX-07Site map03
UX-08Flujos04
UX-09Datos+permisos05 · 01 §5 · 11
UX-10Métricas12
UX-11Research02

3. UI producto → rutas / componentes

UINombreRutaComponente Angular
UI-01Plaza Deriva/PlazaPage
UI-02Dejar/dejarDejarPage
UI-03Llevarse/ sheetLlevarseSheet
UI-04Success/ok/:codeOkPage
UI-05Login/loginLoginPage
UI-06Mesa/mesaMesaPage
UI-07Emptymismas rutasestados
UI-08Errormismas rutasestados · 409
UI-09Loadingmismas rutasestados
UI-10Tokens— (theme)Tailwind config / styles
UI-11Mobile plaza/ @390PlazaPage
UI-12Mobile dejar/dejar @390DejarPage

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

CodeTrastoColorEstadoCover asset
MNT-2801Lámpara de piecremaLIBREtrastos/lampara.jpg
MNT-2802Silla de eneamaderaPEDIDOtrastos/silla.jpg
MNT-2803Cuna plegablecrudoLIBREtrastos/cuna.jpg
MNT-2804Maleta rígidaverdeENTREGADOtrastos/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

ArtboardAncho 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ódigoEvidencia en UI
R-CLMerendero clásico (S-BOTTOM, mantas, wordmark Baskerville)
S-BOTTOMPlaza · Dejar · Mesa en UI-01 / 11 / 02 / 06
H-MAPUI-01 Deriva: tile plaza + 3 datos + 4 mantas
F-MKTUI-03 una pieza, sin carrito

8. Gaps conscientes

GapNotas
Pagos / GPSL2/L3 · no son huecos del prototipo L1
PATCH de estadoFuera · mesa de lectura
Analytics en prototipoModelo 12
Densificación PaperGate del mismo día · 00 placeholder

Ningún gap es producto in-scope aplazado. [DECISIÓN]

9. Criterios de aceptación del mapa

  1. Cada UI-01…12 tiene fila en esta tabla.
  2. Cada ruta Must tiene artboard.
  3. No hay artboard de /encargo, /carrito, /subasta, GPS o anuncio.
  4. Mobile 390 cubierto (UI-11, UI-12).
  5. 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.

PiezaEstado
Docs 01–20 + README + executiveOK (este set)
00-day-briefIntactos (fuente de verdad)
00-paper-referenceOK · UX-count 12 · UI-count 12 · placeholder hasta gate
Paper 12 UX + 12 UIInventario en 00 · file 01M13JZXPYG2GXDC3HWW5K8X6K
App path /Users/cristian/orca/manta-appOK · GH Criscode2022/manta-app
API :3028 · health manta-apiContrato
Código trastos + tratos + JWT REGIDORAContrato doc 20
Cierre sin deuda del L1OK · roadmap solo L2/L3 pagos / GPS

2. Terna y diversidad

CheckEvidencia
R-CL · S-BOTTOM · H-MAP · F-MKTBrief + 01 + 07
0 códigos = PIÑÓNPIÑÓN era R-HY · S-TOP · H-BENTO · F-CMP
≥2 vs BOBINA / LOMOBottom/Map/Mkt vs dock/feed/story y cmd/data/lead
S-BOTTOM, H-MAP, F-MKT no en últimos 5Brief
Ground G-BONE #F4F1E800 + 07 + Tailwind
No leftover PIÑÓN0 bicis / MECANICO / pinon-api / ganchos en el contrato
Mood botanical ≠ sepia rastro07
H-MAP ≠ DERIVAF-MKT de un objeto, no F-MAP de ruta
L1 no L2 consecutivoBrief

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

APMitigación
AP-12 hero 2-colH-MAP Deriva tile + 3 datos + 4 mantas
AP-21 card huecaTítulo/color/estado visibles
Leftover como estadoContrato MANTA; no se anota PIÑÓN como producto vivo
Entrevistas inventadas02 etiquetado
bicis/MECANICO/pinon-api/ganchos0 en dominio; 05 + 20
H-BENTO / S-TOP / F-CMPPlano + S-BOTTOM + F-MKT
H-FEED / S-DOCKPlano + S-BOTTOM
H-DATA / S-CMDNo mesa de datos ni comando
Carrito F-MKTUna pieza · 409
KanbanMesa de mantas
Pagos / GPS en L1S3 · solo L2/L3
Estadísticas inventadasEtiquetas [HIPÓTESIS]/[SUPUESTO]
Roadmap con deuda L1Doc 15 solo pagos / GPS

5. Seed

4 trastos · 2 LIBRE · 1 PEDIDO · 1 ENTREGADO · Nines REGIDORA · Pilar sin cuenta · Amparo fuera de login.

codetitlecolorstatus
MNT-2801Lámpara de piecremaLIBRE
MNT-2802Silla de eneamaderaPEDIDO
MNT-2803Cuna plegablecrudoLIBRE
MNT-2804Maleta rígidaverdeENTREGADO

Métricas: libres 2 · pedidos 1 · entregados 1.

6. Assets

ArchivoPresente
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

ArchivoEstado
README.mdOK
presentation/executive-summary.mdOK
docs/00-day-brief.mdPreexistente
docs/00-paper-reference.mdOK
docs/01 … docs/20OK

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)

EjeScoreNota
Diversidad5Merendero nuevo; L1 no L2; no taller/bento/top
Docs4Suite 00–20 + brief + presentation
Paper craft UI512 UI tokens/plaza Deriva/dejar/llevar/success/login/mesa/empty/error+loading + 2 mobile
Paper UX process512 UX
Media5Hero plaza + 4 trastos (lámpara/silla/cuna/maleta)
Canvas org5Bandas §1–§3 origen 0,0
Código E2E5GET trastos + POST tratos 201/409 + JWT REGIDORA; ng build; thumb no negro
Paridad app4S-BOTTOM + H-MAP Deriva + tokens G-BONE
Unicidad estructura5R-CL · S-BOTTOM · H-MAP · F-MKT
Cierre admin5Registry+Excel+GitHub+Paper gate+portfolio UI-01
Media~4.8

Gate: node scripts/check-paper-reference.mjs 2026-08-28-mantaOK 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

EstadoSignificado
DoneDefinido y aceptado en la suite ALS L1 (esta iteración)
Won’t L1Fuera; 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ÍtemEstado
A1Deriva tile plaza a sangre + 3 métricas + 4 mantasDone
A2Ficha: título, color, statusDone
A3Tap LIBRE → sheet llevarseDone
A4Empty / loading / errorDone
A5Mobile 390 + assets coversDone
A6Búsqueda comando /buscarWon’t L1 (≠ LOMO)
A7Bento de ganchosWon’t L1 (≠ PIÑÓN)
A8Feed de nochesWon’t L1 (≠ BOBINA)

3. Épica B — Dejar

IDÍtemEstado
B1/dejar · name + phone + título + colorDone
B2POST público 201 / 400Done
B3Crea trasto LIBREDone
B4/ok/:code + 4 oposicionesDone
B5Precio / anuncio / WallapopWon’t L1 (≠ vender)
B6Signup vecinaWon’t L1 (S2)

4. Épica C — Llevarse F-MKT

IDÍtemEstado
C1Sheet una pieza sobre /Done
C2POST /api/tratos → PEDIDODone
C3409 si no LIBREDone
C4Copy llevarse ≠ reservar IKEADone
C5Carrito / multi-pieza / holdWon’t L1 (H2)
C6Subasta / pujaWon’t L1

5. Épica D — Mesa REGIDORA

IDÍtemEstado
D1Login JWT NinesDone
D2/mesa LIBRE / PEDIDO / ENTREGADODone
D3GET mesa 401 sin tokenDone
D4LogoutDone
D5Tratos + donors con name + phoneDone
D6Kanban columnasWon’t L1 (≠ PREGÓN)
D7PATCH estado / ficha pedidoWon’t L1 (mesa de lectura)

6. Épica E — Chrome S-BOTTOM

IDÍtemEstado
E1Bottom Plaza · Dejar · MesaDone
E2aria-current + targets 44Done
E3Mesa guest → loginDone
E4Top PIÑÓN / dock BOBINA / comando LOMOWon’t L1

7. Épica F — Design system & a11y

IDÍtemEstado
F1Tokens hueso/ink/card/mark/mute/geranioDone
F2Libre Baskerville + Nunito SansDone
F3Contraste ink/hueso AADone
F4Reduced motionDone
F5Modo letra grande AmparoWon’t L1 (corte a11y, no deuda)

8. Épica G — Plataforma

IDÍtemEstado
G1Nest :3028 · health manta-apiDone
G2Neon fancy-sun-85815074 schema+seedDone
G3Angular rutas + guardDone
G4pnpm apps independientesDone
G5GPS / MapboxWon’t L1 · L2/L3
G6Pagos / StripeWon’t L1 · L2/L3

9. Épica H — Documentación & diseño

IDÍtemEstado
H1docs 00–20 + README + executiveDone
H2Paper UX 12 + UI 12 inventarioDone
H3File 01M13JZXPYG2GXDC3HWW5K8X6KDone (ref · placeholder hasta gate)

10. Orden de build (mismo alcance, no roadmap)

  1. Schema + seed + health
  2. GET trastos + PlazaPage Deriva
  3. DejarPage + POST trastos
  4. LlevarseSheet + POST tratos + 409
  5. OkPage copy
  6. Auth + MesaPage
  7. S-BOTTOM + 390 + empty/error/loading
  8. 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

TipoCount (aprox)
Done L1~40
Won’t L1 / L2/L3pagos, GPS + analogías vetadas
Docs DoneSuite completa

No se inventan story points ni velocidades de equipo. [DECISIÓN]

20-implementation.md

20 — Implementación — MANTA

1. Resumen ejecutivo técnico

CampoValor
App path/Users/cristian/orca/manta-app
GHCriscode2022/manta-app
APINestJS · puerto 3028 · prefijo /api
WebAngular standalone · puerto 4200
Packageapps independientes (pnpm --filter)
DBNeon PostgreSQL · project fancy-sun-85815074 (DATABASE_URL)
Tablasusers, trastos, tratos, sessions
AuthJWT Bearer · role REGIDORA (/mesa); plano y POST públicos
DominioUser, Trasto, Trato
Fecha2026-08-28
Healthmanta-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

RolEmailPassword
REGIDORAnines@manta.plazapassword123

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:

  1. CREATE TABLE de users, sessions, trastos, tratos (doc 05).
  2. Índices: trastos(code), trastos(status), trastos(sort_order), users(email), tratos(trasto_id), tratos(created_at DESC).
  3. Seed idempotente:
    • upsert REGIDORA nines@manta.plaza (hash bcrypt canónico)
    • upsert trastos por code (MNT-2801MNT-2804) restaurando status, color, cover, donor
    • upsert 2 tratos seed (Lola Méndez / Toni Vega)
  4. Dominio: solo trastos + tratos + users. [DECISIÓN]

Upsert de trastos por code restaura status de catálogo para que el guión sea repetible. [DECISIÓN]

POST de dejar genera código nuevo (MNT-2805+). POST de trato reutiliza el code del trasto.

Tablas (recordatorio)

TablaContenido
usersREGIDORA Nines Ortega
trastos4 mantas (+ las del POST dejar)
tratosLlevarse (seed PEDIDO/ENTREGADO + POST)
sessionssid + expires_at

DROP leftover bicis, requests, sesiones, ejemplares si existen en el mismo Neon. [DECISIÓN] El project es de MANTA.

Seed SQL (modelo)

codetitlecolorstatuscover
MNT-2801Lámpara de piecremaLIBRE/assets/trastos/lampara.jpg
MNT-2802Silla de eneamaderaPEDIDO/assets/trastos/silla.jpg
MNT-2803Cuna plegablecrudoLIBRE/assets/trastos/cuna.jpg
MNT-2804Maleta rígidaverdeENTREGADO/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 === REGIDORA protege /mesa.
  • Públicos: health, trastos, trastos/:code, POST trastos, POST tratos, login.

Oficio

MétodoRutaAuthNotas
GET/api/healthNo{ ok: true, service: "manta-api" }
GET/api/trastosNometrics + sort_order asc sin name/phone/donor
GET/api/trastos/:codeNoitem público
POST/api/trastosNoINSERT trasto LIBRE; 400 si title/name/phone/color inválidos
POST/api/tratosNoUPDATE PEDIDO + INSERT trato; 409 si no LIBRE
GET/api/mesaJWTmantas 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

PathComponentGuard
''PlazaPage
dejarDejarPage
ok/:codeOkPage
loginLoginPage
mesaMesaPageauthGuard
**redirect ''

Servicios

ServiceResponsabilidad
TrastosApiGET list/detail · POST dejar
TratosApiPOST tratos (captura 409)
AuthApilogin, token store, logout
MesaApiGET mesa con Bearer
BottomNavStateslot activo

UI Must

  1. PlazaPage — tile + 3 datos + 4 mantas (Deriva), no bento ni tabla.
  2. LlevarseSheet — F-MKT una pieza.
  3. DejarPage — form público.
  4. OkPage — código + 4 oposiciones.
  5. LoginPage / MesaPage.
  6. BottomNavComponent — S-BOTTOM.
  7. 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.jpg
  • silla.jpg
  • cuna.jpg
  • maleta.jpg

hero.jpg → tile Deriva (/assets/hero.jpg).

Paths en DB alineados a /assets/trastos/.... [DECISIÓN]

7. Checklist anti-leftover

Prohibido en runtimeSustituto
pinon-apimanta-api
puerto 30273028
bicis / requests / ganchostrastos / tratos / mantas
MECANICOREGIDORA
PIN-XXXXMNT-XXXX
/encargo/dejar + sheet
ESPERA/EN_TALLER/LISTALIBRE/PEDIDO/ENTREGADO
Spectral / Sora industrialLibre Baskerville / Nunito Sans botanical
G-GRAPHITE #2C3033G-BONE #F4F1E8
S-TOP Taller · Encargo · MesaS-BOTTOM Plaza · Dejar · Mesa

8. DoD técnico (merge)

  1. Smoke S01–S12 (doc 13) en verde.
  2. Health manta-api.
  3. Seed idempotente.
  4. Mesa 401 sin token.
  5. POST trato no-LIBRE → 409.
  6. Success muestra las 4 oposiciones.
  7. 390 + S-BOTTOM usable.
  8. 0 referencias de producto a bicis/MECANICO/pinon-api/ganchos.
  9. 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.