From 5af5b82dd38b55dc1ff7f8186885b7a8ada9a0b1 Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 10:34:11 +0100 Subject: [PATCH 1/9] Add new NHS website opt-out journey Scaffolds a non-app, standard nhsuk-frontend styled opt-out flow alongside the existing app journeys, under app/views/website/pages/opt-out. Includes start, preference selection, and confirmation pages plus the POST handler in routes.js, and links it from the homepage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/routes.js | 17 +++++++ app/views/index.html | 8 +++ .../pages/opt-out/confirmation-saved-no.html | 27 ++++++++++ .../pages/opt-out/confirmation-saved-yes.html | 28 ++++++++++ .../website/pages/opt-out/preferences-1.html | 51 +++++++++++++++++++ app/views/website/pages/opt-out/start.html | 35 +++++++++++++ 6 files changed, 166 insertions(+) create mode 100644 app/views/website/pages/opt-out/confirmation-saved-no.html create mode 100644 app/views/website/pages/opt-out/confirmation-saved-yes.html create mode 100644 app/views/website/pages/opt-out/preferences-1.html create mode 100644 app/views/website/pages/opt-out/start.html diff --git a/app/routes.js b/app/routes.js index 90eff4cf..f2485521 100644 --- a/app/routes.js +++ b/app/routes.js @@ -70,6 +70,23 @@ } }) + // Website (non-app) journey routes + + router.post('/website/pages/opt-out/preferences-1-post', function (req, res) { + const input = req.session.data['stop-messages'] + + if (input === 'Yes') { + res.redirect('/website/pages/opt-out/confirmation-saved-yes') + } else if (input === 'No') { + res.redirect('/website/pages/opt-out/confirmation-saved-no') + } else { + // Validation fallback if they select nothing + res.render('website/pages/opt-out/preferences-1', { + error: true + }) + } + }) + // V6 Routes router.post('/v6/pages/opt-in/preferences-1-post', function (req, res) { diff --git a/app/views/index.html b/app/views/index.html index 3e5e753f..4f0b9f6b 100755 --- a/app/views/index.html +++ b/app/views/index.html @@ -14,6 +14,14 @@

Digital Child Health NHS App prototype

A prototype for Digital Child Health to test new design components and patterns for the NHS App.

+

NHS Website journeys

+

A non-app, standard NHS website version of the opt-out flow.

+ +

V6

Content designer has been added to the team

21/07/2025 Updated the flow to reflect an "unsubscribe" route.

diff --git a/app/views/website/pages/opt-out/confirmation-saved-no.html b/app/views/website/pages/opt-out/confirmation-saved-no.html new file mode 100644 index 00000000..5191e09e --- /dev/null +++ b/app/views/website/pages/opt-out/confirmation-saved-no.html @@ -0,0 +1,27 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Your preference has been saved" %} + +{% block content %} + +
+
+ +

{{ pageHeading }}

