--- name: web-layer-builder description: Construye la capa web (front + back ligero) que acompaña a la solución WxO. Soporta dos happy-paths: FastAPI+HTMX (estilo Cotemar — demos rápidas, control plane SSR) y FastAPI+React+Vite (estilo Dun — apps productivas). Incluye widget embed WxO, vista de trazas observable, polling pattern. --- # Web Layer Builder Tu trabajo es **construir la capa web** de la solución: la app/landing/panel que el usuario humano va a usar para ver lo que el agente está haciendo. ## Dos modos ### Modo A — FastAPI + HTMX + Jinja (default) **Cuándo:** demos, control planes, kanbans, paneles operativos, dashboards. **Ventajas:** SSR (no build), polling con `hx-trigger` trivial, fácil de mantener por una persona. **Estructura:** ``` web/ ├── Dockerfile ├── app/ │ ├── main.py │ ├── routers/ │ │ ├── pages.py ← rutas que devuelven HTML │ │ ├── api.py ← endpoints JSON (traces, etc.) │ │ └── partials.py ← fragmentos HTMX │ ├── templates/ │ │ ├── base.html ← layout │ │ ├── index.html ← landing con embed WxO │ │ ├── traces.html ← timeline observable │ │ └── _*.html ← partials HTMX │ ├── static/ │ │ ├── css/ │ │ └── js/ │ └── db.py ← SQLite para audit_logs / traces └── requirements.txt ``` ### Modo B — FastAPI + React + Vite + Tailwind **Cuándo:** apps productivas con varios usuarios, mucha interacción, UI rica. **Ventajas:** ecosistema React, state management decente, lazy loading. **Estructura:** ``` web/ ├── backend/ ← FastAPI (puede coincidir con backend-tool-builder) └── frontend/ ├── Dockerfile ← multi-stage: build + nginx ├── package.json ├── vite.config.ts ├── tailwind.config.js ├── nginx.conf ← reverse-proxy /api → backend └── src/ ├── main.tsx ├── App.tsx ├── pages/ ├── components/ ├── hooks/ │ ├── usePolling.ts ← pattern correcto │ └── useDownload.ts ← downloadAuthenticated ├── stores/ ← zustand ├── lib/ │ ├── api.ts │ └── auth.ts └── styles/ ``` ## Patrones obligatorios (ambos modos) ### 1. Embed del chat WxO En la página principal: ```html
``` Recordatorio: WxO Console → Embed Security → **Off** (issue I-007). ### 2. Vista de trazas observable - `GET /traces` página timeline filterable (filtros: agent, tool, fecha) - `GET /api/traces/recent?since=ISO` JSON endpoint - Polling cada 2s para nuevas trazas - Tabla SQLite con índices `(started_at, agent_caller, tool)` - `POST /api/traces` recibe trazas del decorator `@observable_tool` ### 3. Polling correcto (issue I-016) **Modo A (HTMX):** ```html