512kg / dima
Comercial

Monto tiendas online

Dos tiendas, hechas de maneras opuestas por razones distintas.

Una tienda de pósters bajo demanda

Un Worker genera en el servidor la portada, el catálogo, cada ficha de producto y el sitemap, a partir de un único fichero de catálogo. Los buscadores y los asistentes de IA reciben HTML terminado. Cada ficha lleva marcado schema.org ProductGroup con sus 14 variantes de tamaño, con los datos de envío y la política de devolución.

Tres problemas suyos fueron más interesantes que la tienda en sí.

El 59 % del catálogo era un solo párrafo. Las fichas se importaron de un marketplace, y 171 de las 196 traían las mismas cinco líneas sobre el papel y la impresión. Medido, el 59 % de todo el texto del catálogo era ese párrafo repetido, que es justo lo que un buscador trata como contenido duplicado a escala. El Worker filtra ahora esas líneas al generar la página y enseña la información una sola vez. La regla para los productos nuevos es que la descripción lleva solo lo que es único de esa obra.

Los precios no siguen el tipo de cambio, a propósito. La tienda vende en euros, dólares y libras. Los precios son puntos fijos, calculados una vez con un cambio real y redondeados, no una conversión en vivo. Si la web cambiara los precios cada día, el de la página dejaría de coincidir con el del feed de producto, y Google desaprobaría las 2.744 variantes por discrepancia de precio. La moneda llega en la dirección y se vuelve a validar en el servidor: lo que manda el navegador no decide lo que se cobra. Esas direcciones van con noindex y un enlace canónico a la limpia, para que el catálogo no se indexe tres veces.

Un feed que no debe parecer nuevo. Pinterest crea los pines leyendo un RSS. Si la fecha de publicación de un elemento cambiara en cada petición, el mismo producto podría tomarse por nuevo y volver a publicarse. Así que cada producto tiene una fecha fija, una base más una hora por posición, y su identificador es la dirección de su ficha.

Una cosa más pequeña: el fichero de catálogo pesa 410 KB y se cargaba en todas las páginas, aunque fuera de la tienda el carrito solo necesita un título y una miniatura. Ahora se genera solo, a partir de él, una versión reducida de 49 KB.

Una web que vende una sola cosa

Plazas numeradas en un muro público, en cinco idiomas. Los datos están en D1.

El idioma se elige sin recordar nada. La detección ocurre en una única dirección, la raíz. El Worker lee Accept-Language, ordena los idiomas por peso y redirige al primero que tiene. No se guarda nada: ni cookie, ni almacenamiento local. Lo delicado es la caché. La página en español se guarda con una clave modificada, de modo que nunca pueda servirse desde caché a quien debía recibir una redirección.

Las entradas van encadenadas, y la cadena es pública. El hash de cada entrada cubre su número, su texto exacto, su fecha de publicación y el hash anterior.

Fig. 1 — Tres entradas encadenadas, y lo que hace cambiar una letra. Las entradas son ejemplos escritos para esta figura. Los hashes son SHA-256 de verdad, calculados en tu navegador con la fórmula que publica la web: número, texto, fecha de publicación y hash anterior, uno por línea.

Tres decisiones dentro de eso:

  • La cadena la calcula una tarea programada, no el momento de publicar. Los números se asignan bajo condiciones de carrera, y un hash escrito es definitivo.
  • Retirar una entrada no cambia su hash. Retirar afecta a cómo se muestra, no a lo que se escribió, y la cadena documenta lo segundo.
  • Si aparece un hueco, el encadenado se detiene. No lo rellena en silencio.

El pago solo se captura tras la revisión. La tarjeta se autoriza, no se cobra. Las autorizaciones caducan solas a los siete días, así que la tarea cancela a los seis las que no se han revisado: nadie paga por algo que nunca se llegó a mirar.

Cada entrada recibe dos imágenes que no cambian nunca, generadas con Satori y resvg en WebAssembly, guardadas en R2 y servidas a través del Worker para que la política de contenido pueda quedarse en img-src 'self'. La tarea genera tres por vuelta. Cada imagen cuesta mucha CPU, y con lotes de veinte se quedaba sin presupuesto a la mitad y dejaba el resto sin hacer.

Publicar no actualizaba la web. Algunas páginas seguían enseñando la navegación antigua después de un despliegue. Las páginas se guardaban una hora en la caché del borde, y un despliegue no las invalidaba: medí una página servida desde una copia de 59 minutos. El arreglo fue meter un identificador de versión en la clave de caché. Cada despliegue falla ahora en caché a propósito y regenera al instante, y el guion de pruebas lo vigila.

  • JavaScript66.8%
  • TypeScript18.7%
  • CSS7.2%
  • HTML5.4%
  • Shell1.6%
  • Otros0.3%