Drinks brand
A heritage spirits rebrand, forty screens of Figma, and an age gate that had to satisfy the lawyers without wrecking the Lighthouse score.

The studio arrived with a rebrand that was nearly finished: new bottle, new type, a lot of foil texture, and a forty-screen Figma covering everything from the brand story to a serve-measure calculator. What they didn't have was anyone to build it, and the client had already put a launch date on a billboard.
Where it started
The studio sent the file on a Tuesday with a note that said, roughly, tell us if this is buildable before we show the client a date. We spent two days in it before quoting: walked all forty screens, sorted the blocks from the one-offs, and flagged the two places where the design assumed content nobody had yet (the tasting notes and the distributor list). The fixed quote went back at the end of that week with the block list attached, so everyone could see what they were buying.
That block list became the project's shared vocabulary. When the studio said 'the ritual block' on a call, we both meant the same artboard, then the same Twig file, and eventually the same thing their client drags into a campaign page.
The build
Every section in the file became a block, sixteen in all, from the full-bleed bottle hero down to a pull quote with the brand's engraved rule under it. Recipes are structured entries rather than styled text. Ingredients, method, glassware and related serves are fields, which lets the site cross-link every drink that uses the same bottle and gives each recipe page markup a search engine can read.
The store locator runs off the distributor's spreadsheet, imported nightly by a console command that flags rows it doesn't understand instead of dropping them. Nobody at the studio or the client re-keys an address.
The awkward one was the age gate. Legal wanted it on every entry point and we wanted no render-blocking overlay slowing every page load. What shipped is a cached, static overlay that sets nothing until the visitor answers, so the pages stay fully cacheable, the score stays green, and the lawyers got their screenshot.
The Craft underneath
Each of the sixteen blocks is an entry type with its own Twig partial. A block can gain a field without touching its neighbours, and a page is whatever order the editor stacks them in. The recipe cross-linking that looks expensive is one eager-loaded query, so a serve page touching a dozen related entries costs the same as one that touches none. Live preview is wired so an editor sees their own hero crop against the foil before publishing.
Speed came from the less glamorous parts of Craft. Project config in version control meant the three environments couldn't drift, so a block approved on staging was, byte for byte, the block that shipped, and most of the seven weeks went on the design rather than on deployment problems.
The parts that took the time
The longest single line on the timesheet was the foil. The rebrand leans on an embossed texture that looked superb in Figma at 400% zoom and threatened to weigh half a megabyte in production. It ships as AVIF with a JPEG fallback, three crops per hero and a focal-point field, which keeps the bottle intact at every aspect ratio and the texture under 90KB on the heaviest page.
The serve-measure calculator is small on purpose: an Alpine component of about sixty lines that reads the same structured recipe fields as the page around it. With JavaScript off it renders the measures as a plain table, which is also what search engines get.
Weeks one and two went on the content model and a grey-box version of all sixteen blocks. The overlay pass ran across weeks three to five, block by block against the studio's file. Week six was the importer and the age gate. Week seven was content load, which is where the lawyers came back with notes on the copy but not the mechanism, because they'd seen the mechanism in week two.
Content load ran as a phase of its own rather than something that happened to the site at the end. We entered the first market's pages ourselves, working from the studio's copy deck, on the basis that nothing tests a content model like having to use it. Two field labels changed, one block gained an optional caption, and the client's team loaded the other markets without a single support call.
The checks
Every block cleared the same gate before it reached staging: a keyboard walk, a screen-reader pass, and contrast checks against the foil backgrounds, which failed twice and moved two text styles onto solid panels with the studio's blessing. We test Lighthouse per block, so a dipping score always names its culprit, and the site went out at 98 with the age gate costing it nothing. The same pass covers motion (a one-time reveal as blocks enter and a slow sheen across the foil on hover, all of it removed under reduced motion) and the fluid type scale, checked so headings track the viewport instead of jumping at arbitrary widths.
Blocks landed on staging in weekly drops and were reviewed on a Friday call with the overlay up and the Figma beside it. Most weeks the call lasted about ten minutes. Launch was quiet: the old site's ninety-odd URLs mapped to new homes, DNS moved at seven in the morning, and the date on the billboard was beaten by two days, which the studio presented to their client as planned.
After launch
The client's marketing team assembles campaign pages per market from the block kit. The seasonal ones never touch the studio, which is how the studio likes it. The site sits on our hosting, so Craft and plugin updates happen without anyone raising a ticket. Eighteen months on, the block count is still sixteen. Nobody has needed a seventeenth.
The client thinks the studio's dev team built it. Contractually, we did.