-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow for dynamically resolving the DraftMode API URL #1280
Comments
|
FYI, we have a partial alternative in the meantime, where we circumvent This isn't ideal, and while it solves |
This is the perfect explanation of the issue, I just stumbled across. The only "solution" in our case (Next.js) would be using the embedded Studio and the draft mode URL set with a env variable. But IMO this would not be a great UX opening multiple embedded studios to edit stuff on multiple domains. Hopefully this gets some attention soon, as we would also love to offer visual editing to our clients. 🙏 |
Thanks for sharing @markomitranic 🙌 We'll fast track this and add the escape hatches you need 👍 |
@markomitranic a status update on what we intend to do, following our deep dive into this so far. We'll do two feature releases. 1. Add
|
Dear @stipsan thank you for this lengthy and sturdy plan of action! I am super happy to hear some movement on this, it will change the editor's experience quite a bit if we are able to do this! I understand that your "RFC" needs to support more consumers than I can think of - live editing, preview links, iframe plugin etc, and many ways of using it - you mention being able to manually type stuff into the address bar for example, I never thought of that. So, I write this while fully appreciating that the issue is more complex than it seems to me, nor am I a library author, so not thinking that I deserve any sort of influence. Just my 2 cents. We might be overthinking this. The proposed changes seem much more like a long-term course correction, than a simple and non-breaking addition to the API. Instead of taking it in small steps, going from a string to a simple callback, we are talking about re-engineering how preview URLs work. Instead of focusing on one problem - draftMode api on dynamic domains, we are trying to solve redirections by checks, addressbar behaviour, on-page links, extending the fetch call, live previews and more. I like the changes, but I don't think they are at all necessary to resolve the issue I've raised:
|
Hey @markomitranic, I think I'm confused what you mean by:
What do you mean on every request? The current behaviour is that the redirect only happens initially, before we fade in the iframe.
The static behavior of draftMode today is centered on the assumption that each instance of Changing that into a dynamic resolver has side-effects. If we don't have a way of checking if draft mode is enabled or not, then we can't do it with a fetch call as it's possible that:
That's the best case scenario. The more likely scenario is that on step 3:
Yes, we'll preserve the convenience of relative URLs and installations where you only deal with one origin at a time. The complexity of multiple origins are opt-in. We're not going to introduce any breaking changes in order to deliver this functionality. |
Also worth mentioning that the |
Hey @stipsan sorry for the late reply, I was quite busy over the past few days. Thank you for the response I think i understand the intent much better now! After reading your response I am starting to realize that it might be smart for me to stick with using the productionUrl buttons, as they (unfortunately) make for a better experience for the editors. They require zero IQ to use, you click a button, observe a page and reload it when you wish to. There are no edge cases, weird states or address bars to worry about. Perhaps I'll try to use the raw iframe plugin again to achieve it. Here are some clarifications of functional expectations from my part, that I now understand are not really the goal of the presentation plugins:
Oh ok my mistake then, I suppose me using iframe plugin directly to achieve this has muddied up how the real thing works in my mind. I thought that draft gets hit on every "request", with request meaning when you click the preview button, or reload button.
This is percicely what I meant by saying - overcomplicating. Sounds like you are trying to protect the users from themselves by manually adding these limitations. For example, the iframe plugin itself works just fine and dandy with typing outside domains in the address bar. The only reason why it doesn't in presentation, is that you probably made that decision yourselves in order to make it a smoother experience for the end user. Same with white flashes - that is how the whole internet works, its fine, no reason to hide them from the users. In fact it makes it feel weird, since as a user you don't really know what is going on, as the loading cues you are used to aren't there. In my opinion these constraints are just making it harder to use the tool, not easier. The presentation tool shouldn't be trying to reinvent the browser, it should just show pages when user clicks preview or reload, and refresh them every time a draft is updated. Clunky and simple and old-school. Apart from (obviously) the fancy live editing plugin, the presentation tool itself should basically be an equivalent of you having 2 windows open side by side, preview with autorefresh and Sanity editor.
Good point, that is a very good use for this endpoint. Currently we simply let the users know by showing an "EXIT PREVIEW MODE" button (top bar) on every page while the user is in preview mode. This puts the control away from automated systems and into the user's hands, where they not only explicitly know if they are in preview mode, but can also choose to exit preview mode themselves.
Yup, in my opinion this is exactly what should happen. The user should end up on whichever page they wish to end up, doesn't matter if it is the French website or wikipedia. The draft mode should not automagically activate when you click on links within the iframe (unless its already active for that domain ofc) it should only activate by you clicking a Sanity UI action on a corresponding document that has a preview url on a given page or domain. To turn your example around - if you are editing an english version of a document in Sanity, you change to French through the Sanity UI, the iFrame should refresh with the draft mode on the FR website. If you, however click on the language picker inside the iframe, you are on your own, since your iframe context is now doing something entirely different than the editing UI around it is displaying (the EN version of the document).
Yup, percisely what should happen - you are editing the EN version. The fact that you navigated away to FR is not presentation's concern. All UI actions such as Retry should be related to the document you are editing, not to the content of the iframe.
I may be wrong but I absolutely recall entering multiple domains into the raw iframe plugin. This was a while ago so perhaps I am misremembering... Oh or perhaps I didn't enter it, but used the hook to force a navigate action! 😕 maybe that is what i remember.
phew, glad to hear that
Ah, super useful, a header and a token is a common practice when it comes to CDNs, so I'm super glad to hear this! |
Hey @markomitranic, just a status update 👋 The last couple of weeks I've had my hands full keeping up with turbopack fixes for the upcoming release of You're welcome to make the changes you need to these packages and send a PR for us to look at with the escape hatches you need, we could perhaps add a feature flag that's tagged as Also worth knowing that we started off building Presentation by using the iframe pane plugin as the foundation, we didn't want to reinvent the wheel or "overcomplicate" things, quite the opposite. But eventually this hard constraint on the preview frame always being present, but not always know what the current URL is just yet, or know ahead of time what documents are used on the page, or wether the application inside the preview is showing only published content, or the expected draft content, these constraints force decisions to be made as I mentioned last time. |
Any plans / progress to support preview mode for multiple domains? 😄 We have the studio and our other applications spread across different subdomains, so presentation mode is pretty useless for us. This feature would be much appreciated. Keep up the great work that you guys do ⭐ |
I am using preview mode on multiple websites. It is not documented how to do it, and I wish that Sanity made this an easier thing to do. You basically have to hijack the import { createPreviewSecret } from "@sanity/preview-url-secret/create-secret";
export const previewUrl: DocumentPluginOptions["productionUrl"] = async (
prev: string | undefined,
context: ResolveProductionUrlContext,
): Promise<string | undefined> => {
const { getClient, document, currentUser } = context;
const client = getClient({ apiVersion: "2023-06-04" });
const resolvedUrl = await resolver(); // <-- my own internal URL generation implementation here.
if (!resolvedUrl) return prev;
const { secret } = await createPreviewSecret(
client,
"@sanity/presentation",
typeof window === "undefined" ? "" : location.href,
currentUser?.id,
);
return constructDraftUrl(
"/api/draft/enable/",
secret,
resolvedUrl.href,
resolvedUrl.locale,
).toString();
};
function constructDraftUrl(
draftEndpoint: string,
secret: string,
resolvedUrl = "/",
targetLocale: Locale,
) {
const domain = findDomainByLocale(targetLocale); // <-- My own logic for finding the appropriate domain. In my case based on the targetLocale parameter, but of course you may pass your own props.
const enablePreviewModeUrl = new URL(draftEndpoint, domain);
enablePreviewModeUrl.searchParams.set("sanity-preview-secret", secret);
enablePreviewModeUrl.searchParams.set(
"sanity-preview-pathname",
resolvedUrl ?? "/",
);
return enablePreviewModeUrl;
} With this in place, your preview button will now send the user to the appropriate draft API on the appropriate domain, with the sanity-preview params and your URL. Works like a charm for our editors in production on 20 domains for a while now. Hope this helps @mjansrud (also @stipsan i guess would love to read this 😄 ) |
following is my sanity config setup
In my case, we are using two distinct home page ids to render home page of two separate domains. but, presentation tool always ends up using origin value mentioned in Have I done something wrong in the above setup or have I misunderstood anything? following the versions that we are using "sanity": "^3.57.3", Thanks! |
Is your feature request related to a problem? Please describe.
The preview plugins (iframe, presentation etc) don't allow us to provide absolute URLs. This hinders our ability to provide a URL resolution mechanism when using multiple domains. This would allow us to use the preview mode with websites that might be spread across multiple domains or subdomains. Think about multi-tenant setups or more commonly
next-intl
with domains for different locales. A concrete example I have is a project with 24 locales spread across 16 domains, like:Feeding the presentation plugin an absolute preview URL (for example on another domain) isn't possible as it only sends the path to the draft mode API.Update: if we get no.2, then this is no longer an issue since the path belongs to the draftUrl domain.Describe the solution you'd like
The draft mode API url should be able to be decided on a document by document basis, allowing for us to invoke multiple different domains or subdomains and set cookies for them. We should be able to provide a draft mode URL resolver inside
sanity.config.ts
, that would receive a Sanity context and the document being queried. Example:Describe alternatives you've considered
See below for example #1280 (comment)
We can get preview URLs to play along, by circumventing
@sanity/preview-url-secret
, but this still doesn't help with presentation plugins.Which versions of Sanity are you using?
Which versions of Node.js / npm are you running?
Additional context
I'd be interested in contributing to this, although I have no idea where to start, so perhaps some advice would be needed. For now, let's see if the repo is interested in this sort of contribution (or perhaps I've missed something and this is entirely possible?)
The text was updated successfully, but these errors were encountered: