Un e-commerce completo, construido en 6 días
PhonEcommerce es una tienda online de teléfonos móviles, full-stack: catálogo con filtros, carrito, checkout en tres pasos, historial y cancelación de órdenes, perfil con direcciones y un panel de administración. El frontend es Next.js 16 con React 19, Zustand y Tailwind CSS 4; el backend, Fastify 5 sobre PostgreSQL con Prisma.
Es un proyecto 100% propio: 41 commits, todos míos, sin fork ni upstream que acreditar. El primer commit es del 2026-05-06 y el último del 2026-05-11 — una ventana de 6 días de punta a punta, ya incluido el panel admin.
Ese número es el que obliga a explicar dos cosas, y son las dos zonas que siguen: cómo está armado el backend (Clean Architecture por features, con tres ADRs escritos) y cómo se organizó el trabajo (un flujo multiagente con agentes especializados por dominio). El primero es lo que sostiene el proyecto; el segundo es lo que explica el calendario.
Cuatro capas, una vez por feature — no una vez por proyecto
El backend no está organizado por tipo de archivo (controllers/, services/, models/) sino por
feature, y dentro de cada feature aparecen las cuatro capas de Clean Architecture. El primer commit
del repo ya lo dice en su mensaje —“initial project setup with Clean Architecture backend and
feature-based frontend”—, así que no es algo que se acomodó después: es el punto de partida.
backend/src/<feature>/
domain/ ← entidades e interfaces, sin dependencias externas
application/ ← use-cases
infrastructure/ ← repositorios Prisma
presentation/ ← controllers y routes FastifyLa dirección de las dependencias es lo que hace que esto valga la pena. domain/ no importa nada de
afuera: define las entidades y, sobre todo, las interfaces de los repositorios. application/
contiene los use-cases y depende únicamente de esas interfaces. Recién en infrastructure/ aparece
Prisma, implementándolas, y en presentation/ aparece Fastify. El resultado es que ni el ORM ni el
framework HTTP están tocando las reglas del negocio: son detalles enchufados en los bordes.
Que el corte primario sea la feature y no la capa es la decisión propiamente dicha, y está escrita
como ADR: docs/decisions/001-clean-architecture-by-features.md. Cada feature funciona como un contexto
acotado con sus cuatro capas adentro, así que todo lo que hace falta para tocar “stock” o “órdenes” vive
junto, en vez de repartido en cuatro carpetas lejanas del árbol.
Tres decisiones escritas, no tres decisiones recordadas
El repo trae docs/decisions/ con tres ADRs: 001-clean-architecture-by-features.md, 002-jwt-with-refresh-tokens.md y 003-prisma-postgresql.md. Escribirlos es lo que separa una arquitectura elegida de una arquitectura heredada de un tutorial: cada uno deja registrado qué se decidió y por qué, y sirve de referencia cuando aparece la tentación de romper la regla por comodidad.
El costo: mucha más ceremonia por endpoint
Cuatro capas por feature significa que agregar una operación trivial toca varios archivos —entidad e interfaz en domain, use-case en application, repositorio en infrastructure, controller y route en presentation— donde un CRUD directo contra Prisma habría sido un archivo. Es el precio explícito de esta arquitectura, y se paga en cada feature nueva. Lo que se compra a cambio se ve en la zona de testing.
El frontend sigue el mismo criterio de corte, aunque sin las capas: features/<feature>/ con sus
components, hooks, services y types, shared/ para lo reutilizable entre features, y app/ para las
rutas del App Router de Next.js.
Agentes especializados por dominio, con firma en el TODO
Los 6 días no salen de trabajar más horas: salen de cómo se repartió el trabajo. El proyecto se construyó
con un flujo multiagente propio — el repo trae su propia carpeta .agents/ (agents, skills,
workflows), el mismo patrón con el que está hecho este portafolio.
La evidencia más concreta está en docs/TODO.md, donde las entradas vienen firmadas por el agente que
las agregó:
Agregado por: agente-principal - 2026-05-06
agregado por: agente-backend-stock - 2026-05-06No es una anécdota de proceso: es exactamente el mismo corte que la arquitectura. Hay un
agente-principal que coordina y agentes especializados por dominio —agente-backend-stock es el que
quedó firmado— trabajando cada uno sobre su feature. Que el backend esté cortado por bounded context es
lo que hace posible que varios frentes avancen sin pisarse: si el corte hubiera sido por capa, cualquier
feature nueva habría tocado las mismas cuatro carpetas que todas las demás.
Dicho de otro modo: la arquitectura de la zona anterior no es solo una decisión de código, también es la que habilitó la forma de trabajo — y el calendario que salió de ella.
Tienda completa y panel de administración, no una demo de catálogo
El alcance no se quedó en la vidriera. Estas son las funcionalidades que el proyecto tiene terminadas, según el README del repo:
Catálogo con filtros
El listado de productos con filtrado, que es la puerta de entrada de la tienda.
Checkout en 3 pasos
El flujo de compra dividido en tres etapas, en vez de un formulario único.
Historial y cancelación de órdenes
El cliente ve sus compras anteriores y puede cancelar una orden — la parte de post-venta que suele quedar afuera de un proyecto de práctica.
Perfil con direcciones
Cuenta de usuario con gestión de direcciones de envío.
Panel admin
CRUD de productos, marcas y categorías; control de stock con historial de movimientos; y gestión de órdenes.
El panel admin es la mitad que decide si esto es una tienda o una maqueta: sin CRUD de catálogo ni control de stock, el catálogo del cliente sería contenido fijo. Acá el stock además guarda historial de movimientos, no solo el número actual.
34 tests en el backend, cero en el frontend, sin CI
Acá se cobra la ceremonia de las cuatro capas. Con los use-cases dependiendo de interfaces y no de Prisma, cada capa se puede testear aislada sin levantar una base de datos: el backend tiene 34 archivos de test corriendo con Vitest.
El otro lado del número es igual de real: el frontend tiene 0 tests, y no hay CI — no existe
.github/ en el repo, así que esos 34 tests corren cuando alguien los corre a mano, no en cada push.
Están escritos, no automatizados.
Lo digo tal cual porque el caso no mejora escondiéndolo: en 6 días se priorizó cubrir la lógica de negocio del backend, que es donde una regresión rompe datos, y quedó afuera todo lo demás. Es un proyecto real con su recorte real, no uno idealizado.
Lo que queda de haber decidido antes de escribir
La autenticación es el ejemplo más chico y más claro de cómo funcionó esto: JWT con access token de 15
minutos más refresh token con rotación, decidido y escrito en docs/decisions/002-jwt-with-refresh-tokens.md
antes de existir como código. La rotación no es lo que sale por defecto de un tutorial de JWT — es una
decisión que se toma sabiendo qué se está mitigando.
El proyecto está finalizado: 41 commits propios, 6 días, un backend con Clean Architecture por features y tres ADRs, un flujo multiagente que lo construyó y un producto completo hasta el panel admin. Lo que me llevo es que las dos mitades se sostienen entre sí: la arquitectura por bounded context es lo que hizo posible repartir el trabajo entre agentes, y ese reparto es lo que explica el calendario. Ninguna de las dos, sola, da 6 días.