# Physiotherapy Clinic

> A seven-page clinic website template for physiotherapists, dental practices, chiropractors, osteopaths and massage clinics. An interactive body map leads to treatment pages, and every page change opens through a vermilion disc that grows from the point the visitor touched.

Canonical: https://gsapvault.com/templates/physiotherapy-clinic-template
Live demo: https://gsapvault.com/demos/physiotherapy-clinic-template/index.html

| Property | Value |
|----------|-------|
| Type | template |
| Tier | paid |
| Price | Not sold singly; comes with the Templates Pass or the Vault |
| Difficulty | advanced |
| Plugins | ScrollTrigger |
| Techniques | page-transition, soft-navigation, directional-transition, clip-path, mask-reveal, scrub, scroll-reveal, stagger, hover-effect, filter, form-animation, keyboard-navigation, focus-management, progressive-enhancement |
| Uses Lenis | No |

## Lighthouse, as measured

Google Lighthouse on the demo (7 pages, lowest score shown), 4 October 2026. A measurement of the demo as shipped, not a promise for your page.

| Category | Score |
|----------|-------|
| Accessibility | 100 |
| Best practices | 100 |

No performance score is published: it depends on the deployment (server compression, caching, CDN, connection and device) rather than on the code, so measure it where it will live.

## Overview

A clinic website has one job before any other: help someone in pain find the right appointment. This seven-page template starts with a full-bleed treatment-room photograph that releases into an inset card as you scroll, then asks the question patients actually arrive with: where does it hurt? A full-length body map with six touch points shows the common problems for each area and the treatment that usually helps first. Fulcrum Physiotherapy, a fictional clinic in Leeds, is the worked example; the same pages suit a dental practice, chiropractor, osteopath, sports massage studio or private health clinic.

Every page change is the template's signature. A vermilion disc grows from the exact point the visitor touched, the destination's name is set in a light serif on the coloured field, and the field opens as a circular aperture from the new page's focal point, closing down to a small dot that lands on the page's "you are here" marker. Follow a body-map point and the dot settles on the matching area of the treatment page. Choose a clinician and their portrait travels across to the team page. Back and Forward run the transition in reverse, and every page keeps its own address.

The pages cover three treatments with first-session steps, area notes, prices and FAQs, a filterable treatment index, a team page with registration details and a four-step booking flow that prepares an unsent appointment request. Cool grey ground, white cards, deep green-black ink and one vermilion signal colour keep the interface calm; replace the photographs, copy and four colour tokens to make it yours. Everything is static HTML, CSS and JavaScript with bundled images and no build step.

## Features

- Seven standalone HTML pages: home, treatment index, three treatment pages, team and booking
- Signature page transition on every internal link: a disc grows from the touch point, the destination title holds on the field, and an aperture opens from the new page's focal point
- A landing dot that settles on each page's current marker, including the selected body area on treatment pages
- Clinician portraits that travel from the home page into their section of the team page
- Back and Forward run the transition in reverse, with scroll positions restored and the focused heading announced
- "Where does it hurt?" body map with six hotspots and area chips, hover, focus and tap cards, and links into the matching treatment
- Full-bleed hero photograph that releases into a rounded inset card on scroll
- Treatment index filtered by body area, pre-selected from a ?area= link
- Treatment pages with first-session steps, a wide photographic moment that opens out on scroll (plain, quote or figures variant), notes by area, prices table, lead clinician and native FAQ disclosures
- Booking page with reception photograph, four-step flow, live summary, clinician filtering by treatment and an explicitly unsent request draft, plus first-visit, directions, cancellation and payment information
- Real links and complete pages without JavaScript; instant page swaps under reduced motion
- Seventeen bundled, graded WebP images: real treatment photography plus AI-generated clinician portraits and body-map figure, with credits

## Use Cases

- Physiotherapy and sports injury clinics presenting treatments by body area
- Chiropractic and osteopathy practices with several practitioners
- Dental practices and private health clinics taking appointment requests
- Sports massage, Pilates and rehabilitation studios with a small team

