Website build: coding with Claude

Website build: coding with Claude

Tim Girling-ButcherNovember 18, 2025

I’ve been working with my organisation's website — built with Sanity and React/Next.js — for several years, but I hadn’t had many opportunities to properly familiarise myself with the tech stack. With the site live, the risks of breaking something or simply embarrassing myself were high.

So I decided to build a fully-functional platform and learn by struggling through the real work: wiring up schemas, GROQ queries, dynamic routing, image pipelines, and all the deployment oddities. Hands-on experimentation is the main way I actually learn and retain information, and I wanted to understand how Next.js 16 handles server components, how Sanity’s structure builder behaves once you push it beyond the basics, and how the whole stack holds up once real content starts moving through it.

At the same time, I used the project as a chance to experiment with Claude Code as a kind of pair-programmer. Instead of treating AI as a shortcut, I approached it as a debugging partner and pattern-spotter - giving it discrete tasks, watching how it refactored or reasoned about the code, and testing where it genuinely improved my workflow versus where it wandered into rabbit holes or simply hit a wall. It became a way to learn both the stack (its knowledge of this ecosystem is genuinely encyclopaedic) and the practical limits of AI-assisted development at the same time.

Being completely new to this setup, the learning curve was steep. I quickly found myself leaning heavily on Claude to design solutions and troubleshoot roadblocks. Before long, I was surprised by how reliably it could untangle issues, and that reliability meant the pace of work accelerated far faster than it would have if I’d been learning everything unaided.

Before unpacking the role AI played in the build - and how well it actually performed - it’s worth first outlining the core modules I developed: the components that now form the site’s framework and underpin most of its functionality.

Modules

There were a range of modules I wanted to develop and utilise. Listed below as a reference and in no particular order.

Hero video

The Hero Section (see above) is the full-screen intro block used for big, cinematic openings. It supports high-quality video backgrounds (H.265, WebM, H.264, full-back image or a direct URL) with an optional poster image, or a simple gradient fallback when no video is provided. An adjustable overlay keeps text readable, while the title and subtitle are centred and fully driven by Sanity. It’s a lightweight, flexible way to create bold, immersive page headers.

Photo gallery

PhotoSwipe is the image-viewer layer that powers all of my gallery and pop-up interactions. It gives the site a fast, touch-native way to browse high-resolution images, handling pinch-zoom, smooth panning, swipe navigation and responsive scaling without adding unnecessary bulk. Unlike many gallery libraries, it doesn’t force a specific layout or markup structure, which means I can design my own grid components and use PhotoSwipe purely for the viewing experience. This keeps the visual design flexible while still delivering a polished, app-like feel when a user taps into an image.

PhotoSwipe also integrates cleanly with Next.js and plays well with the Sanity image pipeline. Each gallery pulls in structured image data — source, alt text, aspect ratio, crop, hotspot — and hands it off to a lightweight React wrapper that initialises the viewer only when needed. That lets me lazy-load both images and the PhotoSwipe module itself, keeping pages fast and reducing visual shift. The result is a self-contained module that gives me complete control over presentation while ensuring users get a smooth, intuitive way to explore detailed visual content.

Parallax


The Parallax Section is a flexible hero block that lets me place text over either an image or video background with a smooth scroll or scale-based parallax effect. It uses lightweight, GPU-accelerated transforms to keep motion fluid, and supports multiple layout options — height, text alignment, overlays, gradients, and Sanity hotspots — so the same module can be reused across very different page types.

Content is fully driven by Sanity: titles, subtitles, and rich text flow into a responsive layout that adapts to mobile and desktop. Backgrounds can be high-res images or multi-format videos, and all the scroll logic is handled automatically. It’s a self-contained way to create atmospheric, cinematic sections without custom coding each time.


Paralax

A subtitle field

Body text for writing general copy.

Text block

The Text Section is a simple, flexible content block for long-form writing. It renders Portable Text from Sanity using shared text components and supports adjustable width, alignment, spacing, and optional colour inversion for light-on-dark or dark-on-light layouts. It’s the building block for clean, readable content without custom styling each time. it includes:

Code block

