Build notes · musictherapy
How the Common Chord page was built
A landing page for a fictional music therapy practice in Victoria Park. It is for the parent, support coordinator or adult child who has been told music therapy is worth a try and needs to know what a term actually is. The page has one job: show exactly what a ten-week term contains and costs before the first phone call, without promising anything about what the sessions will do.
Why this converts
- The call-back button sits in the header, the hero, the planner and the mobile bar, and every one of them books the free 15-minute chat rather than a term, because a first-time buyer in allied health is more likely to agree to a free call than to a paid booking.
- The form asks only what a therapist needs before that call (name, phone, suburb, who the sessions are for, how they will be paid for), and the funding question is a neutral list with “Not sure yet” in it, so nobody stops at a question they cannot answer.
- The term planner answers the question people are too embarrassed to ring about, which is the whole cost, and it puts the $185 report fee in writing before any total so the number never grows later.
- The cheaper fortnightly term is priced beside the weekly one in every state, with the honest note that it is a different plan rather than a discount, and that single admission is what makes the dearer figure believable.
- The trust line is professional registration, a free first call and a report inside every total, not a star rating. On the real practice’s page that registration is something a family can look up on the association’s own directory, and the people this page is for check before they ring.
Palette
The blue of printed staves, calm rather than clinical. Moss marks what is included: the report tag, the trust tick and the “included” line in the ledger. Every ratio below is pasted from contrast-w59.log, and every text token lands only on a ground that log declares for it.
- bg #F7F6F2Page ground. Ink 15.18:1, muted 7.17:1, primary 8.80:1, accent 5.88:1.
- surface #FFFFFFCards. Ink 16.42:1, muted 7.75:1, primary 9.52:1, accent 6.35:1.
- ink #1E1F26Body copy and headings.
- muted #50525ESecondary copy, the row you did not pick, rests on the stave.
- primary #2F3E8FManuscript cobalt. CTA fill with white at 9.52:1; the notes of your chosen term.
- accent #2E6B45Moss. Report tag with white at 6.35:1; the aged-care ring on the map.
- band #1F2340Footer and demo band, with #F3F2F7 at 13.74:1.
- minted: stave #C4C8DAStave lines and weekly barlines, 1.66:1 on white. Decoration only: every figure the strip carries is in text beside it.
- minted: water #DCE4F0The two rivers on the map, 1.28:1 on white. No label is ever drawn on it; labels carry a white halo.
- minted: field border #8A8C98Form input edges, 3.34:1 on white, above the 3:1 needed for a control boundary.
Type
Ten weeks, one goal, written down.
Atkinson Hyperlegible 700 — 10 sessions × $140.00
Atkinson Hyperlegible 400 at 17px. Il1 O0 rn m are all different shapes.
Atkinson Hyperlegible carries every word you have to read. The Braille Institute commissioned it for readers with low vision, which is why its similar letters look different on purpose: capital I, lower-case l and the digit 1 can’t be mixed up, and neither can O and 0. On this page that is not decoration. The people reading it include older adults choosing for a parent in aged care, and support coordinators reading fee tables on a phone between visits, so the body is set at 17px and the figures use tabular numerals. A coordinator who notices the face is choosing a practice that noticed its readers.
Young Serif sets the headings and the term total. It is round and warm rather than academic, so it reads as a small practice with a person answering the phone, and it gives the one number that matters a different voice from the arithmetic above it.
The proof element: a ten-week term strip
The planner has three controls: session length (30, 45 or 60 minutes), frequency (weekly or fortnightly) and setting (clinic, or home visit for $30 more). Under them are two rows, weekly and fortnightly, at the same size and always visible together. Each row is a hand-built SVG stave of ten bars, one per week, redrawn in real CSS pixels at every width so the labels never shrink with a scaled viewBox. A booked week gets a note, and a week off gets a whole rest. The note sits higher on the stave for a longer session. After a double barline, which in music marks the end of a piece and here marks the end of the term, a moss tag reads report.
The report fee is stated in the sentence above the controls before any figure appears, and again as its own ledger line above the total. Line items print to the cent. The total is a sum of whole dollars, so nothing is rounded except the per-week average, and that is rounded once, to the cent. The fees come straight from figures-w59.mjs: 30 min $95, 45 min $140, 60 min $185, home +$30, report $185, with 10 sessions weekly or 5 fortnightly.
| Worked example (from the spec) | Arithmetic | Shown on the page |
|---|---|---|
| Weekly, 45 min, clinic | 10 × $140 + $185 | $1,585 · $158.50 a week |
| Fortnightly, 45 min, clinic | 5 × $140 + $185 | $885 · $700 less |
| Weekly, 60 min, home visit | 10 × $215 + $185 | $2,335 · clinic $300 less |
| Cheapest term: fortnightly, 30 min, clinic | 5 × $95 + $185 | $660 = the services-grid “from” |
The state probe window.__musictherapy exposes the inputs, per-session fee, sessions, report, total, per-week average, both rows, the alternative and isSubstitute. That boolean is false in every state, by design. A page that makes no claim about what sessions achieve cannot say that five sessions do the job of ten, so the cheaper option is always shown with its reason attached and never as an equivalent. With a home visit selected, the page also prints the same term in the clinic, which is a like-for-like saving.
The entrance plays the notes left to right, 70 ms apart, on wall-clock time, and comes to rest well inside a second and a half, with a 2.6-second backstop. Reduced motion draws the finished strip straight away. Resizing redraws the finished strip without replaying the entrance.
What this page declined to publish
The spec’s carve-out says no NDIS price limits, item numbers or registration rules unless they are verified at ndis.gov.au or austmta.org.au. These were considered and left off both pages:
- Any NDIS rate for music therapy. An NDIA statement on ndis.gov.au quotes hourly rates, but the NDIA now marks that page’s advice as changed. A figure the regulator has flagged as superseded has no place on a page that tells people to check the regulator.
- Support item numbers, travel-claiming rules and registered-provider rules for each way a plan can be managed. The FAQ names the three management types and says a plan manager pays providers, both quoted from ndis.gov.au, then says the practice can explain on the phone how a plan type affects this.
- Any rule about who may deliver NDIS-funded music therapy. A search summary suggested one, but we could not find it stated on the AMTA page we verified, so it is not printed. The RMT answer uses only what that page says about registration, training and professional development.
- Any outcome. No conditions, no percentages, no before-and-after. The reviews describe phone calls, lounges, guitars and invoices.
Iteration log
Each pass drove the planner through the four worked examples and all twelve length × frequency × setting cells against a Node model, and drove the form empty, with rubbish in the phone field, and filled in. It then looked at screenshots at 375, 768, 1280 and 1440 and at the 1200×750 thumbnail captured at 7 seconds.
-
Pass 1 — Craft
- The wordmark rendered in capitals:
.wordmark spanalso matched the outer span wrapping the name, so the uppercase tracking of the sub-line leaked into it. Scoped to its own class. - At 375 the map card ran 8 px past the viewport. Its suburb lists sat in grid items with the default
min-width:auto, and a two-column list inside a two-column grid split words mid-name. Fixed withminmax(0,1fr)tracks,min-width:0and a single-column group on phones. - The sticky masthead covered the top of every anchor target, including the form heading that four buttons jump to. Added
scroll-padding-topandscroll-padding-bottomfor the mobile bar. - At 1280, map labels collided in two places, and every ring line cut through the words it crossed. Moved four labels and gave all labels a white halo with
paint-order:stroke. The duplicate legend went; its line samples moved into the list headings. - In the how-it-works row the four step headings sat at different heights because the grid stretched its rows. Fixed with
align-content:start. The reviews heading dropped an orphaned “us”, so it was reworded. - The form intro promised “five short questions” above seven fields. It now says five need an answer.
- Measured: $1,585 / $158.50, $885 / $700 less, $2,335 with clinic $2,035, and $660 all matched; 12 of 12 grid cells matched the model. Empty submit showed 5 errors and focused the name field. “ring me maybe” in the phone field was rejected, and the pattern attribute also rejects “12345678abc”, so it is alive under Chrome’s
vflag. A filled submit confirmed and quoted the $1,585 term.
- The wordmark rendered in capitals:
-
Pass 2 — Depth
- The strip already encoded three things nobody was told about: note height is session length, a whole rest is a week off, and the double bar is the end of the term. A one-line key under the week numbers now says so, which turns a chart into something a parent can read aloud.
- Changing the session length used to redraw the notes at their new height instantly. Now they glide there over 0.3 s, so the reader sees longer sessions sitting higher. The drive asserts the transition is running straight after the change and cleared again by 650 ms. Reduced motion skips it.
- With a home visit chosen, both row labels now read “10 home visits” and “5 home visits”, not just “sessions”, so the setting shows up in the drawing and not only in the ledger.
- An FAQ line suggested readers could look this practice up on the association’s directory. A fictional practice can’t be found there, so the line now points to the directory in general.
- The key line moved the ledger total from 805 px to 858 px at 1200 wide. That was accepted: the answer the thumbnail needs is the row total at 468 px, and the whole strip ends at 648 px, both measured and both still inside 750.
-
Pass 3 — Hardening
- The empty-submit error state at 375 painted a black bar on every funding radio button, because
.field.bad inputmatched the radios as well as the text boxes. The rule is now scoped to non-radio inputs, the radio group gets one border, and the drive asserts the radios carry no box-shadow. - Chanel rule: the footer’s “On this page” column went. It repeated four links that the masthead, the hero and the mobile bar already cover.
- The test drive itself was missing clicks on the mobile form. The page scrolls smoothly, so a click sent straight after scrolling landed where the button had been. It was not a page fault, but it hid the junk-phone test for two runs, so every driven scroll is now instant.
- Checks added and passing: resizing mid-entrance still comes to rest fully opaque; ArrowRight on the length chips moves 45 to 60 minutes and prints $2,035; reduced motion draws the finished strip immediately; the probe reads the same at 7 and 15 seconds; the map-label hide rule matches 17 elements at 375; and the proof card’s computed grid area is the hero’s second column at 1200.
- No horizontal overflow at 375, 768 or 1440, no console errors on either page, the phone
patterncompiles under thevflag, and neither file has a curly quote inside an attribute. There is no canvas or WebGL on the page, so device-pixel-ratio handling does not apply. The strip is SVG, redrawn in CSS pixels on resize. - Final drive: 93 checks, 0 failures.
- The empty-submit error state at 375 painted a black bar on every funding radio button, because
Local SEO we would implement for the real practice
The live page carries only a WebPage block that calls itself a demonstration, because structured data describing a fictional business would be dishonest markup in a real index. For the real practice we would ship this, filled from their Google Business Profile, with reviews only ever taken from a genuine source:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": ["LocalBusiness", "MedicalBusiness"],
"name": "[Practice name]",
"url": "https://[practice-domain].com.au/",
"telephone": "+61 8 [real number]",
"address": {
"@type": "PostalAddress",
"streetAddress": "[clinic street address]",
"addressLocality": "Victoria Park",
"addressRegion": "WA",
"postalCode": "6100",
"addressCountry": "AU"
},
"areaServed": ["Victoria Park", "East Victoria Park", "Lathlain",
"Burswood", "Carlisle", "Rivervale", "Kensington", "Bentley", "South Perth"],
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "08:00", "closes": "18:00"
}],
"makesOffer": [{
"@type": "Offer",
"name": "Individual music therapy session, 45 minutes",
"price": "[their fee]", "priceCurrency": "AUD"
}],
"review": [{
"@type": "Review",
"author": { "@type": "Person", "name": "[reviewer name, with consent]" },
"reviewBody": "[verbatim text from a genuine review]"
}]
}
</script>
Alongside it: a Google Business Profile with the category and suburb names matching the page, a link to the therapists’ listings on the AMTA directory, and one short page per setting (clinic, home visits, aged care) targeting the searches families actually type.
What changes for the real client
- Booking and the free call. The form posts to their practice software rather than a local confirmation. Cliniko, Splose and Nookal all take online bookings, so the “free 15-minute call” becomes a real appointment type with its own calendar slots, and the planner’s summary rides along in the booking notes.
- Plan-manager invoicing. Plan-managed families need invoices addressed so their plan manager can pay them. We would set up the practice software’s invoice template and the fee schedule once, so the planner and the invoice can’t drift apart, and have the practice confirm the funding wording before launch.
- Fees in one place. The planner reads the same fee table the invoices do, so a price change is one edit, not a hunt through the page.
- Their people and rooms. Their therapists’ names and AMTA registration details, their own photographs of the clinic room, and the real home-visit boundary drawn on the map.
- Reviews. Real reviews from their Google Business Profile, with consent, in place of the demonstration copy, still with no outcome language, which the practice would want for its own professional standards anyway.