Henroo Pottery is a small online shop for Briony‘s hand-built ceramic characters: monsters, ghosties, goblins, mushrooms with faces and whatever else comes out of her studio in Suffolk. Nearly every piece is one of a kind, and new work goes out in small drops that tend to sell out quickly.
This year I rebuilt the WooCommerce site from the theme up. This post covers the parts that were most interesting to build. It is less of a step-by-step guide than my other posts, but most of the ideas carry over to any small shop.
A Shop That Looks Like the Work
The redesign started from a small design system written around the pieces themselves: a warm paper background instead of white, a handwriting display font, soft clay and glaze colours, and copy in Briony’s own first-person voice. The brief, in the design system’s own words, was to feel “handmade, warm, a little cheeky, never slick”.
I built it as a new Storefront child theme, with custom templates for the home, shop, category and product pages wired into WooCommerce’s hooks. Even the order emails match: they are laid out like a handwritten note with a packing slip, with every style inlined by hand so Gmail and Outlook show them as designed.
Photographing One-Offs
When every piece is unique, the photos do the selling. The site shows each image through two centred crops: square on the grid cards and 3:4 portrait on the product page. So every product photo is made as a 3:4 master, 2400 × 3200 pixels, with the piece centred at 66% of the frame height. The centred square of a 3:4 frame covers the middle three-quarters of its height, so 66% leaves a small margin and the piece is never clipped in either crop.
I shoot the newer photos on a DSLR against a white background, and each master is a straight crop plus one correction measured from the wall behind the piece, with no retouching. That is partly taste and partly policy, as Etsy now asks for at least one unedited photo of the real piece on every listing. Those pieces also get a dimensions tile: the main photo with height and width arrows labelled from the product’s own measurements.
360° Turntable Videos, Self-Hosted
Many pieces, most of the Monsters included, also have a 360° video as the second tile in the product gallery. A script measures the turntable’s rotation period from the differences between frames, cuts exactly one turn starting face-on, crossfades the join so the loop is seamless, speeds it up three times and encodes an 810 × 1080 H.264 clip of about 11 seconds with no audio. Running it twice gives the same file, byte for byte.
I turned down YouTube (player chrome, cookie consent and a visible restart at the end of every loop) and the hosts that charge a monthly subscription to serve a few 2 MB files. The clips are ordinary media library attachments, offloaded to S3 and served through CloudFront like the photos, where the free tier alone covers hundreds of thousands of plays a month. They autoplay muted, show a play button instead when autoplay is refused or reduced motion is preferred, and go to Etsy unchanged. Phil the Goblin King is a good one to try.

Shopping by Size
A character’s name doesn’t tell you how big it is, so every product gets a size band: the largest of its length, width and height, banded from Small to XXL in 6 cm steps. The band is worked out at query time from the dimensions WooCommerce already stores, so nothing needs tagging or backfilling.
On a category page such as the Monsters range, each tile carries its size letter and the filter pills are multi-select toggles. Picking one fetches the same URL in the background and swaps the grid in place, updating the address bar so Back still works and falling back to a normal page load if anything fails. The default order is in stock first, then size, then price.

Not everything is a one-off. Mini Monster Moods are pocket-sized monsters sold singly or in packs of three or five. They are a variable product, but stock is held as one pool of pieces: a pack of five takes five from the pool, and the basket refuses a pack there aren’t enough pieces left for.
One Piece, Several Places to Sell It
The hardest problem was stock. A one-off can sell on the website, on Etsy or on the card reader at a craft market, and once it sells it has to disappear everywhere.
- Etsy: I built a module that publishes WooCommerce products as Etsy listings, with photos, video, tags, size and weight, and hears about Etsy sales by webhook. Each sale also becomes a website order, so postage is handled in one place.
- Square: Briony takes payments at markets on Square. Every in-stock piece is on the till, a market sale marks the piece sold on the site and on Etsy within about 15 minutes, and each sale is copied in as a website order without touching stock a second time.
- Parcel2Go: postage labels are bought from the order screen, and the tracking number goes to the buyer.
The bug that taught me the most: a piece sold on Etsy, the site set its stock to zero, and eleven seconds later it was back on sale. Every product save starts the Square plugin’s own sync job, which pulls Square’s count back for a linked product, and Square still said one. The fix sends any stock change on a synced piece straight to Square as an absolute count before that job can read it, and while Etsy holds a claim on a piece, a Square sync can’t raise its stock.
Fast Pages, and Images Machines Can Read
Every image on the site is AVIF, converted on upload, and that taught me two things. First, WordPress writes the resized copies of each image at its default quality of 82. After comparing a sample of Henroo photos side by side, I settled on 50, and re-encoding all 929 images took those files from 448.6 MB to 145.2 MB, 68% smaller. The only visible cost is that a fine crackle glaze looks a touch softer on a high-density phone screen.
Second, not everything can read AVIF. ChatGPT’s product cards were showing Henroo’s photos as broken images, and Google Merchant Center, Pinterest and LinkedIn have the same problem. Every image now also has a JPEG share copy for social previews, structured data and the product feed, and visible images sit in a <picture> element, so AVIF browsers download exactly what they did before and anything else gets the JPEG.
I measured speed with Lighthouse in a fresh browser profile, because my extensions and logged-in cookies made the scores look worse than visitors see them. Mobile Performance started at 72–78 across the main page types. Apart from the images, what moved it was:
- inlining the critical CSS, but keeping the layout stylesheet render-blocking, because deferring it gave the product page a layout shift of 0.49
- loading PayPal’s SDK on the visitor’s first scroll, tap or pointer move instead of at page load
- requesting the brush font, used for a single “@” sign, with Google Fonts’
text=parameter so only that one character is downloaded
Mobile now scores 81–89 and desktop 98–99, with Best Practices at 100 and Accessibility at 97.
Groundwork for Search
Henroo is a new name, so the site has to explain itself to search engines and AI assistants. Each product’s structured data carries its dimensions, weight, material, handling time and returns policy, with sold pieces marked as sold out and packs listed as variants. Category pages describe the grid on screen as an item list, and filtered URLs stay out of the index.
A Toolkit Shared Across Four Sites
Most of the generic code isn’t Henroo’s at all. The mailer, S3 media offload, AVIF conversion, the Etsy and Parcel2Go modules and the updater live in one toolkit repository shared by four WordPress sites, this one included. Each site gets a synced copy with a manifest of content hashes that flags local edits, the tests run on disposable lab sites, and the sites update from signed releases. Henroo’s own code is mostly the child theme and a site plugin: the brand, the size bands, the packs and the glue between Square and everything else.
Briony goes full-time on Henroo from the end of 2026, so the site will keep growing with her: more ranges, more photography and video, and whatever the next drop needs. If you are building something similar on WooCommerce, I hope some of this saves you a few evenings.