<p>The tokens need to be in the request headers or query string, not in the body of the request. We use a different request lib, but try something like this:</p>
<pre class="lang-javascript prettyprint-override"><code>      const entry = await app.apolloProvider.defaultClient.query({
        query: aboutEntry,
        variables: {
          slug: 'over-ons',
          siteId: curSiteId,
        },
        headers: {
          'X-Craft-Token': route.query.token ?? ''
        },
      }).then(({data}) =&gt; data &amp;&amp; data.entry)
</code></pre>
<p>This is the relevant section from the Craft 4 docs:</p>
<blockquote>
<p>You can pass the token via either a query string parameter named after your <a href="https://craftcms.com/docs/4.x/config/general.html#tokenparam" rel="nofollow noreferrer">tokenParam</a> config setting, or an <code>X-Craft-Token</code> header.</p>
</blockquote>
<p><a href="https://craftcms.com/docs/4.x/entries.html#previewing-decoupled-front-ends" rel="nofollow noreferrer">https://craftcms.com/docs/4.x/entries.html#previewing-decoupled-front-ends</a></p>

CC BY-SA 4.0
2023-06-27T16:26:15.000Z
2023-06-27T16:31:33.853Z
2023-06-27T16:31:33.853Z
Josh Coady
<p>Over the past few weeks I've been working on a headless CraftCMS integration with Nuxt for the frontend. I use Apollo and GraphQL to fetch the data from the CMS. Almost there now, but there's one feature I can not get to work. It's the live preview from CraftCMS which needs to show the updated page, loaded from a different domain.</p>
<p>I have been checking out numerous of tutorials, like these:</p>
<p><a href="https://nystudio107.com/blog/headless-preview-in-craft-cms" rel="nofollow noreferrer">https://nystudio107.com/blog/headless-preview-in-craft-cms</a>
<a href="https://www.trevor-davis.com/blog/setting-up-live-preview-with-craft-cms-in-headless-mode" rel="nofollow noreferrer">https://www.trevor-davis.com/blog/setting-up-live-preview-with-craft-cms-in-headless-mode</a></p>
<p>So far, I've been able to extract the params from the URL. I've added them to my query params, and although the right template is being loaded in the preview URL, it's not updating it with my (draft) changes.</p>
<p>This is (part of) my Nuxt page query:</p>
<pre><code>
    async asyncData({error, app, route, params}) {
      const curSiteId = app.i18n.locales.find(locale =&gt; locale.code === app.i18n.locale).siteId ?? process.env.DEFAULT_SITE_ID;

      const entry = await app.apolloProvider.defaultClient.query({
        query: aboutEntry,
        variables: {
          slug: 'over-ons',
          siteId: curSiteId,
          token: route.query.token ?? '',
          'x-craft-preview': route.query['x-craft-live-preview'] ?? '',
          'x-craft-live-preview': route.query['x-craft-live-preview'] ?? '',
        },
      }).then(({data}) =&gt; data &amp;&amp; data.entry)

      if (!entry) {
        return error({
          'statusCode': 404
        })
      }

      return {
        headData: await app.seomaticMeta(route, curSiteId),
        entry
      };
    },
</code></pre>
<p>The token and the x-craft-preview variables have the correct values. I've tested this by outputting it to the console.</p>
<pre><code>{
  slug: 'over-ons',
  siteId: '2',
  token: 'v_FXkP_Hx2m7iKmjfc9CnSrVhKW4xBke',
  'x-craft-preview': '5QxCvjPZVg',
  'x-craft-live-preview': '5QxCvjPZVg'
}
</code></pre>
<p>So it seems that GraphQL is not passing it to Craft or Craft is not accepting the params.</p>
<p>This is my config/general.php</p>
<pre><code>&lt;?php
/**
 * General Configuration
 *
 * All of your system's general configuration settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/GeneralConfig.php.
 *
 * @see \craft\config\GeneralConfig
 */

use craft\config\GeneralConfig;
use craft\helpers\App;

return GeneralConfig::create()
    // Set the default week start day for date pickers (0 = Sunday, 1 = Monday, etc.)
    -&gt;defaultWeekStartDay(1)
    // Prevent generated URLs from including &quot;index.php&quot;
    -&gt;omitScriptNameInUrls()
    // Enable Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
    -&gt;devMode(App::env('DEV_MODE') ?? false)
    // Allow administrative changes
    -&gt;allowAdminChanges(App::env('ALLOW_ADMIN_CHANGES') ?? false)
    // Disallow robots
    -&gt;disallowRobots(App::env('DISALLOW_ROBOTS') ?? false)
    // Control panel
    -&gt;cpTrigger(App::env('CP_TRIGGER') ?? 'admin')
    // Run CraftCMS headless
    -&gt;headlessMode(App::env('ENABLE_HEADLESS_MODE') ?? false)
    -&gt;enableGraphQlCaching(App::env('ENABLE_GQL_CACHING') ?? false)
    -&gt;previewIframeResizerOptions([
        'checkOrigin' =&gt; false
    ])
