Creating new Next.js 13 app β€” and trying to migrate from an existing Next.js 12 app

I know, I know. It's new. It just came out yesterday. I recently set up a Next.js 12 app and felt confident I could get Slicemachine running on a Next.js 13 app with the new nested Layouts feature. Here's how you can do it in a nut shell:

  1. Run npx create-next-app@latest --experimental-app
  2. Follow the documentation for Set up Prismic
  3. When you get to npm install @prismicio/next you'll need to run npm install @prismicio/next --force due to strict Next.js dependency versions
  4. Continue to configure
  5. Adding the PrismicProvider and PrismicPreview go on the app/layout.tsx file†
  6. Create Slice Simulator page in app/ folder
  7. Update next.config.js to include basePath: '/app', β€” this tells Prismic to look in the app folder
  8. Update the app/page.tsx to include the SliceZone††

Technically β€” that's as I far as I've have gotten. npm run dev works, so does npm runs slicemachine. I went further to see if I could migrate an existing project to this new repository...

I moved the Next.js 12 working apps .slicemachine folder, slices folder and updated the prismicio.js file to ensure proper routes. With that I re-ran npm run slicemachine. All my Slices showed up! None of my Custom Types showed up β€” haha. So running npm run dev and going to the home page naturally 404's. I assume that is because Slicemachine is not properly seeing the .slicemachine/customtypes/homepage Custom Type I made. Bummer. Can't seem to find any help on the community here that shows how to migrate an existing Next.js repository to a new repo. Will continue to try in free time! Any ideas? Feel free to share!

†

"use client";
import Link from 'next/link';
import { PrismicProvider } from '@prismicio/react';
import { PrismicPreview } from '@prismicio/next';
import { linkResolver, repositoryName } from '../prismicio';
import './globals.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <PrismicProvider
    linkResolver={linkResolver}
    internalLinkComponent={({ href, ...props }) => (
      <Link href={href}>
        <a {...props} />
      </Link>
    )}
  >
    <html lang="en">
      <head>
        <title>Ascent Design System</title>
        ...
      </head>
      <body>
        <PrismicPreview repositoryName={repositoryName}>
        {children}
        </PrismicPreview>
      </body>
    </html>
    </PrismicProvider>
  )
}

††

"use client";
import { SliceZone } from '@prismicio/react';
import { components } from '../slices';

export default function Home({ page }) {
  return (
    <SliceZone slices={page.data.slices} components={components} />
  )
}

1 Like

Hi there,

You might want to copy over the /customtypes folder from your previous project as well (like you copied the /slices and /.slicemachine folders), as it contains the customtypes json structures.
The custom types should then show up in the slicemachine.

Have a nice one
Alex

1 Like

You are 100% correct! I forgot to migrate the /customtypes folder. :see_no_evil: The Custom Types now show up in Slicemachine appropriately however I am still getting a 404 on the / route.

Unfortunately that was not the only issue and I am not sure I'll have time to debug this more. I know React 13 is new, and arguably in beta with the app/ folder. Not sure Slicemachine's integration will work with this new nested Layouts.

1 Like

Updating for clarification as of Nov 25, 2022. When Next 13's nested layouts / app directory is out of beta I imagine the Prismic team will be on top of updating prismic-next accordingly. Why do I say that? They were quick to update to Next 13's new next/image very quickly.

So I've created a small workaround for previewing within the Next.js 13's nested layouts / App directory.

It's a very basic solution and will enable those wanting to add previewing functionality within their App Directory until the Prismic Team add support for 'next/navigation' where they're currently using 'next/router' within the Prismic Next package.

Within your prismicio.js file, remove prismicNext.enableAutoPreviews.

export const createClient = (config = {}) => {
    const client = prismic.createClient(sm.apiEndpoint, {
        routes,
        ...config,
    })

    return client
}

Then within your page, fetch your previewData making sure to check for the Prismic preview ref.

import { createClient } from '../prismicio';
import SliceZone from './slice-zone';
import { previewData } from 'next/headers';

async function getPersitantData() {
  const data = previewData();

  const client = createClient({ ref: data?.ref });
  const nav = await client.getSingle("site-navigation");

  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  // Recommendation: handle errors
  if (!nav) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data');
  }

  return nav;
}

async function getSlices() {
  const data = previewData();
  console.log(data)
  const client = createClient({ ref: data?.ref  });
  const slices = await client.getSingle("homepage");
 
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.

  // Recommendation: handle errors
  if (!slices) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data');
  }

  return slices;
}


export default async function Home() {
  const nav = await getPersitantData();
  const slices = await getSlices();

  return (
   <div>
      <SliceZone slices={slices?.data?.slices} />
   </div>
  )
}
 

Then to exit your preview, you will need to create a file called exit-preview-button.tsx, that will enable you to exit preview mode.

'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';

export default function ExitPreviewButton() {
    const router = useRouter();
    return (  <Link href="/api/exit-preview" onClick={() => router.refresh()}>Close Preview</Link>);
}

For providers and the Prismic Toolbar where the @prismicio/next PrismicPreview provider will not work due to next/router.

Prismic Toolbar won't allow you to exit the Prismic Preview on close, however. This is due to the Toolbar not removing __next_preview_data cookie.

'use client';

import { PrismicProvider, PrismicToolbar } from '@prismicio/react';
import Link from 'next/link';
import { repositoryName } from '../prismicio'

export default function Providers({ children }: { children:  React.ReactNode }) {

    return (
        <PrismicProvider internalLinkComponent={(props) => <Link {...props} />}>
            {children}
            <PrismicToolbar repositoryName={repositoryName} type="new" />
        </PrismicProvider>
    );
}

Then in your layout.tsx file, you can then add.


import '@assets/main.css'
import '@assets/chrome-bug.css'
import Providers from './providers';
import { headers } from 'next/headers';
import ExitPreviewButton from './exit-preview-button';


export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {

  const headersList = headers();
  const cookies = headersList.get('cookie');
  console.log(cookies)
  return (
    <html lang="en">
      {/*
        <head /> will contain the components returned by the nearest parent
        head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
      */}
      <head />
      <body>
        <Providers>
          <>
            {children}
          </>
          {cookies?.indexOf('__next_preview_data') !== -1 &&
            <div className="sticky bottom-4 right-4 m-auto w-full max-w-[10rem] mr-10 mb-12 text-center">
              <div className="bottom-0 right-0 rounded-full p-5 bg-black shadow-lg w-42 text-white hover:text-gray-100 hover:bg-gray-800 " >
                <ExitPreviewButton />
              </div>
            </div>
          }
        </Providers>
      </body>
    </html>
  )
}

All preview and exit-preview APIs are as per the Next.js documentation.

I hope this helps those needing a solution related to previewing within this thread. I know it's not perfect, though it at least allows you to use the new App Directory.

2 Likes

Since this thread is putting together a lot of problems related to the migration, here is an issue that I'm dealing with, if you're interested: https://community.prismic.io/t/prismicio-next-1-x-using-old-userouter-hook