Ok! Got it. Here's what I've discovered (which I'll write up as a blog post - but maybe not until after Christmas):
In Umbraco 14 the "Save & Preview" button does the following:
- Saves the content
- Calls a special API to start preview mode for the current user and setup a SignalR hub (for realtime updates)
- Opens the backoffice preview url in a new window
(Note: no way to configure the backoffice preview url at the moment)
The backoffice preview url is a backoffice route that loads the
web component, which sets up a banner at the bottom and loads the front-end preview route in an iframe.
(Note: no way of configuring a different front-end preview url at the moment)
The frontend preview url is (/{id}?culture=XXX) where Id is the content node Guid. In MVC world that is picked up by Umbraco and rendered as normal, but using the preview content rather than the published content.
If you are headless this gives a lovely 404 and everything stops.
To make this work, I've added a RenderController for that specific route only that checks for the context.IsPreview flag. It looks up the content from the Id and works out the path, then does a redirect to the NextJS preview api url including:
- the path
- an expiry time (5 mins out)
- an SHA256 HMAC of the timestamp and the path using a shared secret as the key
NextJS preview api route checks the signature matches and then turns on preview mode (now called Draft mode -
https://nextjs.org/docs/app/building-your-application/configuring/draft-mode) using a cookie for the front-end domain, and then redirects you to the appropriate page.
Once on the page, NextJS has a lovely context.preview / content.draftMode flag which you pass straight into the Umbraco content delivery api and hey presto you got draft content.