;

</code></pre>
<p>I am running Craft 4.4.13 and Nuxt 2.16.2. My CraftCMS is running locally on <a href="https://backend.XXX.local" rel="nofollow noreferrer">https://backend.XXX.local</a>, while I'm running Nuxt on http://localhost:3000.</p>

<craft4><graphql><headless>
CraftCMS headless / Nuxt - not getting live preview to work
# CraftCMS headless / Nuxt - not getting live preview to work

(Asked by: username_0 on 2023-06-21)

Over the past few weeks I've been working on a headless CraftCMS integration with Nuxt for the frontend. I use Apollo and GraphQL to fetch the data from the CMS. Almost there now, but there's one feature I can not get to work. It's the live preview from CraftCMS which needs to show the updated page, loaded from a different domain.
I have been checking out numerous of tutorials, like these:
https://nystudio107.com/blog/headless-preview-in-craft-cms
https://www.trevor-davis.com/blog/setting-up-live-preview-with-craft-cms-in-headless-mode
So far, I've been able to extract the params from the URL. I've added them to my query params, and although the right template is being loaded in the preview URL, it's not updating it with my (draft) changes.
This is (part of) my Nuxt page query:

    async asyncData({error, app, route, params}) {
      const curSiteId = app.i18n.locales.find(locale => locale.code === app.i18n.locale).siteId ?? process.env.DEFAULT_SITE_ID;

      const entry = await app.apolloProvider.defaultClient.query({
        query: aboutEntry,
        variables: {
          slug: 'over-ons',
          siteId: curSiteId,
          token: route.query.token ?? '',
          'x-craft-preview': route.query['x-craft-live-preview'] ?? '',
          'x-craft-live-preview': route.query['x-craft-live-preview'] ?? '',
        },
      }).then(({data}) => data && data.entry)

      if (!entry) {
        return error({
          'statusCode': 404
        })
      }

      return {
        headData: await app.seomaticMeta(route, curSiteId),
        entry
      };
    },

The token and the x-craft-preview variables have the correct values. I've tested this by outputting it to the console.
{
  slug: 'over-ons',
  siteId: '2',
  token: 'v_FXkP_Hx2m7iKmjfc9CnSrVhKW4xBke',
  'x-craft-preview': '5QxCvjPZVg',
  'x-craft-live-preview': '5QxCvjPZVg'
}

So it seems that GraphQL is not passing it to Craft or Craft is not accepting the params.
This is my config/general.php
defaultWeekStartDay(1)
    // Prevent generated URLs from including "index.php"
    ->omitScriptNameInUrls()
    // Enable Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
    ->devMode(App::env('DEV_MODE') ?? false)
    // Allow administrative changes
    ->allowAdminChanges(App::env('ALLOW_ADMIN_CHANGES') ?? false)
    // Disallow robots
    ->disallowRobots(App::env('DISALLOW_ROBOTS') ?? false)
    // Control panel
    ->cpTrigger(App::env('CP_TRIGGER') ?? 'admin')
    // Run CraftCMS headless
    ->headlessMode(App::env('ENABLE_HEADLESS_MODE') ?? false)
    ->enableGraphQlCaching(App::env('ENABLE_GQL_CACHING') ?? false)
    ->previewIframeResizerOptions([
        'checkOrigin' => false
    ])
;


I am running Craft 4.4.13 and Nuxt 2.16.2. My CraftCMS is running locally on https://backend.XXX.local, while I'm running Nuxt on http://localhost:3000.

**Tags:** craft4, graphql, headless


---

## 1 answers

### Answer by username_1 on 2023-06-27. Score: 1

The tokens need to be in the request headers or query string, not in the body of the request. We use a different request lib, but try something like this:
      const entry = await app.apolloProvider.defaultClient.query({
        query: aboutEntry,
        variables: {
          slug: 'over-ons',
          siteId: curSiteId,
        },
        headers: {
          'X-Craft-Token': route.query.token ?? ''
        },
      }).then(({data}) => data && data.entry)

This is the relevant section from the Craft 4 docs:

You can pass the token via either a query string parameter named after your tokenParam config setting, or an X-Craft-Token header.

https://craftcms.com/docs/4.x/entries.html#previewing-decoupled-front-ends


---

