Skip to content
Tommy CardeLo
Go back

Versavi — Una tienda para aretes de madera pintados a mano, sin framework y sin paso de build

Una tienda estática para Versavi, una pequeña marca de aretes de madera pintados a mano: HTML, CSS y JS planos sin paso de build, un catálogo tipo “guía de campo” por estaciones, un carrito que envía un solo correo prefabricado y formularios en n8n con los que la dueña agrega, edita y borra piezas por su cuenta.

Sitio: versavi.store


El problema

Una marca artesanal de una sola persona vive en Instagram, pero Instagram es un mal catálogo. No hay precios estables, no se puede explorar por temática y cada venta empieza con un hilo de mensajes directos. La dueña necesitaba tres cosas: un lugar al que dirigir a la gente, una forma de recibir pedidos sin que yo estuviera en medio y una manera de seguir ampliando el catálogo sin pagarme por cada par de aretes nuevo.

Las restricciones lo definieron todo. El tráfico es pequeño, el presupuesto es casi cero y quien mantiene el contenido es una artista, no una desarrolladora. Así que la pregunta real nunca fue “qué framework”, sino “cuál es la mínima maquinaria que aún se sienta como una marca cuidada”.

Qué hace

Arquitectura

Navegador
  index.html / shop.html / product.html
    ├─ catalog-data.js   JSON estricto: slug, nombre, precio, estación, fotos/diseños
    ├─ catalog.js        tarjetas + reveal + control de caché
    ├─ cart.js           localStorage → un pedido por mailto:
    └─ garden.js         hero de cuatro estaciones, guiado por el scroll

Dueña (teléfono)
  formulario n8n ──► valida ──► reduce fotos a webp
                 ──► un solo commit a main (fotos + catalog-data.js + sitemap.xml)
                          │
                          ▼
        GitHub Actions ──► Firebase Hosting (dominio propio, SSL)

Todo el sitio es una carpeta de archivos estáticos. No hay bundler, ni gestor de paquetes, ni dependencias que actualizar. El catálogo es un único arreglo JSON asignado a window.VERSA_RAW, y todas las páginas se renderizan a partir de él.

Decisiones de diseño clave

1. Archivos estáticos, a propósito

Para un sitio de este tamaño, un framework añadiría sobre todo cosas que pueden romperse. HTML estático en el plan gratuito de Firebase Hosting no cuesta nada, responde rápido y no hay nada que parchear. Medí una visita completa a la home en aproximadamente 1 MB, lo que cabe de sobra en la cuota gratuita para el tráfico que esta marca puede esperar. El camino de salida es claro: pasar a un plan de pago solo si necesito un backend, por ejemplo para pagos reales, o si el tráfico se acerca al límite.

2. Dirección de diseño: una guía de campo por estaciones

La marca pinta sobre pequeños círculos de madera, y las piezas se agrupan de forma natural por estación (fruta y mar en verano, flores en primavera). Así que el sitio se volvió una guía de campo de un jardín: cada pieza aparece como un espécimen sobre el color de su estación, recortada en el círculo de madera y con una etiqueta colgante.

Mantuve la paleta y la tipografía originales (verde azulado, terracota y crema, Baloo 2 con Nunito Sans) en lugar de rediseñar alrededor del logo. Fue un compromiso deliberado: la clienta ya había aprobado ese aspecto, y un sitio coherente vale más que uno teóricamente mejor que haya que aprobar de nuevo. La última pasada de rediseño quitó cosas que se habían ido acumulando, como una marquesina y algunas criaturas decorativas, y dejé etiquetada la versión anterior en git para poder recuperar cualquier parte.

3. Los pedidos salen como un correo, no por un checkout

Un checkout real implica un proveedor de pagos, un backend y trabajo de cumplimiento normativo. Para una vendedora que confirma envío y pago personalmente, nada de eso se justifica todavía. El carrito reúne las piezas, el nombre del cliente, un contacto y una dirección opcional, y arma un solo mensaje mailto:. La dueña responde con el total final y sus opciones de pago.

Es honesto con sus límites: la página avisa de que se abrirá la aplicación de correo y muestra la dirección como alternativa si no se abre. El carrito también sobrevive a navegadores que bloquean el almacenamiento: recurre a la memoria en lugar de lanzar un error.

