Live Preview
When editors update content in LeadCMS, they often want to see their changes reflected immediately on the site—even before saving or publishing. LeadCMS supports live preview (also called temp user preview) to provide this feedback. In this article we describe how live previews work today and outline a simplified, unified approach for the next SDK release.
Current implementation
Live preview is delivered through a combination of the LeadCMS SSE watcher and special naming conventions:
- The watch command listens for
draft-updatedandcontent-updatedevents from the CMS. When an editor starts editing a page, the CMS sends adraft-updatedevent that includes a user ID. - The watcher generates a new file in your
.leadcms/contentfolder with the name{slug}-{userUid}.mdx(or.jsonfor JSON formats). It sets the frontmatter propertydraft: true. This file contains the unsaved changes and exists only locally【152248343170964†L37-L205】. - To render this file, the page component must extract the
userUidfrom the slug and callgetCMSContentBySlugForLocale(slug, locale, includeDrafts, userUid). For lists, it must pass bothincludeDraftsanduserUidwhen callinggetAllContentSlugsForLocale()【97649375988743†L62-L78】.
While this approach works, it requires developers to explicitly handle preview logic in every query. Forgetting to pass includeDrafts or userUid can lead to inconsistent previews and duplicate entries. Moreover, the additional slug logic complicates routing and makes generic components harder to reuse.
To‑be vision
We plan to simplify the live preview experience by moving preview logic entirely into the SDK. Instead of passing includeDrafts and userUid throughout your code, you will enable preview mode once and let the SDK handle the details.
Key improvements we envision:
-
Environment‑driven preview: The SDK will detect
process.env.NODE_ENV === 'preview'(or a dedicatedLEADCMS_PREVIEWflag) and automatically include drafts and user previews in queries. Your page components will continue to callgetCMSContentBySlugForLocale(slug, locale)andgetAllContentSlugsForLocale(locale, contentTypes)without additional parameters. The SDK will decide whether to fetch published content, drafts or user‑specific previews. -
Unified slug handling: User‑specific preview files will still be created with
{slug}-{userUid}, but you won’t need to extract the user ID in your code. The SDK will parse the slug internally and load the appropriate file. For example, requesting/blog/about-us-4fee1e45-0bb5-4118-82d8-e9d0db51dc4f/will automatically serve the draft created by that user. -
Safe enumeration: Collections (like blog indexes) will continue to exclude drafts and user previews by default, even in preview mode. If you want to include drafts in a list, you will call an explicit function (e.g.
getAllContentSlugsForLocalePreview) or pass an option. This prevents duplicate entries while still allowing editors to see unpublished work via direct links. -
Simplified API: Functions like
getCMSContentBySlugForLocaleWithDraftSupportandgetAllContentSlugsForLocaleWithDraftSupportwill be deprecated. Instead, a unified API will always be used. Additional preview options can be configured globally or per call via an options object. -
Automatic fallback: In preview mode, if no user‑specific preview exists for a slug, the SDK will fall back to the latest draft or published version. This ensures that links continue to work even if a user closes the CMS without saving.
Running in preview mode
To make the above vision possible, we will introduce a new environment that tells the SDK it is running in preview mode:
- Set
NODE_ENV=preview(or defineLEADCMS_PREVIEW=true) when starting your preview server. The SDK will check this variable and adjust its behaviour automatically. - The preview Dockerfile and supervisor script already set
NODE_ENV=development. In the new design you will setNODE_ENV=previewinstead. The rest of the preview setup remains the same.
Summary
Live preview makes it easy for editors to see their changes in real time. The current SDK implementation exposes includeDrafts and userUid parameters, which require additional boilerplate. In the upcoming version we aim to remove these parameters and make preview behaviour automatic. This unified approach will simplify your codebase and reduce the risk of errors.
For details on draft handling and best practices, see the Draft Preview article. For instructions on configuring the watcher and preview server, see Preview Setup.