Headless Preview in Craft CMS
Tags: craftcms, headless, javascript
Published: 2020-03-10 12:20:29

---
title: Headless Preview in Craft CMS
published: true
date: 2019-08-13 02:40:00 UTC
tags: craftcms,headless,javascript
canonical_url: https://nystudio107.com/blog/headless-preview-in-craft-cms
---

# Headless Preview in Craft CMS

### Craft CMS 3.2 intro­duced head­less con­tent pre­view. Here’s an explo­ration of how it works, and how you can imple­ment it

Andrew Welch / [nystudio107](https://nystudio107.com)

![Headless preview craft cms](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/headless-preview-craft-cms.jpg)

Craft CMS has long had a ​“live pre­view” fea­ture that allows con­tent authors to see a pre­view of exact­ly what their con­tent will look like when pub­lished to the web.

With [Craft CMS 3.2](https://craftcms.com/blog/craft-32), one of the major fea­tures added was ​“head­less preview”.

This fea­ture allows devel­op­ers who are ren­der­ing their pages as a [Sin­gle Page Appli­ca­tion (SPA)](https://medium.com/@NeotericEU/single-page-application-vs-multiple-page-application-2591588efe58) via a fron­tend frame­work like [React](https://reactjs.org/), [Vue.js](https://vuejs.org/), [Svelte](https://svelte.dev/), etc. the abil­i­ty to have Craft CMS con­tent pre­view, too.

## Why it required a rewrite

Even though nowhere in ​“con­tent man­age­ment sys­tem” is the promise of a ren­der­ing engine, all tra­di­tion­al CMSs don’t just man­age con­tent, but also ren­der it as web pages as well.

![Craft cms headless preview horseman](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_992x558_crop_center-center_82_line/craft-cms-headless-preview-horseman.jpg)

A CMS ren­der­ing con­tent was prob­a­bly born out of convenience.

When you use a CMS ​“head­less” you are lop­ping off the part that does the ren­der­ing. Essen­tial­ly, your CMS then man­ages your con­tent, but instead of ren­der­ing it, it pro­vides an API so some­thing else can con­sume it.

The rea­son Craft’s ​“live pre­view” fea­ture worked is that the CMS had con­trol over the whole edit­ing ⟷ pre­view­ing loop.

Now with some­thing else doing the ren­der­ing, that’s no longer the case. So they had come up with a clever solution.

## Tok­enized Preview

The solu­tion the fine folks at Pix­el & Ton­ic came up with is a com­bi­na­tion of auto-saved entry drafts and a <kbd>token</kbd> that’s sent along to the web page that is being previewed.

![Nyc Token](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x573_crop_center-center_100_line/nyc-token.jpg)

When you click on **Pre­view** , rough­ly the fol­low­ing happens:

1. A draft of the entry you’re edit­ing is saved
2. A token is gen­er­at­ed for that draft, and infor­ma­tion about the draft entry ele­ment is saved to the database
3. The token is sent along to wher­ev­er the web page hap­pens to be as a <kbd>token</kbd> URL param
4. The web page then _sends back_ that same token with any API requests

It looks rough­ly like this:

![Craft preview token flowchart](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x728_crop_center-center_100_line/craft-preview-token-flowchart.png)

So why all of this token non­sense? Remem­ber, we’re pre­view­ing an auto-saved draft of the entry that’s being edited.

It’s done this way because the con­tent edi­tor and con­tent ren­der­er no longer share any state, so the saved draft is that state.

The token is what Craft uses to link a pre­view web request to the auto-saved entry draft.

<aside>
                                As you’re edit­ing con­tent with pre­view open, the draft entry is being reg­u­lar­ly saved
                            </aside>

When a request comes in to Craft that has a <kbd>token</kbd> in the URL params, rough­ly the fol­low­ing happens:

1. Craft looks up the route infor­ma­tion asso­ci­at­ed with the <kbd>token</kbd> in the <kbd>tokens</kbd> data­base table
2. In the case of head­less pre­view, the <kbd>Preview</kbd> con­troller’s <kbd>actionPreview()</kbd> method is called
3. The auto-saved draft ele­ment that’s being pre­viewed is then added to a list of <kbd>placeholder</kbd> elements
4. When­ev­er an [ele­ment query](https://docs.craftcms.com/v3/dev/element-queries/) is done that would match any <kbd>placeholder</kbd> ele­ments, they are swapped in

This is what that caus­es it all to ​“just work”. Check out the <kbd>ElementQuery</kbd> meth­ods [\_​placeholderCondition()](https://github.com/craftcms/cms/blob/develop/src/elements/db/ElementQuery.php#L1870) and [\_​createElement()](https://github.com/craftcms/cms/blob/develop/src/elements/db/ElementQuery.php#L2693).

Since the token was passed down to the web page that’s being pre­viewed, if it is passed back up to the API that retrieves data from Craft, the place­hold­er ele­ments get mocked in.

Just like magic.

## Make it so

The [Live pre­view using Vue.js](https://craftcms.stackexchange.com/questions/22045/live-preview-using-vue-js/31039#31039) post details it pret­ty well in terms of what you need to do to add sup­port on your end.

![Star trek make it so picard](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/star-trek-make-it-so-picard.jpg)

Essen­tial­ly, it boils down to just extract­ing the <kbd>token</kbd> URL param, and send­ing it back to the Craft CMS API end­point, whether that be [Ele­ment API](https://github.com/craftcms/element-api), [CraftQL plu­g­in](https://github.com/markhuot/craftql), or what­ev­er else you may be using.

![Craft cms token lifecycle](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x735_crop_center-center_100_line/craft-cms-token-lifecycle.png)

Here’s some JavaScript that Bran­don Kel­ly posted:

```

// Get the preview token from the URL
let m = document.location.href.match(/\btoken=([^&]+)/);
let token = m ? m[1] : '';

// Then forward that on whenever you are sending an API request
let url = `...?token=${token}`;
// ...

```

That’s real­ly all there is to it. Extract the token URL param, and send it back with your API calls.

<aside>
                                If you send Craft back the token it sent you, it’ll take care of the rest
                            </aside>

The <kbd>x-craft-preview</kbd> URL param & request head­er is just a way you can dis­tin­guish the request defin­i­tive­ly as a Craft pre­view, since you might be using the <kbd>token</kbd> URL param for oth­er things as well.

There is a [token­Param](https://docs.craftcms.com/v3/config/config-settings.html#tokenparam) gen­er­al con­fig set­ting if you need to change it to some­thing oth­er than the default of <kbd>token</kbd>.

<aside>
                                This exact same tech­nique is also used for Share links as well!
                            </aside>

If you’re con­cerned about pre­view [not remem­ber­ing the scroll posi­tion cross-domain](https://github.com/craftcms/cms/issues/4410), check out Clive’s [ScrollMemNonEs6.js](https://gist.github.com/narration-sd/a10c5855cb0c06d562d7eb290b3251d3) gist.

Hap­py head­less previewing!

## Further Reading

_If you want to be notified about new articles, follow [nystudio107](https://twitter.com/nystudio107) on Twitter._

<small>Copyright ©2020 nystudio107. Designed by nystudio107</small>