## Questions about this template

### Which kinds of clinic can use this template besides physiotherapy?

It is built as a general clinic website template. Dental practices, chiropractors, osteopaths, sports massage studios, private GP and health clinics, and vet practices can keep the structure: a body map or service chooser, treatment pages, a team page and a booking request. Replace Fulcrum's treatments, photographs and copy with your own services.

### Can I change the body map areas or use a different photograph?

Yes. Each hotspot is a link with its position set as percentages in its style attribute, paired with a card that shares its area name. Replace the figure with your own full-length photograph, move the six points to match, or add and remove areas; a dental practice might map teeth or treatments onto a smile photograph instead.

### Will the booking form create real appointments?

No. The booking page is an unwired static front end. It collects treatment, clinician, preferred time, name, email, phone and a short note, then prepares an unsent request the visitor can copy. Nothing is saved or delivered. Connect Formspree, Netlify Forms, your practice management system or your CRM, and update the visible notice, before taking real bookings.

### Do the page transitions need a special server?

No. Upload the seven HTML files and the assets folder to any static host served over HTTP or HTTPS. Links then fetch the next page and run the transition while keeping fonts and styles loaded. Opened directly from your computer, or with GSAP unavailable, the same links load pages normally, and reduced motion swaps pages instantly.

### How do I add another treatment page?

Copy one of the three treatment pages, rename it and change its title, photograph, steps, prices and FAQs. Set its transition label and title attributes, list the body areas it helps in the area index, and link it from the treatment index and navigation. Any sibling HTML page with the same page wrapper joins the transition automatically.

### Are the clinicians, registration numbers and reviews real?

No. Fulcrum Physiotherapy, its four clinicians, their registration numbers, prices and reviews are fictional examples. The treatment-room photographs are licensed stock of unrelated people, and the clinician portraits and body-map figure are AI-generated images of people who do not exist. Replace them with your own team, accurate registrations and genuine reviews before launch.

## Vibe-Code Ready Setup

This template includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

### Start from where it hurts

The home page body map places six points on a full-length photograph: neck, shoulder, lower back, hip, knee and ankle. Hovering, focusing or tapping a point shows a card with common problems and the recommended treatment, and the matching chips beside the photograph do the same. Each point is a real link, so without JavaScript the cards become a plain list of areas and links.

### One transition for the whole site

Internal links fetch the next page and swap it in under a vermilion field instead of reloading. The field grows from the visitor's touch point, shows the destination's name while the page and its main photograph load, then opens as an aperture from the new page's focal point. A small dot closes onto the page's current marker, so the visitor can see where they have arrived.

### Portraits and areas carry across

Arriving from a body-map point selects that area on the treatment page and lands the dot on it. Choosing a clinician on the home page flies their portrait into their section of the team page. Browser Back and Forward reverse the transition, closing towards the point the visitor left from, and restore the previous scroll position.

### Treatments, team and booking

The treatment index filters by body area. Each treatment page carries first-session steps, a wide photograph that opens out across the page as it scrolls in, notes by area, prices, the lead clinician and questions. The booking page walks through treatment, clinician, time and details, hides clinicians who do not offer the chosen treatment and produces a request the visitor copies; nothing is sent or stored. Below it, what to expect at a first visit, parking and the cancellation policy sit in one place.

### Calm when it needs to be

Reduced motion swaps pages instantly and shows the hero as a static inset card. Opened from the file system, or with the animation library unavailable, links load pages normally and all content stays visible. Rapid clicks are ignored while a transition runs, and pressing Back mid-transition settles on the page the browser asked for.

## Documentation

How this template works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

Upload the folder to any static host and open `index.html`. Keep the seven HTML files beside `assets/` so relative links keep working. There is no build step, framework or package to install.

Serve the files over HTTP or HTTPS to see the page transitions. While editing, use any local static server (for example `python3 -m http.server` in the folder) and open `http://localhost:8000/index.html`. Opening a file straight from disk works too, but links then load pages normally without the transition.