export default function TextSection({ section }: { section: any }) {
  const maxWidthClasses = {
    small: 'max-w-2xl',
    medium: 'max-w-3xl',
    large: 'max-w-4xl',
    full: 'max-w-full',
  }

Table

This module lets a user paste in Excel data and have it automatically lay out as a table. Sanity doesn’t offer an easy native solution for tables, so getting this working was genuinely tricky.

ItemMakeModelDescription
LocatorQuuppaLD6LCeiling Locator
LocatorQuuppaLD6LCeiling Locator
LocatorQuuppaLD6LCeiling Locator
LocatorQuuppaLD6LCeiling Locator
LocatorQuuppaLD6LCeiling Locator
LocatorQuuppaLD6LCeiling Locator

Image with caption

A standard image block showing title, description and credit, with the full gallery viewer option.

Image with text wrap

Aerial view of the coast in Thirroul on a rainy day
search

The Image with Text Wrap block lets me place an image directly inside a text flow, with the text naturally wrapping around it. It’s designed for more editorial layouts where images need to sit within a narrative rather than above or below it. The block supports left or right alignment, responsive behaviour, and full Sanity-driven image data (including crops and hotspots), so it scales cleanly across devices. It gives longer articles a more magazine-like feel while keeping the layout lightweight and flexible.

Image inline

A straight image drop-in with no caption or credit

Man crossing a river

Pull quote

This is a pull quote. They are great for doing things like pulling out words that draw attention and break up the flow.

This is the citation credit with a footnote.

iframe

A flexible embed block for anything external - SoundCloud, Google Maps, YouTube/Vimeo, widgets, calendars, forms. It includes controls for height, width, aspect ratio, scrolling, border radius, captions, and fullscreen toggling, so it feels integrated instead of tacked on.

Scroll Sequence

The Scroll Sequence module brings motion into the page narrative by transforming an animation - output as a series of still images - into a smooth, scroll-controlled animation. As visitors move down the page, their scrolling directly determines which frame is displayed, producing a video-like effect without a traditional player. The module renders onto a canvas for performance, progressively loads frames to reduce initial weight, and supports lazy loading to improve perceived responsiveness.

Built with flexibility in mind, the module supports externally hosted image sequences. I initially attempted to achieve this within Sanity, but the complexity and limitations of managing 200+ frames through the Studio UI made it impractical. The module can also render every second or third frame to reduce overhead when full-sequence fidelity isn’t required. Captions can be triggered at specific frame points, ensuring key information, explanations, or feature highlights align cleanly with visual transitions. Layout options allow the animation to be pinned left or right on desktop, fill the viewport, or switch to alternate image sets for mobile devices.

It also respects reduced-motion preferences, maintaining accessibility while preserving clarity and visual interest. The result is a highly configurable, lightweight module that enables immersive, interactive storytelling — from product reveals and process demonstrations to architectural walkthroughs and rich scrollytelling experiences. The example below is a concept for the Hyde Park Barracks.

Loading frames... 0%
kjahs kaj kasdjhf

Accordian

The Accordion module is designed for content that works best when broken into expandable sections — FAQs, project notes, technical details, or anything that benefits from a cleaner, more compact layout. Each accordion panel can contain full Portable Text and supports embedded modules like Image with Text Wrap, tables, and other rich content blocks, allowing me to reuse existing components rather than creating custom layouts for every case. It keeps dense information organised and scannable, while still giving me the flexibility to include more complex content when needed.

3D model viewer

This viewer brings in models from Pedestal (where MHNSW hosts its 3D models) and overlays a custom UI that is better suited to the website style. It triggers some of the options available through the platform via a custom UI, but rather than cluttering this interface, the user can follow a link to the pedestal platform for all options.

3D model gallery

A way of bringing in models into a gallery with custom titles and images. This opens into a full window view with the same controls as the model viewer.

Contact form

A form to drop in if people want to get in touch


A contact form

Call out for what ever reason someone might have to get in touch.


Video block

The video block gives me a simple, reliable way to drop in a video. It supports YouTube and Vimeo links and automatically handles the thumbnail, aspect ratio, and responsive sizing. The initial controls are lightweight so it feels like part of the site rather than a bolted-on player. One issue I had to resolve was a fallback for iOS to native YouTube player on load (iOS was forcing a double play due to autoplay restrictions). This video is an animation of a 3D model created of a framed portrait of an ancestor of mine.

Video thumbnail

Video Gallery

A way to bring multiple videos into a gallery. The description appears over the hero video once selected. Like the video embed, the standard YouTube controls appear on iOS devices due to Apple autoplay controls.

Video thumbnail

Beach

Highlights block

The Highlights block is a flexible grid of cards designed to surface other content on the site. It can pull in items automatically - based on tags, selected pages, projects or posts - or you can build cards manually with custom titles, icons and URLs, including external links. It’s a simple way to point readers towards related work, further reading or featured material, with the option to send them through to a dedicated page if they want to dive deeper.

Verdict on Claude?

Claude Code ended up exceeding my expectations. It made light work of the things I’d normally grind through - everything from getting Sanity running with Nginx to building and refining the deployment scripts. It handled model scaffolding, styling tweaks, and custom components with a precision that made the whole process feel lighter. Often I’d be stuck on something fiddly or tedious, and throw to Claude, and it would be untangled it in minutes.

Where it struggled was with genuinely complex problems - especially when I collapsed my staging and production environments onto a single server (while cursing myself for not doing that from the start). Its token limits meant it couldn’t hold a reliable memory of what had been running where, which created small but maddeningly time-consuming issues I had to sort out manually. But even with those quirks, the overall experience was remarkable. Its speed and reliability made such a difference that it’s now woven into my workflow - not as a shortcut, but as a genuinely capable second brain.

I plan to continue trialling the development of new modules and refining the platform, and based on my overwhelmingly positive experience with Claude Code so far, I expect it to be far more useful, stable, and capable than I initially anticipated.