4. Que la dueña publique sin mí

Lo más útil no fue visual. Reemplacé el “envíame las fotos y yo las subo” por dos formularios en n8n: uno para subir una pieza (nombre, precio, estación, descripción y de 1 a 6 fotos) y otro para editar o borrar las existentes. Cada envío valida los datos, convierte las fotos a webp de tamaño acotado (corrigiendo la orientación del teléfono) y hace un solo commit a main mediante la API de GitHub. Ese commit incluye las imágenes, el catálogo actualizado y el sitemap, y el CI lo despliega.

Un commit por cambio mantiene el historial legible y hace que cada cambio sea reversible. También impuso una regla que me gusta: catalog-data.js debe seguir siendo JSON estricto, porque lo escribe una máquina además de una persona. Del lado del sitio, build() descarta cualquier pieza con slug, precio o estación inválidos y registra una advertencia, de modo que una entrada errónea no pueda tumbar la página. Las fotos se guardan en caché una semana, así que cada edición añade un parámetro de versión a las URL de las imágenes.

5. Un inventario de placeholders para el contenido real

La primera versión salió con recuadros rayados de “foto pendiente”, un “número por confirmar” en el pie de página y precios que yo había inventado para el diseño. Si se dejan solos, los placeholders terminan en producción. Por eso los traté como un inventario: un documento que lista cada placeholder, dónde aparece en el sitio y la pregunta o el archivo exacto que hace falta para reemplazarlo (canales de contacto, datos de la biografía, precios reales, envíos y pagos, devoluciones, además de una lista de fotos con notas técnicas para quien las tome).

Cuando llegaron las respuestas, las apliqué de una sola vez: un catálogo real, condiciones reales de envío y pago, y el alcance verdadero del trabajo de la marca. Más tarde eliminé por completo los recuadros de “foto pendiente” del sitio en vivo, de modo que el contenido sin terminar se oculta en lugar de verse roto. Dos vacíos quedan a propósito, un retrato de la dueña y fotos del proceso, y el sitio usa sustitutos hasta que lleguen.

6. Rendimiento y SEO, con una cifra honesta

Una lista de verificación de lanzamiento cubrió URL canónicas (incluida una redirección 301 de www al dominio principal), vistas previas Open Graph, sitemap y robots, una página 404, páginas legales y contraste AA. Una corrida local de Lighthouse dio 93 en rendimiento y 100 en accesibilidad, buenas prácticas y SEO. El Largest Contentful Paint ronda los 3,2 s por la animación de entrada del hero, y acepté ese compromiso a conciencia. No instalé analítica, lo que además evita la necesidad de un banner de cookies. El sitio está solo en inglés, pensado para clientes de habla inglesa.

Pruebas

Todo se verifica con pruebas end-to-end en Playwright (Python): 196 comprobaciones sobre los tres tipos de página, incluyendo visibilidad del contenido, un catálogo roto a propósito, los botones de estación y el re-renderizado de la ficha de producto. Un E2E aparte maneja los formularios de n8n contra producción: publica una pieza de prueba, la edita, la borra y comprueba que el catálogo y el sitemap queden idénticos a como empezaron, sin que se envíe ningún correo a la clienta. Los reportes y las capturas se guardan como artefactos.

Lo que aprendí

Qué sigue

Fotos reales para las colecciones que faltan, el retrato de la dueña y fotos del proceso, además de confirmar los textos de muestra que aún no ha revisado. Si el tráfico crece, lo primero que habrá que vigilar es el clip de video de la home, porque es lo que más peso añade por visita.

Stack

HTML · CSS · JavaScript vanilla · Firebase Hosting (plan gratuito, dominio propio) · GitHub Actions · n8n (autoalojado, formularios y API de GitHub) · Playwright (Python) · Lighthouse


Share this post on:

Artículo anterior
Programación semanal de turnos con OR-Tools CP-SAT — una regla dura, tres blandas y Excel como base de datos
Artículo siguiente
motion-comercial — Videos de motion design comercial hechos con código, como skill de Claude Code