How Wattlebird Veterinary Clinic was made

The build notes behind site 231 of the Generative Assets collection — a conversion-focused landing page for a fictional companion-animal vet in Wembley, Perth.

Concept

The gentle consult

Wattlebird Veterinary Clinic is a fictional vet for Wembley and Perth's inner west, pitched at dog and cat owners — new-puppy households, families with an ageing labrador, cat owners who dread the carrier. The page has one job: book an appointment. The direction is calm clinical warmth — no cutesy pet-shop kitsch, no cold hospital white — a page that lowers the owner's heart rate before it asks for anything, and answers the money question before it's asked.

Palette

Argued from the consult room

Warm bone#F7F3EC — the ground. The colour of a calm waiting room, deliberately not surgical white.
Scrub teal#1F4E4A — structure and primary ink. The surgery scrub every vet wears; 8.5:1 on bone.
Banksia apricot#D97F4E — line/mark only: care-plan arcs, timeline markers, collar. Never body text on bone (3.1:1 would fail).
Apricot ink#B25526 — the derived deep tone that lets apricot act as a CTA fill: white on it measures ≈5.0:1.
Heeler blue#5B7B9A — secondary: focus rings, completed-care ticks, water on the map.
Heeler ink#48657F — darkened for link text; the raw heeler only reaches 4.0:1 on bone, so text gets this 5.5:1 tone.

The ink/line split is deliberate: the spec's bright accents (#D97F4E, #5B7B9A) draw lines and marks; wherever those hues had to carry words, a darker sibling was derived and contrast-checked.

Typography

A nameplate and a bedside manner

Fraunces (500–700, optical sizing on) is the practice nameplate and every heading — a warm, humane serif whose old-style quirks read like a hand on the shoulder rather than a hospital sign. The hero sets its one typographic bravery moment: "Gentle with them. Straight with you." with the italic carrying the brand promise. Nunito Sans handles body and UI — soft without being childish, with the weight range (400–800) doing the hierarchy work in forms, price cards and the trust strip. Body is 16px+ throughout.

Techniques

The Life-Stage Care Planner

The signature is a species toggle (dog/cat) plus an age slider (8 weeks → 16 years) driving three synchronised surfaces, all procedural SVG rebuilt per frame from one state object:

The rest state is designed, not blank: a dog at 7 years, timeline three stages ticked, the senior-watch card showing — mid-demonstration at the 7-second thumbnail. A 4.6s breathing idle (scaleY 1.012, transform-box: fill-box) keeps the portrait alive at rest; from age 12 a small wattlebird lands on the portrait ring — the second-read detail. Everything else is restrained: one entrance choreography gated on fonts.ready with a fallback timer, and prefers-reduced-motion kills the intro, the breath and the tween, rendering a settled, complete frame. A state probe (window.__vet) carries species, age, stage, card prices and form status for headless QA.

Conversion decisions

Why the page is shaped this way

Local SEO

What we'd implement for the real business

This demo page ships only WebPage schema naming it a demonstration — fictional structured data in a real index is dishonest markup. For a real clinic we'd ship VeterinaryCare LocalBusiness schema wired to their genuine details and live review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "VeterinaryCare",
  "name": "Wattlebird Veterinary Clinic",
  "url": "https://www.wattlebirdvet.com.au",
  "telephone": "+61 8 9000 0231",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "[real street address]",
    "addressLocality": "Wembley",
    "addressRegion": "WA",
    "postalCode": "6014",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.93, "longitude": 115.80 },
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
      "opens": "07:30", "closes": "18:30" },
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday", "opens": "08:00", "closes": "13:00" }
  ],
  "areaServed": ["Wembley","West Leederville","Subiaco","Floreat",
                 "Churchlands","City Beach","Jolimont","Shenton Park"],
  "aggregateRating": { "@type": "AggregateRating",
    "ratingValue": "[from live review feed]", "reviewCount": "[live]" },
  "review": [ { "@type": "Review",
    "author": { "@type": "Person", "name": "[real reviewer]" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "[pulled from Google Business Profile]" } ]
}
</script>

Plus: Google Business Profile with service categories per suburb, FAQPage schema on the six real questions, and suburb-level service pages once the practice wants to rank beyond Wembley.

The real client

What would change for an actual clinic

Iteration log

Three passes, honestly kept

Pass 1 — Craft

Screenshot review (full-page desktop plus hero and planner clips) caught the two real defects: the hero illustration read as mud — the dog a blob with a handle-loop ear, the banksia cone reading as a second creature — and the adult dog portrait's head detached from its body from age ~4, because the neck path that connects at puppy proportions thinned to nothing at full growth (the collar arc floated under the chin like a smile). Redrew the hero as a resting dog watching a wattlebird perched on a banksia stem; rebuilt the portrait neck as a solid quad polygon, moved the collar onto it, chunked the muzzle. Also fixed a harness artifact: toggle events fire async, so the FAQ probe was read before it ran.

Pass 2 — Depth

Added the breathing idle, made timeline nodes clickable (jump to stage midpoint through the 240ms tween), gave stage cards a hover lift, and kept the age-12 wattlebird as the second-read. One Chanel cut: the apricot line under the perched mini-bird read as a swing — removed. The harness gained an independently reimplemented price oracle: dog @ 8 weeks must show $180–$240 / $65 / $450–$750 and cat @ 12 years $190 / $98 — asserted against the rendered DOM, not the page's own data. Cross-surface greps then caught microchipping $65 present in the planner but absent from the services grid; added it to the vaccinations card so the page can't argue with itself.

Pass 3 — Hardening

375px and reduced-motion screenshot reviews. The timeline's per-stage range sub-labels compressed to ~5px at 375 — now hidden below 600px, the stage names carry alone. Reduced motion verified as a settled complete frame (breath animation computes to none, planner fully rendered, asserted headlessly). Final sweep: 47 checks green — zero console errors at both viewports, exactly one h1 per page, no horizontal overflow at 375, sticky-bar tap targets 48px, empty submit flags all six required fields, filled submit renders the local confirmation, and every phone number on the page uses the reserved (08) 9000 exchange.