SvelteKit - preview drafts

I followed the docs to create a Preview for my SvelteKit website - Preview Drafts in Svelte - Prismic

Preview for published content works great, but if the content is not published, it returns a 404 error

Failed to load resource: the server responded with a status of 404 (Not Found)

My preview file

import { createClient } from "$lib/utils/prismicClient";

export const get = async ({ fetch, request }) => {
  const client = createClient({ fetch, request });
  const url = await client.resolvePreviewURL({ defaultURL: "/" });

  return {
    status: 307,
    headers: {
      location: url,
    },
  };
};

A request example:

  import { createClient } from "$lib/utils/prismicClient";
  import { predicate } from "@prismicio/client";

  export async function load({ params, fetch, request }) {
    const client = createClient({ fetch, request });
    const type = params.type;
    const uid = params.uid;

    const doc = await client
      .getByUID("post", uid, {
        fetchLinks: [
          "post_category.name",
          "person.name",
          "person.image",
          "person.longer_description",
          "post_type.name",
        ],
      })
      .catch(() => {
        return {
          status: 500,
        };
      });

The request param is undefined which doesn't happen if I preview a published document

Hi @kris,

This would suggest the preview script hasn't been added to your 404 page as discussed here:

Thanks.

@Phil Thanks for the response. I saw this message, but unfortunately, this is not the issue. I have put the script that within app.html and the 404 page uses that template as well for its page.

The issue is something else that needs to be investigated and fixed.

Hey @kris, I'll take a look at this and get back to you tomorrow!

Hey @kris,

I spent some time working on this today, but I couldn't figure it out. Monday is a holiday, but I'll come back to it on Tuesday.

Sam

Hey @kris,

I don't know why this isn't working server-side with src/routes/preview.js. However, it's relatively easy to make previews work client-side.

The issue seems to be that the server isn't receiving the cookie. In my implementation, the page reloads and the server receives the cookie on the second try, so everything works fine, but if I look at the console I can see the same error that you're getting.

So, my solution for now is to switch to client-side routing. Delete src/routes/preview.js and create src/routes/preview.svelte, then paste in this code:

<script>
	import { onMount } from 'svelte';
	import createClient from '$lib/prismicio';
	import { goto } from '$app/navigation';

	onMount(async () => {
		const client = createClient();
		const url = await client.resolvePreviewURL({ defaultURL: '/' });
		goto(url);
	});
</script>

<h1>Loading preview...</h1>

Be sure to update the route for your createClient import.

Tell me if that works for you.

Sam

Hi @samlittlefair ,

Many thanks for looking into this. It does seem to fix it for the first load of the webpage, but if I Save another change while the browser is still open, it does refresh but the page doesn't render with an error:

Failed to load resource: the server responded with a status of 404 (Not Found)

Any idea of how I can fix that?

@kris My colleague @angeloashmore suggested a tweak to the official implementation to make the cookie available immediately. Would you be willing to try this and let me know if it works? It means reverting to your original implementation, and changing src/routes/preview.js to this:

// src/routes/preview.js

import * as prismic from '@prismicio/client';
import * as cookie from 'cookie';

import createClient from '$lib/prismicio';

export const GET = async ({ url, fetch, request }) => {
	const client = createClient({ fetch, request });

	const previewToken = url.searchParams.get('token');
	const previewURL = await client.resolvePreviewURL({ defaultURL: '/' });

	return {
		status: 307,
		headers: {
			location: previewURL,
			'set-cookie': cookie.serialize(prismic.cookie.preview, previewToken, { path: '/' })
		}
	};
};

If you have the chance, let me know if that works :slight_smile:

Sam

Hey Sam, I'm getting this error:

node.component is not a function
TypeError: node.component is not a function

Hey @kris,

Are you planning to update to SvelteKit's new routing API? If so, we have new documentation for implementing previews with Svelte's new system.

Otherwise, I haven't seen that error. Could you send me the full terminal output?

Thanks,
Sam

@samlittlefair ,I upgraded to the newest routing API and I following the documentation. The previews work for pages that already exist, but the the same error appears for 404 pages:

Failed to load resource: the server responded with a status of 404 (Not Found)

I just want to double check - have you tested the documentation in a test repository internally? If so, can you share a github repository with a working preview for drafts?

@kris Yep, I have this working with a minimal setup, following the docs step-by-step. Here's the app; you just need to update the repo name and routes option in src/lib/prismicio.js, and update the folder structure and querying if necessary.

sam-220812-svelte-01.zip (159.6 KB)

Let me know if that still throws an error. If so, let me know the error. If not, let's keep trying to debug your project to see what the difference is.