+ + {% from 'nhsuk/components/inset-text/macro.njk' import insetText %} + {{ insetText({ + html: "

You will continue to receive age-based messages from us.

" + }) }} + +

You can change this preference at any time.

+ +

More information

+

Visit our privacy notice for more information on how the NHS uses your data.

+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/confirmation-saved-yes.html b/app/views/website/pages/opt-out/confirmation-saved-yes.html new file mode 100644 index 00000000..64a8921b --- /dev/null +++ b/app/views/website/pages/opt-out/confirmation-saved-yes.html @@ -0,0 +1,28 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "You have unsubscribed from age-based messages" %} + +{% block content %} + +
+
+ +

{{ pageHeading }}

+ + {% from 'nhsuk/components/inset-text/macro.njk' import insetText %} + {{ insetText({ + html: "

This confirms that you will no longer receive age-based messages from us.

" + }) }} + +

It may take up to one working day to update.

+

Support and guidance for you and your baby is always available at Best Start in Life.

+ +

More information

+

Visit our privacy notice for more information on how the NHS uses your data.

+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/preferences-1.html b/app/views/website/pages/opt-out/preferences-1.html new file mode 100644 index 00000000..64b69e91 --- /dev/null +++ b/app/views/website/pages/opt-out/preferences-1.html @@ -0,0 +1,51 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Would you like to stop receiving NHS age-based messages?" %} + +{% block content %} + +
+
+ +
+ + {% from "radios/macro.njk" import radios %} + + {{ radios({ + idPrefix: "stop-messages", + name: "stop-messages", + errorMessage: { text: "Select an option" } if error, + fieldset: { + legend: { + text: pageHeading, + classes: "nhsuk-fieldset__legend--l", + isPageHeading: true + } + }, + hint: { + text: "Select 1 option" + }, + items: [ + { + value: "Yes", + text: "Yes, stop sending me messages" + }, + { + value: "No", + text: "No, keep sending me messages" + } + ] + }) }} + + {{ button({ + text: "Save" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html new file mode 100644 index 00000000..cf59880d --- /dev/null +++ b/app/views/website/pages/opt-out/start.html @@ -0,0 +1,35 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Stop receiving age-based messages" %} + +{% block content %} + +
+
+ +

{{ pageHeading }}

+ +

We'll need your:

+
    +
  • name
  • +
  • date of birth
  • +
  • postcode or NHS number
  • +
+ +

We'll use these details to find your contact details from your health records so we can confirm your preference.

+ + {{ button({ + text: "Continue", + href: "/website/pages/opt-out/preferences-1" + }) }} + +

+ How your data will be processed using this service (opens in new window). +

+ +
+
+ +{% endblock %} From be11d290a2ecb43dee833aeb93b549c17bf023ea Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 10:37:25 +0100 Subject: [PATCH 2/9] Update opt-out start page copy to match design Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/views/website/pages/opt-out/start.html | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html index cf59880d..55280145 100644 --- a/app/views/website/pages/opt-out/start.html +++ b/app/views/website/pages/opt-out/start.html @@ -2,7 +2,7 @@ {% set version = "website" %} {% set hub = "Opt Out" %} {% set backLink = true %} -{% set pageHeading = "Stop receiving age-based messages" %} +{% set pageHeading = "Unsubscribe from Age-Based Messages" %} {% block content %} @@ -11,24 +11,25 @@

{{ pageHeading }}

+

You were automatically signed up to receive timed reminders based on your baby's age, including information about appointments, check-ups and more.

+ +

You can use this service to unsubscribe from these messages.

+ +

You'll need to confirm your identity before you can make changes.

+

We'll need your:

-

We'll use these details to find your contact details from your health records so we can confirm your preference.

- {{ button({ text: "Continue", href: "/website/pages/opt-out/preferences-1" }) }} -

- How your data will be processed using this service (opens in new window). -

- From 413299f46e4ff84fa32cf52c7e4d680ce46670ef Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 10:48:48 +0100 Subject: [PATCH 3/9] Build full NHS website opt-out journey with identity verification Adds the remaining pages and routing for the opt-out flow, matching the supplied design screenshots and flow diagram: - do-you-know-nhs-number (branches to NHS number or name/DOB path) - enter-your-nhs-number / enter-your-name / enter-your-postcode / enter-date-of-birth - check-your-details-nhs-number / check-your-details (confirm identity) - identity-details-error (simulated identity check failure, loops back to retry) - confirm-unsubscribe-request (renamed from preferences-1, now the final step) - confirmation-saved-yes / confirmation-saved-no updated to use the nhsuk panel component and match the 'What happens next' / 'Before you leave this page' design Routing added in app/routes.js for every POST step, including branching logic so the postcode page is shared by both identity paths, and a simulated identity match (postcode SW1 2CV) that triggers the error page. Also adds app/views/website/pages/opt-out/README.md with a Mermaid flow diagram documenting the full journey and routing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/routes.js | 96 +++++++++++++++++-- app/views/website/pages/opt-out/README.md | 48 ++++++++++ .../check-your-details-nhs-number.html | 51 ++++++++++ .../pages/opt-out/check-your-details.html | 60 ++++++++++++ ....html => confirm-unsubscribe-request.html} | 21 ++-- .../pages/opt-out/confirmation-saved-no.html | 22 +++-- .../pages/opt-out/confirmation-saved-yes.html | 24 ++--- .../pages/opt-out/do-you-know-nhs-number.html | 48 ++++++++++ .../pages/opt-out/enter-date-of-birth.html | 51 ++++++++++ .../pages/opt-out/enter-your-name.html | 42 ++++++++ .../pages/opt-out/enter-your-nhs-number.html | 40 ++++++++ .../pages/opt-out/enter-your-postcode.html | 36 +++++++ .../pages/opt-out/identity-details-error.html | 22 +++++ app/views/website/pages/opt-out/start.html | 2 +- 14 files changed, 523 insertions(+), 40 deletions(-) create mode 100644 app/views/website/pages/opt-out/README.md create mode 100644 app/views/website/pages/opt-out/check-your-details-nhs-number.html create mode 100644 app/views/website/pages/opt-out/check-your-details.html rename app/views/website/pages/opt-out/{preferences-1.html => confirm-unsubscribe-request.html} (61%) create mode 100644 app/views/website/pages/opt-out/do-you-know-nhs-number.html create mode 100644 app/views/website/pages/opt-out/enter-date-of-birth.html create mode 100644 app/views/website/pages/opt-out/enter-your-name.html create mode 100644 app/views/website/pages/opt-out/enter-your-nhs-number.html create mode 100644 app/views/website/pages/opt-out/enter-your-postcode.html create mode 100644 app/views/website/pages/opt-out/identity-details-error.html diff --git a/app/routes.js b/app/routes.js index f2485521..72a028cd 100644 --- a/app/routes.js +++ b/app/routes.js @@ -70,18 +70,102 @@ } }) - // Website (non-app) journey routes + // Website (non-app) opt-out journey routes - router.post('/website/pages/opt-out/preferences-1-post', function (req, res) { - const input = req.session.data['stop-messages'] + router.post('/website/pages/opt-out/do-you-know-nhs-number-post', function (req, res) { + const input = req.session.data['do-you-know-nhs-number'] - if (input === 'Yes') { + if (input === 'yes') { + res.redirect('/website/pages/opt-out/enter-your-nhs-number') + } else if (input === 'no') { + res.redirect('/website/pages/opt-out/enter-your-name') + } else { + // Validation fallback if they select nothing + res.render('website/pages/opt-out/do-you-know-nhs-number', { + error: true + }) + } + }) + + router.post('/website/pages/opt-out/enter-your-nhs-number-post', function (req, res) { + const input = req.session.data['your-nhs-number'] + + if (!input || input.trim() === '') { + res.render('website/pages/opt-out/enter-your-nhs-number', { + error: true + }) + } else { + res.redirect('/website/pages/opt-out/enter-your-postcode') + } + }) + + router.post('/website/pages/opt-out/enter-your-name-post', function (req, res) { + const firstName = req.session.data['first-name'] + const lastName = req.session.data['last-name'] + + if (!firstName || !lastName) { + res.render('website/pages/opt-out/enter-your-name', { + error: true + }) + } else { + res.redirect('/website/pages/opt-out/enter-your-postcode') + } + }) + + // The postcode page is shared by both the NHS number and name/date of + // birth routes through identity verification - branch based on whether + // an NHS number was already given. + router.post('/website/pages/opt-out/enter-your-postcode-post', function (req, res) { + const postcode = req.session.data['your-postcode'] + const hasNhsNumber = req.session.data['do-you-know-nhs-number'] === 'yes' + + if (!postcode || postcode.trim() === '') { + res.render('website/pages/opt-out/enter-your-postcode', { + error: true + }) + } else if (hasNhsNumber) { + res.redirect('/website/pages/opt-out/check-your-details-nhs-number') + } else { + res.redirect('/website/pages/opt-out/enter-date-of-birth') + } + }) + + router.post('/website/pages/opt-out/enter-date-of-birth-post', function (req, res) { + res.redirect('/website/pages/opt-out/check-your-details') + }) + + router.post('/website/pages/opt-out/check-your-details-nhs-number-post', function (req, res) { + // Simulate an identity check against the example patient record + const postcode = (req.session.data['your-postcode'] || '').replace(/\s+/g, '').toUpperCase() + + if (postcode !== 'SW12CV') { + res.redirect('/website/pages/opt-out/identity-details-error') + } else { + res.redirect('/website/pages/opt-out/confirm-unsubscribe-request') + } + }) + + router.post('/website/pages/opt-out/check-your-details-post', function (req, res) { + // Simulate an identity check against the example patient record + const postcode = (req.session.data['your-postcode'] || '').replace(/\s+/g, '').toUpperCase() + + if (postcode !== 'SW12CV') { + res.redirect('/website/pages/opt-out/identity-details-error') + } else { + res.redirect('/website/pages/opt-out/confirm-unsubscribe-request') + } + }) + + router.post('/website/pages/opt-out/confirm-unsubscribe-request-post', function (req, res) { + const input = req.session.data['confirm-unsubscribe'] + + if (input === 'unsubscribe') { res.redirect('/website/pages/opt-out/confirmation-saved-yes') - } else if (input === 'No') { + } else if (input === 'keep') { res.redirect('/website/pages/opt-out/confirmation-saved-no') } else { // Validation fallback if they select nothing - res.render('website/pages/opt-out/preferences-1', { + res.render('website/pages/opt-out/confirm-unsubscribe-request', { error: true }) } diff --git a/app/views/website/pages/opt-out/README.md b/app/views/website/pages/opt-out/README.md new file mode 100644 index 00000000..9f596f4c --- /dev/null +++ b/app/views/website/pages/opt-out/README.md @@ -0,0 +1,48 @@ +# NHS website opt-out journey — flow diagram + +Non-app, standard NHS website version of the age-based messages opt-out flow. +Routes live under `/website/pages/opt-out/`, views in +`app/views/website/pages/opt-out/`, and POST handlers in `app/routes.js`. + +```mermaid +flowchart TD + start["01 start
Unsubscribe introduction"] + nhsChoice["05 do-you-know-nhs-number
Do you know your NHS number?"] + enterNhs["06 enter-your-nhs-number
What is your NHS number?"] + enterName["09 enter-your-name
Enter your full name"] + postcode["03 enter-your-postcode
What is your post code"] + dob["02 enter-date-of-birth
What is your date of birth?"] + checkNhs["07 check-your-details-nhs-number
Confirm details (NHS number + postcode)"] + checkNoNhs["08 check-your-details
Confirm details (name, DOB, postcode)"] + error["04 identity-details-error
We can't identify you"] + confirmRequest["13 confirm-unsubscribe-request
Keep or unsubscribe?"] + keep["11 confirmation-saved-no
You will continue to receive messages"] + unsub["12 confirmation-saved-yes
You will no longer receive messages"] + + start --> nhsChoice + nhsChoice -- Yes --> enterNhs + nhsChoice -- No --> enterName + enterNhs --> postcode + enterName --> postcode + postcode -- "has NHS number" --> checkNhs + postcode -- "no NHS number" --> dob + dob --> checkNoNhs + checkNhs -- "identity matched" --> confirmRequest + checkNhs -- "identity not matched" --> error + checkNoNhs -- "identity matched" --> confirmRequest + checkNoNhs -- "identity not matched" --> error + error -- Continue --> nhsChoice + confirmRequest -- Keep --> keep + confirmRequest -- Unsubscribe --> unsub +``` + +## Notes + +- The postcode step is shared by both identity paths (NHS number, or + name + date of birth). +- The identity check is simulated in `app/routes.js`: enter postcode + `SW1 2CV` to pass verification on either path; anything else routes to + the `identity-details-error` page, whose Continue button loops back to + `do-you-know-nhs-number` to retry. +- Both confirmation pages (`confirmation-saved-yes` / `confirmation-saved-no`) + use the standard `nhsuk-frontend` panel component, not app-specific styling. diff --git a/app/views/website/pages/opt-out/check-your-details-nhs-number.html b/app/views/website/pages/opt-out/check-your-details-nhs-number.html new file mode 100644 index 00000000..a3d1bd7d --- /dev/null +++ b/app/views/website/pages/opt-out/check-your-details-nhs-number.html @@ -0,0 +1,51 @@ +{% from "summary-list/macro.njk" import summaryList %} +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Confirm your details" %} + +{% block content %} + +
+
+
+
+ +

{{ pageHeading }}

+ + {{ summaryList({ + rows: [ + { + key: { text: "NHS number" }, + value: { text: data['your-nhs-number'] or "2345678912" }, + actions: { + items: [ + { href: "/website/pages/opt-out/enter-your-nhs-number", text: "Change", visuallyHiddenText: "NHS number" } + ] + } + }, + { + key: { text: "Post code" }, + value: { text: data['your-postcode'] or "SW1 2CV" }, + actions: { + items: [ + { href: "/website/pages/opt-out/enter-your-postcode", text: "Change", visuallyHiddenText: "postcode" } + ] + } + } + ] + }) }} + +
+ {{ button({ + text: "Confirm details" + }) }} +
+ +
+
+
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/check-your-details.html b/app/views/website/pages/opt-out/check-your-details.html new file mode 100644 index 00000000..9ce00f06 --- /dev/null +++ b/app/views/website/pages/opt-out/check-your-details.html @@ -0,0 +1,60 @@ +{% from "summary-list/macro.njk" import summaryList %} +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Confirm your details" %} + +{% block content %} + +
+
+
+
+ +

{{ pageHeading }}

+ + {{ summaryList({ + rows: [ + { + key: { text: "Name" }, + value: { text: "First Middle Surname" }, + actions: { + items: [ + { href: "/website/pages/opt-out/enter-your-name", text: "Change", visuallyHiddenText: "name" } + ] + } + }, + { + key: { text: "Date of birth" }, + value: { text: "01 January 1980" }, + actions: { + items: [ + { href: "/website/pages/opt-out/enter-date-of-birth", text: "Change", visuallyHiddenText: "date of birth" } + ] + } + }, + { + key: { text: "Post code" }, + value: { text: data['your-postcode'] or "SW1 2CV" }, + actions: { + items: [ + { href: "/website/pages/opt-out/enter-your-postcode", text: "Change", visuallyHiddenText: "postcode" } + ] + } + } + ] + }) }} + +
+ {{ button({ + text: "Confirm details" + }) }} +
+ +
+
+
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/preferences-1.html b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html similarity index 61% rename from app/views/website/pages/opt-out/preferences-1.html rename to app/views/website/pages/opt-out/confirm-unsubscribe-request.html index 64b69e91..275699ae 100644 --- a/app/views/website/pages/opt-out/preferences-1.html +++ b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html @@ -2,20 +2,20 @@ {% set version = "website" %} {% set hub = "Opt Out" %} {% set backLink = true %} -{% set pageHeading = "Would you like to stop receiving NHS age-based messages?" %} +{% set pageHeading = "Confirm your unsubscribe request" %} {% block content %}
-
+ {% from "radios/macro.njk" import radios %} {{ radios({ - idPrefix: "stop-messages", - name: "stop-messages", + idPrefix: "confirm-unsubscribe", + name: "confirm-unsubscribe", errorMessage: { text: "Select an option" } if error, fieldset: { legend: { @@ -24,23 +24,20 @@ isPageHeading: true } }, - hint: { - text: "Select 1 option" - }, items: [ { - value: "Yes", - text: "Yes, stop sending me messages" + value: "keep", + text: "Keep receiving age-based messages" }, { - value: "No", - text: "No, keep sending me messages" + value: "unsubscribe", + text: "Unsubscribe from age-based messages" } ] }) }} {{ button({ - text: "Save" + text: "Submit" }) }}
diff --git a/app/views/website/pages/opt-out/confirmation-saved-no.html b/app/views/website/pages/opt-out/confirmation-saved-no.html index 5191e09e..4d780e15 100644 --- a/app/views/website/pages/opt-out/confirmation-saved-no.html +++ b/app/views/website/pages/opt-out/confirmation-saved-no.html @@ -1,25 +1,27 @@ +{% from "panel/macro.njk" import panel %} {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Your preference has been saved" %} {% block content %}
-

{{ pageHeading }}

- - {% from 'nhsuk/components/inset-text/macro.njk' import insetText %} - {{ insetText({ - html: "

You will continue to receive age-based messages from us.

" + {{ panel({ + titleText: "You will continue to receive age-based messages.", + titleSize: "l" }) }} -

You can change this preference at any time.

+

What happens next

+

You do not need to do anything else. We will keep sending you timed reminders based on your baby's age.

-

More information

-

Visit our privacy notice for more information on how the NHS uses your data.

+

Before you leave this page

+

You can:

+
diff --git a/app/views/website/pages/opt-out/confirmation-saved-yes.html b/app/views/website/pages/opt-out/confirmation-saved-yes.html index 64a8921b..721c04ac 100644 --- a/app/views/website/pages/opt-out/confirmation-saved-yes.html +++ b/app/views/website/pages/opt-out/confirmation-saved-yes.html @@ -1,26 +1,28 @@ +{% from "panel/macro.njk" import panel %} {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "You have unsubscribed from age-based messages" %} {% block content %}
-

{{ pageHeading }}

- - {% from 'nhsuk/components/inset-text/macro.njk' import insetText %} - {{ insetText({ - html: "

This confirms that you will no longer receive age-based messages from us.

" + {{ panel({ + titleText: "You will no longer receive age-based messages.", + titleSize: "l" }) }} +

What happens next

It may take up to one working day to update.

-

Support and guidance for you and your baby is always available at Best Start in Life.

- -

More information

-

Visit our privacy notice for more information on how the NHS uses your data.

+

You can find support and guidance for you and your baby at Best Start In Life.

+ +

Before you leave this page

+

You can:

+
diff --git a/app/views/website/pages/opt-out/do-you-know-nhs-number.html b/app/views/website/pages/opt-out/do-you-know-nhs-number.html new file mode 100644 index 00000000..41834c7b --- /dev/null +++ b/app/views/website/pages/opt-out/do-you-know-nhs-number.html @@ -0,0 +1,48 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Do you know your NHS number?" %} + +{% block content %} + +
+
+ +
+ + {% from "radios/macro.njk" import radios %} + + {{ radios({ + idPrefix: "do-you-know-nhs-number", + name: "do-you-know-nhs-number", + errorMessage: { text: "Select an option" } if error, + fieldset: { + legend: { + text: pageHeading, + classes: "nhsuk-fieldset__legend--l", + isPageHeading: true + } + }, + items: [ + { + value: "yes", + text: "Yes, I know my NHS number" + }, + { + value: "no", + text: "No, I do not know my NHS number" + } + ] + }) }} + + {{ button({ + text: "Continue" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/enter-date-of-birth.html b/app/views/website/pages/opt-out/enter-date-of-birth.html new file mode 100644 index 00000000..2b814650 --- /dev/null +++ b/app/views/website/pages/opt-out/enter-date-of-birth.html @@ -0,0 +1,51 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "What is your date of birth?" %} + +{% block content %} + +
+
+ +
+ +
+
+ +

{{ pageHeading }}

+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ + {{ button({ + text: "Continue" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/enter-your-name.html b/app/views/website/pages/opt-out/enter-your-name.html new file mode 100644 index 00000000..c26cc0fd --- /dev/null +++ b/app/views/website/pages/opt-out/enter-your-name.html @@ -0,0 +1,42 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "Enter your full name" %} + +{% block content %} + +
+
+ +
+ +

{{ pageHeading }}

+

Use the same full name that you registered with your GP surgery.

+ + {% from "input/macro.njk" import input %} + + {{ input({ + label: { text: "First name" }, + errorMessage: { text: "Enter your first name" } if error, + id: "first-name", + name: "first-name" + }) }} + + {{ input({ + label: { text: "Last name" }, + errorMessage: { text: "Enter your last name" } if error, + id: "last-name", + name: "last-name" + }) }} + + {{ button({ + text: "Continue" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/enter-your-nhs-number.html b/app/views/website/pages/opt-out/enter-your-nhs-number.html new file mode 100644 index 00000000..ab2c75ad --- /dev/null +++ b/app/views/website/pages/opt-out/enter-your-nhs-number.html @@ -0,0 +1,40 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "What is your NHS number?" %} + +{% block content %} + +
+
+ +
+ + {% from "input/macro.njk" import input %} + + {{ input({ + label: { + text: pageHeading, + classes: "nhsuk-label--l", + isPageHeading: true + }, + hint: { + text: "Your NHS number is a 10 digit number that you find on any letter the NHS has sent you. For example, 485 777 3456." + }, + errorMessage: { text: "Enter your NHS number" } if error, + id: "your-nhs-number", + name: "your-nhs-number", + classes: "nhsuk-input--width-20" + }) }} + + {{ button({ + text: "Continue" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/enter-your-postcode.html b/app/views/website/pages/opt-out/enter-your-postcode.html new file mode 100644 index 00000000..7af96fbb --- /dev/null +++ b/app/views/website/pages/opt-out/enter-your-postcode.html @@ -0,0 +1,36 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "What is your post code" %} + +{% block content %} + +
+
+ +
+ +

{{ pageHeading }}

+ + {% from "input/macro.njk" import input %} + + {{ input({ + label: { text: "Enter post code" }, + hint: { text: "For this prototype, enter SW1 2CV to pass identity verification." }, + errorMessage: { text: "Enter your postcode" } if error, + id: "your-postcode", + name: "your-postcode", + classes: "nhsuk-input--width-10" + }) }} + + {{ button({ + text: "Continue" + }) }} + +
+ +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/identity-details-error.html b/app/views/website/pages/opt-out/identity-details-error.html new file mode 100644 index 00000000..d80a89e5 --- /dev/null +++ b/app/views/website/pages/opt-out/identity-details-error.html @@ -0,0 +1,22 @@ +{% extends 'layout.html' %} +{% set version = "website" %} +{% set hub = "Opt Out" %} +{% set backLink = true %} +{% set pageHeading = "We're sorry. We can't identify you at this time. Please check your details and try again." %} + +{% block content %} + +
+
+ +

{{ pageHeading }}

+ + {{ button({ + text: "Continue", + href: "/website/pages/opt-out/do-you-know-nhs-number" + }) }} + +
+
+ +{% endblock %} diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html index 55280145..011fa792 100644 --- a/app/views/website/pages/opt-out/start.html +++ b/app/views/website/pages/opt-out/start.html @@ -27,7 +27,7 @@

{{ pageHeading }}

{{ button({ text: "Continue", - href: "/website/pages/opt-out/preferences-1" + href: "/website/pages/opt-out/do-you-know-nhs-number" }) }}
From a5c02df34b5fe7bdaaa1419cdd0c10501e914eac Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 10:57:21 +0100 Subject: [PATCH 4/9] Align opt-out journey with NHS prototype kit LLM guide Checked the new website opt-out pages against https://github.com/edwardhorsford/NHS-LLM-documentation and fixed several deviations: - Fixed a real bug: '{% set backLink = true %}' does nothing, because layout.html has no beforeContent block that reads it. Replaced with the actual backLink() component (auto-imported) in a beforeContent block on every page, so back links now genuinely render. - Renamed session data keys to camelCase (knowsNhsNumber, nhsNumber, firstName, lastName, postcode, dateOfBirth, confirmUnsubscribe) per the guide's naming convention, updating routes.js and all views to match. - Renamed POST routes to the '-answer' suffix (eg enter-your-name-answer) as shown in the guide's routing examples, and dropped the enter-date-of- birth route entirely since it did no branching or validation - the form now posts straight to check-your-details. - Radio values now match their visible text exactly (Yes/No, Keep receiving.../Unsubscribe from...) instead of arbitrary lowercase codes. - Replaced the hand-rolled date fieldset with NHS Frontend's dateInput component (namePrefix: dateOfBirth), and removed redundant explicit macro imports (radios/input/summaryList/panel) since template-with- imports.njk already provides them globally. - Grouped the two name fields in enter-your-name with a fieldset/legend rather than a bare h1, matching the guide's related-inputs pattern. - Added value prefilling (value: data.xxx) across text inputs, radios and the date input so returning to a page shows previous answers. - Updated app/views/website/pages/opt-out/README.md with notes on these conventions. Re-verified both identity paths (NHS number, and name/DOB) end-to-end via curl, including the error retry loop, after the refactor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/routes.js | 44 ++++++-------- app/views/website/pages/opt-out/README.md | 12 ++++ .../check-your-details-nhs-number.html | 18 +++--- .../pages/opt-out/check-your-details.html | 20 ++++--- .../opt-out/confirm-unsubscribe-request.html | 19 +++--- .../pages/opt-out/do-you-know-nhs-number.html | 26 +++++---- .../pages/opt-out/enter-date-of-birth.html | 58 +++++++++---------- .../pages/opt-out/enter-your-name.html | 58 ++++++++++++------- .../pages/opt-out/enter-your-nhs-number.html | 24 ++++---- .../pages/opt-out/enter-your-postcode.html | 30 ++++++---- .../pages/opt-out/identity-details-error.html | 4 +- app/views/website/pages/opt-out/start.html | 1 - 12 files changed, 174 insertions(+), 140 deletions(-) diff --git a/app/routes.js b/app/routes.js index 72a028cd..12b3ea0d 100644 --- a/app/routes.js +++ b/app/routes.js @@ -72,12 +72,12 @@ // Website (non-app) opt-out journey routes - router.post('/website/pages/opt-out/do-you-know-nhs-number-post', function (req, res) { - const input = req.session.data['do-you-know-nhs-number'] + router.post('/website/pages/opt-out/do-you-know-nhs-number-answer', function (req, res) { + const input = req.session.data.knowsNhsNumber - if (input === 'yes') { + if (input === 'Yes') { res.redirect('/website/pages/opt-out/enter-your-nhs-number') - } else if (input === 'no') { + } else if (input === 'No') { res.redirect('/website/pages/opt-out/enter-your-name') } else { // Validation fallback if they select nothing @@ -87,8 +87,8 @@ } }) - router.post('/website/pages/opt-out/enter-your-nhs-number-post', function (req, res) { - const input = req.session.data['your-nhs-number'] + router.post('/website/pages/opt-out/enter-your-nhs-number-answer', function (req, res) { + const input = req.session.data.nhsNumber if (!input || input.trim() === '') { res.render('website/pages/opt-out/enter-your-nhs-number', { @@ -99,9 +99,8 @@ } }) - router.post('/website/pages/opt-out/enter-your-name-post', function (req, res) { - const firstName = req.session.data['first-name'] - const lastName = req.session.data['last-name'] + router.post('/website/pages/opt-out/enter-your-name-answer', function (req, res) { + const { firstName, lastName } = req.session.data if (!firstName || !lastName) { res.render('website/pages/opt-out/enter-your-name', { @@ -115,28 +114,23 @@ // The postcode page is shared by both the NHS number and name/date of // birth routes through identity verification - branch based on whether // an NHS number was already given. - router.post('/website/pages/opt-out/enter-your-postcode-post', function (req, res) { - const postcode = req.session.data['your-postcode'] - const hasNhsNumber = req.session.data['do-you-know-nhs-number'] === 'yes' + router.post('/website/pages/opt-out/enter-your-postcode-answer', function (req, res) { + const { postcode, knowsNhsNumber } = req.session.data if (!postcode || postcode.trim() === '') { res.render('website/pages/opt-out/enter-your-postcode', { error: true }) - } else if (hasNhsNumber) { + } else if (knowsNhsNumber === 'Yes') { res.redirect('/website/pages/opt-out/check-your-details-nhs-number') } else { res.redirect('/website/pages/opt-out/enter-date-of-birth') } }) - router.post('/website/pages/opt-out/enter-date-of-birth-post', function (req, res) { - res.redirect('/website/pages/opt-out/check-your-details') - }) - - router.post('/website/pages/opt-out/check-your-details-nhs-number-post', function (req, res) { + router.post('/website/pages/opt-out/check-your-details-nhs-number-answer', function (req, res) { // Simulate an identity check against the example patient record - const postcode = (req.session.data['your-postcode'] || '').replace(/\s+/g, '').toUpperCase() + const postcode = (req.session.data.postcode || '').replace(/\s+/g, '').toUpperCase() if (postcode !== 'SW12CV') { res.redirect('/website/pages/opt-out/identity-details-error') @@ -145,9 +139,9 @@ } }) - router.post('/website/pages/opt-out/check-your-details-post', function (req, res) { + router.post('/website/pages/opt-out/check-your-details-answer', function (req, res) { // Simulate an identity check against the example patient record - const postcode = (req.session.data['your-postcode'] || '').replace(/\s+/g, '').toUpperCase() + const postcode = (req.session.data.postcode || '').replace(/\s+/g, '').toUpperCase() if (postcode !== 'SW12CV') { res.redirect('/website/pages/opt-out/identity-details-error') @@ -156,12 +150,12 @@ } }) - router.post('/website/pages/opt-out/confirm-unsubscribe-request-post', function (req, res) { - const input = req.session.data['confirm-unsubscribe'] + router.post('/website/pages/opt-out/confirm-unsubscribe-request-answer', function (req, res) { + const input = req.session.data.confirmUnsubscribe - if (input === 'unsubscribe') { + if (input === 'Unsubscribe from age-based messages') { res.redirect('/website/pages/opt-out/confirmation-saved-yes') - } else if (input === 'keep') { + } else if (input === 'Keep receiving age-based messages') { res.redirect('/website/pages/opt-out/confirmation-saved-no') } else { // Validation fallback if they select nothing diff --git a/app/views/website/pages/opt-out/README.md b/app/views/website/pages/opt-out/README.md index 9f596f4c..6b9bdca9 100644 --- a/app/views/website/pages/opt-out/README.md +++ b/app/views/website/pages/opt-out/README.md @@ -46,3 +46,15 @@ flowchart TD `do-you-know-nhs-number` to retry. - Both confirmation pages (`confirmation-saved-yes` / `confirmation-saved-no`) use the standard `nhsuk-frontend` panel component, not app-specific styling. +- Session data keys use `camelCase` (`knowsNhsNumber`, `nhsNumber`, `firstName`, + `lastName`, `postcode`, `dateOfBirth`, `confirmUnsubscribe`), and radio + values match their visible text exactly, per the + [NHS prototype kit guide](https://github.com/edwardhorsford/NHS-LLM-documentation). +- POST routes use the `-answer` suffix (for example `enter-your-name-answer`) + rather than `-post`, and only exist where branching or validation is + needed — `enter-date-of-birth` posts straight to `check-your-details` + since no route is required there. +- Back links use the real `backLink()` component in a `beforeContent` block. + The rest of this prototype's pages set `{% set backLink = true %}`. which + `layout.html` does not read, so that flag renders nothing — that pattern + is left as-is elsewhere to avoid touching unrelated journeys. diff --git a/app/views/website/pages/opt-out/check-your-details-nhs-number.html b/app/views/website/pages/opt-out/check-your-details-nhs-number.html index a3d1bd7d..0815b896 100644 --- a/app/views/website/pages/opt-out/check-your-details-nhs-number.html +++ b/app/views/website/pages/opt-out/check-your-details-nhs-number.html @@ -1,9 +1,13 @@ -{% from "summary-list/macro.njk" import summaryList %} {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Confirm your details" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/enter-your-postcode", + text: "Back" + }) }} +{% endblock %} {% block content %} @@ -12,13 +16,13 @@
-

{{ pageHeading }}

+

Confirm your details

{{ summaryList({ rows: [ { key: { text: "NHS number" }, - value: { text: data['your-nhs-number'] or "2345678912" }, + value: { text: data.nhsNumber }, actions: { items: [ { href: "/website/pages/opt-out/enter-your-nhs-number", text: "Change", visuallyHiddenText: "NHS number" } @@ -27,7 +31,7 @@

{{ pageHeading }}

}, { key: { text: "Post code" }, - value: { text: data['your-postcode'] or "SW1 2CV" }, + value: { text: data.postcode }, actions: { items: [ { href: "/website/pages/opt-out/enter-your-postcode", text: "Change", visuallyHiddenText: "postcode" } @@ -37,7 +41,7 @@

{{ pageHeading }}

] }) }} -
+ {{ button({ text: "Confirm details" }) }} diff --git a/app/views/website/pages/opt-out/check-your-details.html b/app/views/website/pages/opt-out/check-your-details.html index 9ce00f06..9739da9e 100644 --- a/app/views/website/pages/opt-out/check-your-details.html +++ b/app/views/website/pages/opt-out/check-your-details.html @@ -1,9 +1,13 @@ -{% from "summary-list/macro.njk" import summaryList %} {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Confirm your details" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/enter-date-of-birth", + text: "Back" + }) }} +{% endblock %} {% block content %} @@ -12,13 +16,13 @@
-

{{ pageHeading }}

+

Confirm your details

{{ summaryList({ rows: [ { key: { text: "Name" }, - value: { text: "First Middle Surname" }, + value: { text: data.firstName + " " + data.lastName }, actions: { items: [ { href: "/website/pages/opt-out/enter-your-name", text: "Change", visuallyHiddenText: "name" } @@ -27,7 +31,7 @@

{{ pageHeading }}

}, { key: { text: "Date of birth" }, - value: { text: "01 January 1980" }, + value: { text: data.dateOfBirth.day + " " + data.dateOfBirth.month + " " + data.dateOfBirth.year }, actions: { items: [ { href: "/website/pages/opt-out/enter-date-of-birth", text: "Change", visuallyHiddenText: "date of birth" } @@ -36,7 +40,7 @@

{{ pageHeading }}

}, { key: { text: "Post code" }, - value: { text: data['your-postcode'] or "SW1 2CV" }, + value: { text: data.postcode }, actions: { items: [ { href: "/website/pages/opt-out/enter-your-postcode", text: "Change", visuallyHiddenText: "postcode" } @@ -46,7 +50,7 @@

{{ pageHeading }}

] }) }} - + {{ button({ text: "Confirm details" }) }} diff --git a/app/views/website/pages/opt-out/confirm-unsubscribe-request.html b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html index 275699ae..911c1deb 100644 --- a/app/views/website/pages/opt-out/confirm-unsubscribe-request.html +++ b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html @@ -1,36 +1,33 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Confirm your unsubscribe request" %} {% block content %}
- - - {% from "radios/macro.njk" import radios %} + {{ radios({ - idPrefix: "confirm-unsubscribe", - name: "confirm-unsubscribe", + idPrefix: "confirmUnsubscribe", + name: "confirmUnsubscribe", errorMessage: { text: "Select an option" } if error, fieldset: { legend: { - text: pageHeading, - classes: "nhsuk-fieldset__legend--l", + text: "Confirm your unsubscribe request", + size: "l", isPageHeading: true } }, + value: data.confirmUnsubscribe, items: [ { - value: "keep", + value: "Keep receiving age-based messages", text: "Keep receiving age-based messages" }, { - value: "unsubscribe", + value: "Unsubscribe from age-based messages", text: "Unsubscribe from age-based messages" } ] diff --git a/app/views/website/pages/opt-out/do-you-know-nhs-number.html b/app/views/website/pages/opt-out/do-you-know-nhs-number.html index 41834c7b..5e676910 100644 --- a/app/views/website/pages/opt-out/do-you-know-nhs-number.html +++ b/app/views/website/pages/opt-out/do-you-know-nhs-number.html @@ -1,36 +1,40 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Do you know your NHS number?" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/start", + text: "Back" + }) }} +{% endblock %} {% block content %}
- - - {% from "radios/macro.njk" import radios %} + {{ radios({ - idPrefix: "do-you-know-nhs-number", - name: "do-you-know-nhs-number", + idPrefix: "knowsNhsNumber", + name: "knowsNhsNumber", errorMessage: { text: "Select an option" } if error, fieldset: { legend: { - text: pageHeading, - classes: "nhsuk-fieldset__legend--l", + text: "Do you know your NHS number?", + size: "l", isPageHeading: true } }, + value: data.knowsNhsNumber, items: [ { - value: "yes", + value: "Yes", text: "Yes, I know my NHS number" }, { - value: "no", + value: "No", text: "No, I do not know my NHS number" } ] diff --git a/app/views/website/pages/opt-out/enter-date-of-birth.html b/app/views/website/pages/opt-out/enter-date-of-birth.html index 2b814650..60fa5b65 100644 --- a/app/views/website/pages/opt-out/enter-date-of-birth.html +++ b/app/views/website/pages/opt-out/enter-date-of-birth.html @@ -1,43 +1,39 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "What is your date of birth?" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/enter-your-postcode", + text: "Back" + }) }} +{% endblock %} {% block content %}
- - -
-
- -

{{ pageHeading }}

-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
+ + + + {{ dateInput({ + id: "dateOfBirth", + namePrefix: "dateOfBirth", + fieldset: { + legend: { + text: "What is your date of birth?", + size: "l", + isPageHeading: true + } + }, + items: [ + { name: "day", value: data.dateOfBirth.day }, + { name: "month", value: data.dateOfBirth.month }, + { name: "year", value: data.dateOfBirth.year } + ] + }) }} {{ button({ text: "Continue" diff --git a/app/views/website/pages/opt-out/enter-your-name.html b/app/views/website/pages/opt-out/enter-your-name.html index c26cc0fd..0b01644b 100644 --- a/app/views/website/pages/opt-out/enter-your-name.html +++ b/app/views/website/pages/opt-out/enter-your-name.html @@ -1,34 +1,48 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "Enter your full name" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/do-you-know-nhs-number", + text: "Back" + }) }} +{% endblock %} {% block content %}
- - -

{{ pageHeading }}

-

Use the same full name that you registered with your GP surgery.

- - {% from "input/macro.njk" import input %} - - {{ input({ - label: { text: "First name" }, - errorMessage: { text: "Enter your first name" } if error, - id: "first-name", - name: "first-name" - }) }} - - {{ input({ - label: { text: "Last name" }, - errorMessage: { text: "Enter your last name" } if error, - id: "last-name", - name: "last-name" - }) }} + + + {% call fieldset({ + legend: { + text: "Enter your full name", + size: "l", + isPageHeading: true + } + }) %} + +

Use the same full name that you registered with your GP surgery

+ + {{ input({ + label: { text: "First name" }, + errorMessage: { text: "Enter your first name" } if error, + id: "firstName", + name: "firstName", + value: data.firstName + }) }} + + {{ input({ + label: { text: "Last name" }, + errorMessage: { text: "Enter your last name" } if error, + id: "lastName", + name: "lastName", + value: data.lastName + }) }} + + {% endcall %} {{ button({ text: "Continue" diff --git a/app/views/website/pages/opt-out/enter-your-nhs-number.html b/app/views/website/pages/opt-out/enter-your-nhs-number.html index ab2c75ad..38495212 100644 --- a/app/views/website/pages/opt-out/enter-your-nhs-number.html +++ b/app/views/website/pages/opt-out/enter-your-nhs-number.html @@ -1,30 +1,34 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "What is your NHS number?" %} + +{% block beforeContent %} + {{ backLink({ + href: "/website/pages/opt-out/do-you-know-nhs-number", + text: "Back" + }) }} +{% endblock %} {% block content %}
- - - {% from "input/macro.njk" import input %} + {{ input({ label: { - text: pageHeading, - classes: "nhsuk-label--l", + text: "What is your NHS number?", + size: "l", isPageHeading: true }, hint: { - text: "Your NHS number is a 10 digit number that you find on any letter the NHS has sent you. For example, 485 777 3456." + text: "Your NHS number is a 10 digit number that you find on any letter the NHS has sent you. For example, 485 777 3456" }, errorMessage: { text: "Enter your NHS number" } if error, - id: "your-nhs-number", - name: "your-nhs-number", + id: "nhsNumber", + name: "nhsNumber", + value: data.nhsNumber, classes: "nhsuk-input--width-20" }) }} diff --git a/app/views/website/pages/opt-out/enter-your-postcode.html b/app/views/website/pages/opt-out/enter-your-postcode.html index 7af96fbb..def0ce09 100644 --- a/app/views/website/pages/opt-out/enter-your-postcode.html +++ b/app/views/website/pages/opt-out/enter-your-postcode.html @@ -1,26 +1,34 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "What is your post code" %} + +{% block beforeContent %} + {{ backLink({ + href: "javascript:history.back()", + text: "Back" + }) }} +{% endblock %} {% block content %}
- - -

{{ pageHeading }}

- - {% from "input/macro.njk" import input %} + {{ input({ - label: { text: "Enter post code" }, - hint: { text: "For this prototype, enter SW1 2CV to pass identity verification." }, + label: { + text: "What is your post code", + size: "l", + isPageHeading: true + }, + hint: { + text: "For this prototype, enter SW1 2CV to pass identity verification" + }, errorMessage: { text: "Enter your postcode" } if error, - id: "your-postcode", - name: "your-postcode", + id: "postcode", + name: "postcode", + value: data.postcode, classes: "nhsuk-input--width-10" }) }} diff --git a/app/views/website/pages/opt-out/identity-details-error.html b/app/views/website/pages/opt-out/identity-details-error.html index d80a89e5..cdc70e80 100644 --- a/app/views/website/pages/opt-out/identity-details-error.html +++ b/app/views/website/pages/opt-out/identity-details-error.html @@ -1,15 +1,13 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} -{% set pageHeading = "We're sorry. We can't identify you at this time. Please check your details and try again." %} {% block content %}
-

{{ pageHeading }}

+

We're sorry. We can't identify you at this time. Please check your details and try again.

{{ button({ text: "Continue", diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html index 011fa792..dad55419 100644 --- a/app/views/website/pages/opt-out/start.html +++ b/app/views/website/pages/opt-out/start.html @@ -1,7 +1,6 @@ {% extends 'layout.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} -{% set backLink = true %} {% set pageHeading = "Unsubscribe from Age-Based Messages" %} {% block content %} From eea6b1b421103892afc342c20eabffb2478b5977 Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 11:06:33 +0100 Subject: [PATCH 5/9] Fix website journey layout: back-link padding, header/footer isolation - Add layout-website.html, extending layout.html, overriding header/footer and setting mainClasses = "nhsuk-main-wrapper--s" for this journey only, per NHS design system question-page and start-page patterns. This fixes the excess padding above back links. - Header now shows only logo + service name (no app nav), footer shows the standard meta links (accessibility, contact, cookies, privacy, terms) and correct copyright text, per the header/footer component guidance. - Swap all 12 opt-out pages to extend layout-website.html instead of layout.html. App journeys (v5.4/v5.5/v6) are untouched and still use layout.html/layout-app.html with their original header/footer. - start.html: use nhsuk-heading-xl per the start-page pattern. - Update README with notes on the fix and isolation approach. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/views/layout-website.html | 65 +++++++++++++++++++ app/views/website/pages/opt-out/README.md | 14 ++++ .../check-your-details-nhs-number.html | 2 +- .../pages/opt-out/check-your-details.html | 2 +- .../opt-out/confirm-unsubscribe-request.html | 2 +- .../pages/opt-out/confirmation-saved-no.html | 2 +- .../pages/opt-out/confirmation-saved-yes.html | 2 +- .../pages/opt-out/do-you-know-nhs-number.html | 2 +- .../pages/opt-out/enter-date-of-birth.html | 2 +- .../pages/opt-out/enter-your-name.html | 2 +- .../pages/opt-out/enter-your-nhs-number.html | 2 +- .../pages/opt-out/enter-your-postcode.html | 2 +- .../pages/opt-out/identity-details-error.html | 2 +- app/views/website/pages/opt-out/start.html | 4 +- 14 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 app/views/layout-website.html diff --git a/app/views/layout-website.html b/app/views/layout-website.html new file mode 100644 index 00000000..d1dcf82c --- /dev/null +++ b/app/views/layout-website.html @@ -0,0 +1,65 @@ +{% extends 'layout.html' %} + + + + +{% set mainClasses = "nhsuk-main-wrapper--s" %} + +{% block pageTitle %} + Digital Child Health – NHS +{% endblock %} + + +{% block header %} + {{ header({ + service: { + text: "Digital Child Health", + href: "/website/pages/opt-out/start" + } + }) }} +{% endblock %} + + +{% block footer %} + {{ footer({ + copyright: { + text: "© Crown copyright" + }, + meta: { + items: [ + { + href: "#", + text: "Accessibility statement" + }, + { + href: "#", + text: "Contact us" + }, + { + href: "#", + text: "Cookies" + }, + { + href: "#", + text: "Privacy policy" + }, + { + href: "#", + text: "Terms and conditions" + }, + { + href: "/prototype-admin/reset?returnPage=" + (currentPage | urlencode), + text: "Reset data" + } + ] + } + }) }} +{% endblock %} diff --git a/app/views/website/pages/opt-out/README.md b/app/views/website/pages/opt-out/README.md index 6b9bdca9..e9a1422f 100644 --- a/app/views/website/pages/opt-out/README.md +++ b/app/views/website/pages/opt-out/README.md @@ -58,3 +58,17 @@ flowchart TD The rest of this prototype's pages set `{% set backLink = true %}`. which `layout.html` does not read, so that flag renders nothing — that pattern is left as-is elsewhere to avoid touching unrelated journeys. +- All pages in this journey extend `app/views/layout-website.html` (not + `layout.html`/`layout-app.html` directly). It overrides only the header + and footer to match the standard NHS.UK transactional-service pattern — + logo + service name, no app navigation, and a footer with Accessibility + statement / Contact us / Cookies / Privacy policy / Terms and conditions + links per the [header](https://service-manual.nhs.uk/design-system/components/header) + and [footer](https://service-manual.nhs.uk/design-system/components/footer) + guidance — and sets `mainClasses = "nhsuk-main-wrapper--s"` as recommended + by the [question pages](https://service-manual.nhs.uk/design-system/patterns/question-pages) + and [start page](https://service-manual.nhs.uk/design-system/patterns/start-page) + patterns, which fixes the excess top padding that showed above the back + link. This override is scoped to `layout-website.html` only, so the app + journeys (which still extend `layout.html`/`layout-app.html`) are + unaffected. diff --git a/app/views/website/pages/opt-out/check-your-details-nhs-number.html b/app/views/website/pages/opt-out/check-your-details-nhs-number.html index 0815b896..68f979a6 100644 --- a/app/views/website/pages/opt-out/check-your-details-nhs-number.html +++ b/app/views/website/pages/opt-out/check-your-details-nhs-number.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/check-your-details.html b/app/views/website/pages/opt-out/check-your-details.html index 9739da9e..db094ea5 100644 --- a/app/views/website/pages/opt-out/check-your-details.html +++ b/app/views/website/pages/opt-out/check-your-details.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/confirm-unsubscribe-request.html b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html index 911c1deb..8cecec8b 100644 --- a/app/views/website/pages/opt-out/confirm-unsubscribe-request.html +++ b/app/views/website/pages/opt-out/confirm-unsubscribe-request.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/confirmation-saved-no.html b/app/views/website/pages/opt-out/confirmation-saved-no.html index 4d780e15..2b138bf9 100644 --- a/app/views/website/pages/opt-out/confirmation-saved-no.html +++ b/app/views/website/pages/opt-out/confirmation-saved-no.html @@ -1,5 +1,5 @@ {% from "panel/macro.njk" import panel %} -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/confirmation-saved-yes.html b/app/views/website/pages/opt-out/confirmation-saved-yes.html index 721c04ac..e2c81172 100644 --- a/app/views/website/pages/opt-out/confirmation-saved-yes.html +++ b/app/views/website/pages/opt-out/confirmation-saved-yes.html @@ -1,5 +1,5 @@ {% from "panel/macro.njk" import panel %} -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/do-you-know-nhs-number.html b/app/views/website/pages/opt-out/do-you-know-nhs-number.html index 5e676910..81a45206 100644 --- a/app/views/website/pages/opt-out/do-you-know-nhs-number.html +++ b/app/views/website/pages/opt-out/do-you-know-nhs-number.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/enter-date-of-birth.html b/app/views/website/pages/opt-out/enter-date-of-birth.html index 60fa5b65..9f2ad1f1 100644 --- a/app/views/website/pages/opt-out/enter-date-of-birth.html +++ b/app/views/website/pages/opt-out/enter-date-of-birth.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/enter-your-name.html b/app/views/website/pages/opt-out/enter-your-name.html index 0b01644b..e631f3b8 100644 --- a/app/views/website/pages/opt-out/enter-your-name.html +++ b/app/views/website/pages/opt-out/enter-your-name.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/enter-your-nhs-number.html b/app/views/website/pages/opt-out/enter-your-nhs-number.html index 38495212..43e5aa41 100644 --- a/app/views/website/pages/opt-out/enter-your-nhs-number.html +++ b/app/views/website/pages/opt-out/enter-your-nhs-number.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/enter-your-postcode.html b/app/views/website/pages/opt-out/enter-your-postcode.html index def0ce09..112b1634 100644 --- a/app/views/website/pages/opt-out/enter-your-postcode.html +++ b/app/views/website/pages/opt-out/enter-your-postcode.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/identity-details-error.html b/app/views/website/pages/opt-out/identity-details-error.html index cdc70e80..8b48e70e 100644 --- a/app/views/website/pages/opt-out/identity-details-error.html +++ b/app/views/website/pages/opt-out/identity-details-error.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html index dad55419..afb13c6f 100644 --- a/app/views/website/pages/opt-out/start.html +++ b/app/views/website/pages/opt-out/start.html @@ -1,4 +1,4 @@ -{% extends 'layout.html' %} +{% extends 'layout-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} {% set pageHeading = "Unsubscribe from Age-Based Messages" %} @@ -8,7 +8,7 @@
-

{{ pageHeading }}

+

{{ pageHeading }}

You were automatically signed up to receive timed reminders based on your baby's age, including information about appointments, check-ups and more.

From 2a87bf357423d8aef34f6b863f57595bd23fd6f6 Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 11:07:54 +0100 Subject: [PATCH 6/9] =?UTF-8?q?Change=20website=20footer=20copyright=20to?= =?UTF-8?q?=20=C2=A9=20NHS=20England?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/views/layout-website.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layout-website.html b/app/views/layout-website.html index d1dcf82c..fcd449f5 100644 --- a/app/views/layout-website.html +++ b/app/views/layout-website.html @@ -31,7 +31,7 @@ {% block footer %} {{ footer({ copyright: { - text: "© Crown copyright" + text: "© NHS England" }, meta: { items: [ From b8009d8c8faf5d2389f4d9897a7c305238e26b33 Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 11:12:30 +0100 Subject: [PATCH 7/9] Start page: model it as hosted on NHS.UK, entering the service on Start - Add layout-nhsuk-website.html for the start page only: full NHS.UK header (search + navigation) and breadcrumb, reflecting that a services start page is usually hosted on the main NHS.UK website per https://service-manual.nhs.uk/design-system/patterns/start-page - start.html now uses this layout, with a "Start now" button (was "Continue") linking into the transactional service. - Every other page in the journey still uses layout-website.html, the simpler logo + service name header - so once the user clicks "Start now" they visibly move from nhs.uk into the service, matching how real NHS.UK services (e.g. Find your NHS number) work. - Update README with notes on this split. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/views/layout-nhsuk-website.html | 94 ++++++++++++++++++++++ app/views/website/pages/opt-out/README.md | 12 ++- app/views/website/pages/opt-out/start.html | 4 +- 3 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 app/views/layout-nhsuk-website.html diff --git a/app/views/layout-nhsuk-website.html b/app/views/layout-nhsuk-website.html new file mode 100644 index 00000000..f3359156 --- /dev/null +++ b/app/views/layout-nhsuk-website.html @@ -0,0 +1,94 @@ +{% extends 'layout.html' %} + + + +{% set mainClasses = "nhsuk-main-wrapper--s" %} + +{% block pageTitle %} + Unsubscribe from age-based messages – NHS +{% endblock %} + + +{% block header %} + {{ header({ + search: { + action: "https://www.nhs.uk/search" + }, + navigation: { + items: [ + { href: "https://www.nhs.uk/nhs-services/", text: "NHS services" }, + { href: "https://www.nhs.uk/conditions/", text: "Health A to Z" }, + { href: "https://www.nhs.uk/live-well/", text: "Live Well" }, + { href: "https://www.nhs.uk/mental-health/", text: "Mental health" }, + { href: "https://www.nhs.uk/care-and-support/", text: "Care and support" }, + { href: "https://www.nhs.uk/pregnancy/", text: "Pregnancy" } + ] + } + }) }} +{% endblock %} + + +{% block beforeContent %} + {{ breadcrumb({ + items: [ + { href: "https://www.nhs.uk", text: "Home" }, + { href: "https://www.nhs.uk/nhs-services/", text: "NHS services" }, + { href: "https://www.nhs.uk/nhs-services/online-services/", text: "Online services" } + ] + }) }} +{% endblock %} + + +{% block footer %} + {{ footer({ + copyright: { + text: "© NHS England" + }, + meta: { + items: [ + { + href: "#", + text: "Accessibility statement" + }, + { + href: "#", + text: "Contact us" + }, + { + href: "#", + text: "Cookies" + }, + { + href: "#", + text: "Privacy policy" + }, + { + href: "#", + text: "Terms and conditions" + }, + { + href: "/prototype-admin/reset?returnPage=" + (currentPage | urlencode), + text: "Reset data" + } + ] + } + }) }} +{% endblock %} diff --git a/app/views/website/pages/opt-out/README.md b/app/views/website/pages/opt-out/README.md index e9a1422f..235a2910 100644 --- a/app/views/website/pages/opt-out/README.md +++ b/app/views/website/pages/opt-out/README.md @@ -58,7 +58,17 @@ flowchart TD The rest of this prototype's pages set `{% set backLink = true %}`. which `layout.html` does not read, so that flag renders nothing — that pattern is left as-is elsewhere to avoid touching unrelated journeys. -- All pages in this journey extend `app/views/layout-website.html` (not +- `start.html` extends a separate layout, `app/views/layout-nhsuk-website.html`, + not `layout-website.html`. Start pages for services like this are usually + hosted on the main NHS.UK website, with the full NHS.UK header (search + + navigation) and breadcrumbs, per the + [start page pattern](https://service-manual.nhs.uk/design-system/patterns/start-page). + The "Start now" button then takes the user off nhs.uk and into the + transactional service itself, which is why every other page in this + journey switches to the simpler logo + service name header + (`layout-website.html`) - matching how real services like "Find your NHS + number" work in production. +- All other pages in this journey extend `app/views/layout-website.html` (not `layout.html`/`layout-app.html` directly). It overrides only the header and footer to match the standard NHS.UK transactional-service pattern — logo + service name, no app navigation, and a footer with Accessibility diff --git a/app/views/website/pages/opt-out/start.html b/app/views/website/pages/opt-out/start.html index afb13c6f..197a9f9a 100644 --- a/app/views/website/pages/opt-out/start.html +++ b/app/views/website/pages/opt-out/start.html @@ -1,4 +1,4 @@ -{% extends 'layout-website.html' %} +{% extends 'layout-nhsuk-website.html' %} {% set version = "website" %} {% set hub = "Opt Out" %} {% set pageHeading = "Unsubscribe from Age-Based Messages" %} @@ -25,7 +25,7 @@

{{ pageHeading }}

{{ button({ - text: "Continue", + text: "Start now", href: "/website/pages/opt-out/do-you-know-nhs-number" }) }} From f3228a089d73b980f46eb3eee3c5fd0c5b78c5dd Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 11:31:04 +0100 Subject: [PATCH 8/9] Start page footer: match real NHS.UK website footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the simple meta-link footer on the start page with the actual 4-column navigation footer used on nhs.uk (Home, Health A to Z, NHS services, Healthy living, Mental health, Care and support / NHS App, Find my NHS number, About the NHS, Healthcare abroad / Manage NHS profiles, Other NHS websites / About us, Accessibility statement, Our policies, Cookies), with "© Crown copyright" - matching https://www.nhs.uk/nhs-services/hospitals/book-an-appointment/ Only the start page uses this (layout-nhsuk-website.html); the rest of the journey keeps the simpler transactional footer with "© NHS England" in layout-website.html. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/views/layout-nhsuk-website.html | 69 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/app/views/layout-nhsuk-website.html b/app/views/layout-nhsuk-website.html index f3359156..4cd09d9d 100644 --- a/app/views/layout-nhsuk-website.html +++ b/app/views/layout-nhsuk-website.html @@ -56,39 +56,48 @@ }) }} {% endblock %} - + {% block footer %} {{ footer({ copyright: { - text: "© NHS England" + text: "© Crown copyright" }, - meta: { - items: [ - { - href: "#", - text: "Accessibility statement" - }, - { - href: "#", - text: "Contact us" - }, - { - href: "#", - text: "Cookies" - }, - { - href: "#", - text: "Privacy policy" - }, - { - href: "#", - text: "Terms and conditions" - }, - { - href: "/prototype-admin/reset?returnPage=" + (currentPage | urlencode), - text: "Reset data" - } - ] - } + navigation: [ + { + items: [ + { href: "https://www.nhs.uk/", text: "Home" }, + { href: "https://www.nhs.uk/health-a-to-z/", text: "Health A to Z" }, + { href: "https://www.nhs.uk/nhs-services/", text: "NHS services" }, + { href: "https://www.nhs.uk/live-well/", text: "Healthy living" }, + { href: "https://www.nhs.uk/mental-health/", text: "Mental health" }, + { href: "https://www.nhs.uk/social-care-and-support/", text: "Care and support" } + ] + }, + { + items: [ + { href: "https://www.nhs.uk/nhs-app/", text: "NHS App" }, + { href: "https://www.nhs.uk/nhs-services/online-services/find-nhs-number/", text: "Find my NHS number" }, + { href: "https://www.nhs.uk/using-the-nhs/about-the-nhs/", text: "About the NHS" }, + { href: "https://www.nhs.uk/using-the-nhs/healthcare-abroad/", text: "Healthcare abroad" } + ] + }, + { + items: [ + { href: "https://www.nhs.uk/our-policies/manage-nhs-profiles/", text: "Manage NHS profiles" }, + { href: "https://www.nhs.uk/nhs-sites/", text: "Other NHS websites" } + ] + }, + { + items: [ + { href: "https://www.nhs.uk/about-us/", text: "About us" }, + { href: "https://www.nhs.uk/accessibility-statement/", text: "Accessibility statement" }, + { href: "https://www.nhs.uk/our-policies/", text: "Our policies" }, + { href: "https://www.nhs.uk/our-policies/choose-your-cookie-settings/", text: "Cookies" }, + { href: "/prototype-admin/reset?returnPage=" + (currentPage | urlencode), text: "Reset data" } + ] + } + ] }) }} {% endblock %} From 6c27b3d67a7564ce0b8450f4a9b430ed78598396 Mon Sep 17 00:00:00 2001 From: Matt Fielding Date: Thu, 17 Sep 2026 11:37:02 +0100 Subject: [PATCH 9/9] Fix: scope iOS Dynamic Type override to native app pages only The @supports (font: -apple-system-body) rule in _ios-dynamic-text.scss was applied to the bare `html` element, with !important. Safari/WebKit (including desktop Safari, which also recognises this value) matched the @supports check and reset the font (family, size, line-height) for every page in the prototype - including the NHS website opt-out journey - to the OS Dynamic Type body size, which is noticeably smaller than the NHS Frontend type scale. This made all text look smaller than the real NHS website when viewed in Safari. Scope the override to `.nhs-app-native` (the body class set only by layout-app.html/layout-app-v1.html for the native app webview) so it only affects app pages that are actually rendered inside the native app, and no longer leaks into the website journey or any other page using layout.html directly. Verified with Playwright's WebKit engine: - /website/pages/opt-out/start: h1 48px, body text 19px (unaffected, as expected for a page using the standard NHS Frontend type scale) - /v6/pages/health-choices (extends layout-app.html, has nhs-app-native class): body font still overridden to UICTFontTextStyleBody (unchanged native app behaviour) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/assets/sass/prototype-specific/_ios-dynamic-text.scss | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/assets/sass/prototype-specific/_ios-dynamic-text.scss b/app/assets/sass/prototype-specific/_ios-dynamic-text.scss index dd441697..ea2a014f 100644 --- a/app/assets/sass/prototype-specific/_ios-dynamic-text.scss +++ b/app/assets/sass/prototype-specific/_ios-dynamic-text.scss @@ -1,6 +1,12 @@ // apple ios dynamic text +// Scoped to .nhs-app-native only (set in app/views/layout-app.html for the +// native app webview) so this doesn't override typography site-wide - +// otherwise Safari/WebKit (including desktop Safari) applies the system +// Dynamic Type body size to every page, making text on the NHS website +// journey (and any other non-native-app page) render smaller than it +// should. @supports (font: -apple-system-body) { - html { + .nhs-app-native { font: -apple-system-body !important; } }