GSAP and ScrollTrigger load from a CDN and the fonts from Google Fonts. Images, styles and the script are bundled locally.

### Using It With Your Own Design

1. **Identity.** Replace "Fulcrum", the logo tile letter, the address, phone number, hours and the fictional-clinic note in the header and footer of each page (they are repeated in all seven files so each page stands alone).
2. **Photographs.** Swap the files in `assets/img/` keeping the names, or change the paths. Update alt text and captions to describe what your photographs actually show.
3. **Services.** Rename the three treatment pages for your services: a dental practice might use `check-ups.html`, `hygiene.html` and `whitening.html`. Update their links in the treatment index, home rows, footer and booking choices.
4. **Colour and type.** Edit the four colour tokens at the top of `assets/style.css` (see Palette). Change the Google Fonts link in each page if you change typefaces.
5. **Booking.** Connect the booking page to your own service before taking real requests (see Booking Form).

Everything visual lives in `assets/style.css`; everything interactive lives in `assets/script.js`, organised as one function per feature that returns early when its markup is absent. `assets/page-router.js` is the small page router underneath the transition (link handling, fetching, history, scroll and focus); you should not need to edit it. Delete a section from the HTML and the rest keeps working.

### Pages and Configuration

| File | Content |
| --- | --- |
| `index.html` | Hero photograph that releases into an inset card on scroll, figures row, body map, three treatment rows, four clinicians, reviews, location and hours |
| `treatments.html` | Treatment index with body-area filter chips; `?area=knee` pre-selects an area |
| `physiotherapy.html`, `sports-massage.html`, `clinical-pilates.html` | Treatment pages: sticky area index, hero photograph, first-session steps, a wide photographic moment (plain, with a quote card, or with figures), notes by area, prices, lead clinician, FAQ, next treatment |
| `team.html` | One section per clinician (`id="hannah"` and so on) with portrait, registration, specialisms and a booking link |
| `book.html` | Reception photograph and key facts, four-step booking flow with live summary and an unsent request draft, then what to expect at a first visit, directions and parking, cancellation and payment |

Hooks you will meet in the markup:

- `data-page` wraps each page's header, main and footer. Its `data-passage-label` (small caps line) and `data-passage-title` (large title) are what the transition shows while that page loads.
- `data-passage-photo` marks the element the arriving aperture opens from (usually the page's main photograph).
- `data-area-index` / `data-area-link="knee"` / `data-area-note="knee"`: the treatment pages' area index and notes. `?area=knee` in the address selects that area on arrival.
- `data-filter`, `data-filter-chip="knee"` and `data-areas="neck knee"`: the treatment index filter. List every area a row covers in `data-areas`.
- `data-portrait="hannah"` on two images, one on each page, plus `data-passage-portrait="hannah"` on the link between them, makes the portrait travel across.
- `data-moment` / `data-moment-media`: the treatment pages' wide photograph. It reaches back across the area index to the full page width, and on wider screens opens out from the text column as it scrolls in. Choose a variant with `tx-moment--wide`, `tx-moment--quote` (a white quote card over the photo) or `tx-moment--stats` (three figures over the photo).
- `data-reveal` and `data-reveal-group` give a gentle rise on scroll; `data-hero-fade` marks a page's opening block.

### Page Transitions

Every same-origin link to a sibling `.html` page runs the same transition:

1. **Out.** A vermilion disc grows from the exact point the visitor clicked or tapped. Keyboard activation grows it from the centre of the focused link. Body-map links grow it from their hotspot (`data-passage-from="#spot-knee"`).
2. **Hold.** The destination's label and title rise on the vermilion field while the next page is fetched, its main photograph is decoded and the page is swapped in underneath.
3. **In.** The field opens as a circular aperture from the new page's focal point: the selected body-area marker when there is one, otherwise the main photograph. A small dot closes onto the page's "you are here" marker (the current navigation link, the selected area, or the logo on the home page). The arriving photograph settles from a slight zoom.

Back and Forward reverse it: the aperture closes onto the current page's focal point, and the disc shrinks back into the point the visitor originally left from. Scroll positions are restored and the arriving page's heading receives focus and is announced.

Clinician links with `data-passage-portrait` carry the portrait instead of the title card: it lifts off the home page, stays on the field and flies into its slot on the team page as the aperture opens.

Notes for editing:

- Pages are fetched, not reloaded, so scripts inside a fetched page do not run. Put new behaviour in `assets/script.js` as another init function called from `initPage`. Every page loads `assets/page-router.js` before `assets/script.js`; keep that order on a new page.
- The transition itself is the `leave`, `hold` and `enter` functions passed to `PageRouter.create` at the end of `assets/script.js`; the header comment of `assets/page-router.js` lists everything they receive.
- Any sibling HTML file with a `data-page` wrapper joins the transition automatically. Add `data-native-navigation` to a link or container to opt out; downloads, new-tab clicks, external links and same-page anchors already behave normally.
- Timing lives in `growDisc` (about 0.4s), `showTitle`, `openAperture` (about 0.5s), `closeAperture` and `shrinkDisc`. With the next page already fetched (links prefetch on hover and focus) one transition takes about 1.2 seconds, including a minimum 0.2s hold on the title. On a slow connection the title holds until the page and its main photograph are ready.
- The latest click wins: a second link chosen before the new page is in place goes straight to that page from the vermilion field, and Back or Forward mid-transition settles on the page the browser asked for. Resizing the window mid-transition finishes it quickly.

### Body Map

Each hotspot is a link inside the figure, positioned by percentages: `style="--x: 41.5%; --y: 69.5%"`. Its `aria-describedby` points at the matching card (`id="card-knee"`), and its `href` goes to the recommended treatment with `?area=`. The area chips beside the photograph (`data-map-chip`) behave the same way.

- Mouse: hovering shows the card; clicking follows the link.
- Keyboard: focusing shows the card; Enter follows the link.
- Touch: the first tap shows the card; the card's link or a second tap follows it.
- `data-default-area` on the stage chooses the card shown on load.

Under 700px the card docks below the photograph. Without JavaScript all six cards show as a plain list beside the photograph.

To use a different photograph, keep a portrait image (2:3 here), then move each hotspot's `--x` and `--y` to the right body part. Add or remove areas by adding or removing a hotspot, chip and card with the same area name.

### Booking Form

`book.html` is an **unwired static front end**. Fields are named `treatment`, `clinician`, `slot`, `name`, `email`, `phone` and `note`. With JavaScript it becomes four steps with validation per step, a live summary and a "Prepare my request" button that writes an unsent request the visitor can copy. Without JavaScript it is one long form with a visible notice that nothing is sent.

- `?treatment=sports-massage` and `?clinician=priya` pre-select choices (treatment pages and team links use these).
- Each clinician choice lists the treatments they offer in `data-offers`; the others are hidden when a treatment is chosen.
- The time slots are example weekday times. Replace them with your real availability, or drop the step and link to your practice system's booking page.

To take real requests, point the form at Formspree, Netlify Forms or your CRM, change `method="dialog"` to the method your service needs, replace the `submit` handler in `initBooking` with your delivery code, and update the visible notice. Only say a request was sent after your service confirms it.

### Palette

| Token | Default | Purpose |
| --- | --- | --- |
| `--ground` | `#EEF0EF` | Cool clinical grey page |
| `--card` | `#FFFFFF` | Rows, cards and panels |
| `--ink` | `#13201D` | All text, dark buttons and the footer |
| `--signal` | `#E8572B` | Hotspots, the booking pill, the transition and the "you are here" dot |

Each has a matching `-rgb` triple used for translucent values; change both. Secondary text is the ink at 70% opacity (5.8:1 on the ground). The signal colour carries ink text on the booking pill (4.7:1) and is never used for text on the grey ground. If you choose a new signal colour, keep at least 4.5:1 against the ink and 3:1 against the ground.

Type is Newsreader (light, with italic for one accent word) for display and Geist for everything else.

### Accessibility and Fallbacks

- Real links everywhere, a skip link, visible focus, labelled form controls and one `h1` per page.
- The transition layer is `aria-hidden`. Scrolling is held while it runs and the arriving heading is focused and announced through a polite live region.
- Hotspots are links with descriptions; filter chips are buttons with `aria-pressed`; the booking stepper marks the current step.
- Reduced motion swaps pages instantly with no disc, shows the hero as a static inset card and removes reveals.
- No JavaScript, an unavailable GSAP CDN or opening from `file://`: links load pages normally and all content is visible.

### Dependencies

The demo is pinned to **GSAP 3.15.0** with ScrollTrigger. Compatibility floor: **GSAP 3.12+**, with core and plugin on matching versions. No Lenis, no other plugins, no backend.

### Images and Credits

The download contains seventeen cropped, graded WebP derivatives in `assets/img/`. Third-party brand marks and printed text (clothing logos, scrub logos, signs and stickers) were retouched out of `hero.webp`, `physiotherapy.webp`, `studio.webp`, `reception.webp` and `sports-massage.webp`; the edits are limited to those marks.

Treatment photography is licensed through [Pexels](https://www.pexels.com/license/), which permits use in website templates. The photographs show unrelated people and rooms, not Fulcrum's staff or patients.

| File | Source | Subject |
| --- | --- | --- |
| `hero.webp` | [Pexels 20860610](https://www.pexels.com/photo/20860610/) | Physiotherapist supporting a client lying on his side |
| `physiotherapy.webp` | [Pexels 20860576](https://www.pexels.com/photo/20860576/) | Shoulder assessment, client seated |
| `sports-massage.webp` | [Pexels 5793954](https://www.pexels.com/photo/5793954/) | Shoulder treatment, client seated on a couch by a window |
| `clinical-pilates.webp` | [Pexels 25596676](https://www.pexels.com/photo/25596676/) | Side stretch on a wooden reformer |
| `detail-knee.webp` | [Pexels 20860607](https://www.pexels.com/photo/20860607/) | Hands treating a knee (cropped) |
| `detail-neck.webp` | [Pexels 20860604](https://www.pexels.com/photo/20860604/) | Hands on the neck and shoulder |
| `detail-reformer.webp` | [Pexels 8769176](https://www.pexels.com/photo/8769176/) | Reformer work in a bright studio |
| `studio.webp` | [Pexels 20860619](https://www.pexels.com/photo/20860619/) | Floor exercise in a rehabilitation room |
| `physio-moment.webp` | [Pexels 5793651](https://www.pexels.com/photo/5793651/) | Standing alignment check by a window |
| `massage-moment.webp` | [Pexels 3881012](https://www.pexels.com/photo/3881012/) | Neck and shoulder massage, client lying face down |
| `pilates-moment.webp` | [Pexels 8769163](https://www.pexels.com/photo/8769163/) | Three clients on reformers, arms overhead |
| `reception.webp` | [Pexels 8459996](https://www.pexels.com/photo/8459996/) | Waiting area with blue chairs and reception counter |

The four clinician portraits (`clinician-hannah.webp`, `clinician-james.webp`, `clinician-priya.webp`, `clinician-sam.webp`) and the body-map figure (`body-map.webp`) are **AI-generated** images of people who do not exist, made for this template. Replace them with photographs of your real team before launch; never present generated portraits as real staff.

To replace an image, keep its filename or update every path, its `width`/`height`, alt text and caption. The Vault authoring source includes `assets/img-manifest.json` with original URLs, crops and grades; in the Vault checkout it regenerates with `bun scripts/build-template-assets.ts physiotherapy-clinic-template --force`. The manifest and source files are authoring inputs; your site only needs the files in `assets/img/`.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium template, not sold individually: it comes with the Templates Pass or the Vault. The standard licence covers unlimited personal and commercial projects with no attribution required for our code. Bundled third-party assets retain their own licences and attribution requirements. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Templates Pass (£50 one-time): every current and future premium template](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
