Blast Studio

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

Overview

“Built for wet ground.” Terrain Series is a four-piece kit — shell, anorak, cargo, hood — and the site had to sell it the way the brand talks: loud display type, field-report detail, no fluff. The brief was a storefront that feels like a lookbook but behaves like a shop.

The whole site is statically generated with zero UI framework at runtime. Everything interactive is hand-written TypeScript: about 9 kB of JavaScript and 44 kB of CSS shared across pages.

🛠️ What I Did

  • Built the full storefront in Astro 7 + Tailwind CSS v4, statically generated with no runtime framework
  • Kit configurator — pick one colorway and size across the three-piece kit; changing the swatch cross-fades every garment shot to the matching file
  • Persistent baglocalStorage-backed, so it survives navigation: header counter, side drawer, per-line remove, subtotal, checkout flow
  • Product pages generated per catalogue entry, with per-product sold-out sizes, spec sheets, lot stamps and a related-products rail
  • Pinned lookbook that scrubs sideways on scroll, degrading to a native swipe rail on mobile and under prefers-reduced-motion
  • One scroll engine — a single rAF-throttled handler drives the progress bar, header state, hero parallax, staggered reveals and count-up stats
  • Wrote a custom <picture> layer over Astro’s asset pipeline: AVIF with WebP fallback, real responsive sizes per call site, no upscaling, no layout shift, one eager LCP image per page
  • Built a design-token system — palette, type scale, spacing and motion declared once in tokens.css, mapped into Tailwind’s @theme so semantic utilities like bg-card flip an entire section to the light surface with one class

📉 The AVIF Problem

AVIF’s quality scale is not WebP’s — reusing one number across both codecs makes every AVIF file larger than the WebP it replaced. I measured PSNR against uncompressed resizes on the project’s own photography and found the crossover: AVIF at 18 points below the WebP quality lands 3–23% smaller and sharper.

So the image helper takes a single WebP quality and derives AVIF from it through a calibrated offset, rather than trusting a shared constant.

Colorway swapping is client-side, but processed files have hashed names only the build knows. Both the configurator and the product pages resolve every variant through the same helper the server renders with, and swap the AVIF <source>, the <img> srcset and its src together — updating only src would leave most visitors looking at the previous colorway.

✨ Results

  • ~180 kB first paint on a 390px phone; ~250 kB at 1280px desktop
  • AVIF cuts 12–17% off delivered image weight versus WebP alone, with older browsers still served full-quality WebP
  • 356 image variants build cold in ~16s, near-instant warm
  • Pages stay readable with JavaScript off — reveal animations only hide content once JS is confirmed running
  • Adding a product is a one-line append to a data file; the route, the drop grid, the related rail and the bag all follow