Skip to content

Navigation spike [WHIT-3342] - #11501

Draft
ChrisBAshton wants to merge 1 commit into
mainfrom
navigation-spike
Draft

Navigation spike [WHIT-3342]#11501
ChrisBAshton wants to merge 1 commit into
mainfrom
navigation-spike

Conversation

@ChrisBAshton

@ChrisBAshton ChrisBAshton commented May 26, 2026

Copy link
Copy Markdown
Contributor

What

Spikes a means of creating a Navigation content item (shared_navigation content schema/document type) and linking 0..* Whitehall documents to it.

It defines a "Navigation" StandardEdition with two fields where we can include JSON in the payload for details and links respectively:

Screenshot 2026-05-26 at 15 43 48

The link is implemented as a reverse link, meaning we don't even have to touch any of the documents associated with the Navigation - they get the association by default.

See alphagov/publishing-api#4085 for the counterpart PR.

Why

So that we can test whether our intended approach to Navigation will work end-to-end.

Jira: https://gov-uk.atlassian.net/browse/WHIT-3342

See it in action

DownstreamPayload.new(Document.find_by(content_id: press_release_content_id, locale: "en").editions.last, 1, draft: true).expanded_links

=>

{shared_navigations:
  [{content_id: "81392be0-5ccc-4a84-8431-79f1920b7242",
    title: "Chris shared navigation June",
    locale: "en",
    analytics_identifier: nil,
    api_path: "/api/content/chris-shared-navigation-june--2",
    base_path: "/chris-shared-navigation-june--2",
    document_type: "shared_navigation",
    public_updated_at: "2026-06-02T14:58:28Z",
    schema_name: "shared_navigation",
    withdrawn: false,
    details: {menu_items: [{type: "press_release", content_id: "26086fc1-fbd6-4291-b308-3f334d380d56"}, {type: "publication", content_id: "c6caa8d4-5557-42ea-935b-d45d640d4269"}]},
    links:
     {navigation_items:
       [{content_id: "26086fc1-fbd6-4291-b308-3f334d380d56",
         title: "Foreign Secretary statement on the situation in Lebanon",
         locale: "en",
         analytics_identifier: nil,
         api_path: "/api/content/government/news/foreign-secretary-statement-on-the-situation-in-lebanon--2",
         base_path: "/government/news/foreign-secretary-statement-on-the-situation-in-lebanon--2",
         document_type: "press_release",
         public_updated_at: "2026-03-15T23:02:00Z",
         schema_name: "news_article",
         withdrawn: false,
         links: {}},
        {content_id: "c6caa8d4-5557-42ea-935b-d45d640d4269",
         title: "Youth justice plans: guidance for youth justice services",
         locale: "en",
         analytics_identifier: nil,
         api_path: "/api/content/government/publications/youth-justice-plans-guidance-for-youth-justice-services",
         base_path: "/government/publications/youth-justice-plans-guidance-for-youth-justice-services",
         document_type: "guidance",
         public_updated_at: "2025-01-21T14:33:30Z",
         schema_name: "publication",
         withdrawn: false,
         links: {}}]}}],

Further testing

Tested Navigation that includes some English-only documents and some English documents with Welsh translations. When requesting expanded_links for the cy locale (DownstreamPayload.new(Document.find_by(content_id: publication_content_id, locale: "cy").editions.last, 1, draft: true).expanded_links), the equivalent Welsh translations were automatically surfaced in the expanded links, falling back to the English translation if a Welsh version doesn't exist 🎉

Screenshot 2026-05-29 at 12 22 56

Also tested including live and draft content in the navigation. Both live and draft content would be surfaced in the navigation when rendering the navigation in a draft context, but draft content is automatically not included when rendering in a live context 🎉

Also tested making edits to a draft Navigation and confirmed that it does not alter the live Navigation 🎉

Caveat

Publishing API link expansion / dependency resolution does a lot of the work for us, but we did find one shortcoming:

  • Linking a draft doc A and a published doc B to navigation: the navigation is present in the content items for both, on draft stack. On live stack, published doc B only has navigation link to doc B, not doc A. Great! 🎉 Draft nav items automatically dropped from published docs.
  • Unexpected and unfortunate bug: publishing doc A does not updated the linked navigation on doc B. Requires us to add a callback to Whitehall. Likely a symptom of PTD-91: Whitehall has to manage republishing of linked items despite existence of link expansion in Publishing API 😭
  • Similarly, updating a title of one of the docs in the navigation, does not re-present another doc in the navigation. Manually republishing the other doc sorts that. HOWEVER - it's easier than that - manually republishing the Navigation itself sorts it too.

In other words, whenever any Document in the Navigation is updated, we’ll need to callback and republish the Navigation. Publishing API will then handle the updating of all the other pages in the Navigation. So probably still a big win overall - just the one callback.


⚠️ This repo is Continuously Deployed: make sure you follow the guidance ⚠️

This application is owned by the Whitehall Experience team. Please let us know in #govuk-whitehall-experience-tech when you raise any PRs.

Follow these steps if you are doing a Rails upgrade.

@ChrisBAshton
ChrisBAshton force-pushed the navigation-spike branch 2 times, most recently from b3f4de1 to 913fda5 Compare May 26, 2026 14:57
@ChrisBAshton ChrisBAshton reopened this May 29, 2026
Comment thread app/models/configurable_document_types/news_story.json Outdated
@lauraghiorghisor-tw

lauraghiorghisor-tw commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

I was just thinking... now that we have this expansion rule and really the only thing you have to do is create this navigation content item, with really, any, links on it..., do we still have to bother with the whole editionable flow, or even parent/child modelling?

You can publish the parent -> add nav with link to A page -> more complicated rules -> if page is LP then renders nice nav on FE, if not, it... does not render nice nav but maybe some breadcrumb or smth.

Possible blocker: what happens when we can have an item in multiple navs, which one do you render on the page? (I think I left a comment on pub api PR).

Bit of a nebulous spiral, but I think there's some possibility here 😅

@ChrisBAshton
ChrisBAshton force-pushed the navigation-spike branch 2 times, most recently from 98f92a0 to 6b245e0 Compare June 2, 2026 15:25
The Navigation content type is a StandardEdition here, but when
we do this for real we may model it differently.

The two important things to note:

- `details.menu_items`: hardcoded payload describing the _structure_
  of the navigation (e.g. its nesting, which menu items are highlighted
  etc).
- `links.navigation_items`: hardcoded payload describing the _content_
  of the navigation (JSON array of content IDs representing the
  documents that form the Navigation.

For now these inputs expect JSON and content IDs. When we do it
for real, we wouldn't have these fields - we'd have some way of
choosing/reordering child documents etc, and inferring the details
and links from that.

Note that we've dropped the requirement to specify a base path
prefix or rendering app in the settings, here. We do still want
to enforce that most of the time, so should consider only loosening
it if a different property, `routeless_document: true` or something,
is set.
@leimdorfer

Copy link
Copy Markdown
Contributor

I was just thinking... now that we have this expansion rule and really the only thing you have to do is create this navigation content item, with really, any, links on it..., do we still have to bother with the whole editionable flow, or even parent/child modelling?

You can publish the parent -> add nav with link to A page -> more complicated rules -> if page is LP then renders nice nav on FE, if not, it... does not render nice nav but maybe some breadcrumb or smth.

Possible blocker: what happens when we can have an item in multiple navs, which one do you render on the page? (I think I left a comment on pub api PR).

Bit of a nebulous spiral, but I think there's some possibility here 😅

It is a good question, for beyond this PR but don't think this approach completely negates the need for establishing relationships between the parts of multi-part document, even if it potentially allows us to do so.

Specifically, I think coupling an "about" page to its Topical event, a "visa requirements" page to its country, or a "recruitment" page to its organisation is a feature that makes sense. These are strong relationships.

That said, Where the documents are editionable in their own right and the relationship is weaker (more akin to featuring), then the case for the nav being the linkage is interesting, although I'd still worry about how that would be managed as a "micro-site" if there is nothing linking the pages beyond being on the shared navigation. Anyway - to be continued - on a thread somewhere

@lauraghiorghisor-tw

lauraghiorghisor-tw commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

... how that would be managed as a "micro-site" if there is nothing linking the pages beyond being on the shared navigation

Indeed.

I can't recall the specific rules on Chri's editionable spike but, if generally speaking, for independent children, you always have to make sure you affect the children in some way before the parent can be affected (I think for deletion), or the parent first before the children (creation, publish), it might not be that different from the built-in restrictions and behaviours of publishing API and link expansion. Kind of like the collections model but this PR's nav solution is more powerful. Thought experiment? 🗯️ 3rd spike?

On the other hand, I do think there are some benefits to accessing certain parent-driven actions, a cascading schedule for example, that you can only ever get from the proper modelling. I think users would want that in the long run. Anything that helps us validate user actions and keeps things in sync needs the proper modelling.

@TonyGDS

TonyGDS commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Do we need to identify a root doc in the navigation, e.g. home page, and if so how? Is this expressed through the menu_items?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants