Files
gw-svelte/docs/v5.md
T
2026-07-04 10:00:16 +12:00

6.8 KiB

v5: Simplify the message on service pages

Goal

Every service page should say one clear message, once, in a fixed order, using the homepage's single visual language. No restated sections, no card-grid sprawl. Lead with trust, show the emotional outcome, let the page breathe (PRODUCT.md principles).

The Tiny Gang page is the finished reference. The rest of this task is applying the same treatment to the other two service pages.

The problem we are fixing

The current ServiceLandingPage.svelte stacks ~10 sections that repeat each other: hero, highlight collage, a 6-card benefit pager, an intro badge block, a decision card, a pricing block with an extras grid, an areas card, a FAQ card, and a related services grid. The same promise (matched groups, safe, free pickup) is said three or four times in three or four different card styles. It reads as pages of text and boxes, not one calm argument.

The v5 rule

Say it once, in order. One design system.

Canonical section spine for every service page (this is the order):

  1. Hero - what it is (shared ServiceHero: green copy left, photo right).
  2. What's different - the 3-4 things that actually set this service apart.
  3. How it works - the steps to get started, made explicit.
  4. Honest fit check - who it suits, who it does not (two columns, one card).
  5. Proof - TestimonialsSection.
  6. One deliberate image - a real photo that breaks the text and carries meaning.
  7. Price - even plan cards, plus a short row of promise notes.
  8. FAQ - a calm ruled list, not stacked cards.
  9. Service area - ServiceAreaCoverage: an Auckland hub with all suburbs as tappable links. Robust on every screen (no pin map). Per-page stats, so puppy-visits reads "in-home", not "pickup & drop-off".
  10. Book - BookingWizard.

If a piece of content does not fit one of those ten slots, it is probably a repeat. Cut it.

Design rules (non-negotiable, taken from the Tiny Gang build)

  • Lists, not cards. "What's different" is an icon + text list. "How it works" is numbered items. Reserve real cards for pricing only. Never nest cards.
  • One heading grammar. Every section opens with the same centered eyebrow + H2 (.tg-eyebrow + .tg-h2). No per-section badges, marks, or collages.
  • One token set. Use the shared CSS variables (colours, radius, shadow, spacing). No new gradients or per-section colour systems. Goodwalk green #213021, yellow #FFD100 for buttons only.
  • Pricing cards stay even. Four equal cards in a row on desktop, 2-up at 980px, 1-up on mobile. Do not put images inside or beside the cards.
  • One image, deliberate. A single full-width photo band between sections, with a short keyword-bearing caption. It must mean something (the pack, the pickup, the outcome), not decorate. See SEO rules below.
  • FAQ is a ruled list. Hairline dividers between questions, no card chrome.
  • Copy: half it, then half it again. Active voice. No em dashes. No heading that restates the one above it.

Image and SEO rules

  • Use real Goodwalk photos from static/images/ (keyword-rich filenames already).
  • Register width + height in src/lib/image-metadata.ts so there is zero layout shift.
  • Set explicit width, height, loading="lazy", decoding="async" on every <img>.
  • Alt text is a full, natural, location-aware sentence (e.g. "Four small Tiny Gang dogs looking up together in the long grass at an Auckland park"), not "dogs".
  • Keep the FaqSection schema (emitSchema) and the Service + AggregateOffer structured data in src/routes/[slug]/+page.svelte intact.

Reference implementation (copy this)

  • Component: src/lib/components/pages/ServiceClarityPage.svelte (shared by all three service pages, content-driven)
  • Pricing variant: src/lib/components/pages/PricingClarityPage.svelte
  • Coverage section: src/lib/components/sections/ServiceAreaCoverage.svelte
  • Preview routes (noindex): /variants/tiny-gang, /variants/solo-walks, /variants/puppy-visits, /variants/our-pricing
  • Content: the clarity block in pack-walks.ts, dog-walking.ts, puppy-visits.ts
  • Variant switcher (preview only): src/lib/components/ui/VariantNav.svelte, mounted in src/routes/+layout.svelte

Read the header comment in ServiceClarityPage.svelte first. It states the philosophy and the section order in one place.

Status

Done (built, svelte-check clean, server-rendered):

  • ServiceClarityPage generalised and content-driven; ServicePageContent.clarity added in src/lib/types.ts. Old TinyGangPage.svelte deleted.
  • clarity content written for pack-walks, dog-walking, puppy-visits. Tiny Gang renders identically to before.
  • Coverage spine slot added (ServiceAreaCoverage), with per-page stats so puppy-visits reads "in-home" not "pickup & drop-off".
  • Preview routes for all four variants, plus a global VariantNav to compare them.

Live now

The clarity pages are the live pages. src/routes/[slug]/+page.svelte renders ServiceClarityPage for pack-walks / dog-walking / puppy-visits and PricingClarityPage for our-pricing. The old ServiceLandingPage.svelte, PricingPage.svelte, and ServiceAreaMap.svelte have been deleted.

The /variants/* routes still exist as a sandbox (the minimal-footer test lives there), but are dev/localhost only: src/hooks.server.ts returns 500 for the /variants namespace off-localhost in production, and VariantNav is hidden the same way in +layout.svelte. Verified on a real node build: public host → 500 for any /variants/* and no VariantNav; localhost → variants load.

Footer note: the live pages keep the default footer. The minimal footer is still only on the /variants/* pages, a separate decision from the page-design swap.

Definition of done

  • One ServiceClarityPage component drives all three service pages.
  • Page-specific copy lives in content files, not the component.
  • All three pages follow the spine, say each point once, share one heading grammar and one token set.
  • Pricing cards are even on every page. No image in the pricing block.
  • Exactly one deliberate, captioned, fully-SEO'd image band per service page.
  • FAQ is a ruled list. Schema preserved.
  • npx svelte-check clean (no new errors).
  • Live [slug] branches swapped to the clarity pages.
  • Old ServiceLandingPage.svelte / PricingPage.svelte / ServiceAreaMap.svelte deleted.
  • /variants/* blocked in production (500) and VariantNav hidden there.
  • Decide whether to promote the minimal footer to the live pages.

Do not

  • Do not redesign the brand or introduce new colours, fonts, or gradients.
  • Do not add card grids, badges, collages, or mobile pagers back in.
  • Do not change wording on a page unless it is a repeat being removed or copy being shortened. Keep the meaning.