---
title: "Migrate to Slice Machine"
description: "A guide to migrate your Prismic repository to Slice Machine."
meta_title: "Migrate to Slice Machine"
category: "concepts"
audience: developers
lastUpdated: "2026-01-07T13:31:47.000Z"
---

# Overview

This guide walks you through upgrading from the Legacy Builder to Slice Machine.

Slice Machine offers several improvements:

* **Shared slices**: Create slices once and reuse them across multiple custom types, reducing duplication and maintenance.
* **Page types**: A new model designed for web pages, with built-in metadata fields and a slice zone. New Page Builder features focus on page types.
* **Custom types**: Continue using custom types for menus, taxonomies, configurations, and other non-page entities.
* **Developer experience**: Slice Machine generates typed page snippets and provides a local development environment with the Slice Simulator.

Consider converting some of your existing custom types to page types during the migration.

We recommend using an [environment](https://prismic.io/docs/environments.md) to safely test changes without impacting your live project. Environments are available on Enterprise plans. Visit our [Pricing](https://prismic.io/pricing) page to learn more or reach out to [sales@prismic.io](mailto:sales@prismic.io).

# Prepare your repository

1. **Choose an environment**

   Select or create a dedicated environment for the upgrade.

2. **Synchronize your repository**

   [Synchronize](https://prismic.io/docs/environments.md#resync-content) your dev environment with production.

# Install Slice Machine

1. **Create a Git branch**

   Create a new Git branch in your website's code where you'll complete the upgrade.

2. **Update Packages**

   Ensure you use the latest version of your framework, and upgrade your Prismic packages to the latest versions.

3. **Initialize Slice Machine**

   Install and initialize Slice Machine with the following command:

   ```sh
   npx @slicemachine/init@latest
   ```

   Select your Prismic repository. Make sure you select the repository, not the environment.

   Custom types will be pulled locally. If not, use this script:

   ```tsx filename=fetch-models.ts collapsed
   /**
    * Run this script in your codebase to fetch models from a
    * legacy Prismic repository
    * - `npm install p-limit`
    * - `npm install -d @slicemachine/manager`
    * - Define the legacy repository in the `SOURCE_REPO` variable.
    * - Run the script `npx tsx fetch-models.ts`
    */

   import { createSliceMachineManager } from "@slicemachine/manager";
   import pLimit from "p-limit";

   // Parent repository name
   const SOURCE_REPO = "my-repo-name"; // Legacy repository name

   const manager = createSliceMachineManager();

   async function main() {
     const start = performance.now();

     // Ensures that you are logged in before doing anything.
     if (!manager.user.checkIsLoggedIn()) {
       throw new Error(
         "You are not logged in. Please log in first with `npx prismic-cli login` and try again.",
       );
     }

     await manager.plugins.initPlugins();

     // We "trick" the manager into thinking that we're in the parent repository by
     // setting the environment to the parent repository name.
     manager.project.updateEnvironment({ environment: SOURCE_REPO });

     const remoteTypes = await manager.customTypes.fetchRemoteCustomTypes();
     const remoteSlices = await manager.slices.fetchRemoteSlices();

     const createCustomTypeLimit = pLimit(8);

     console.log(
       `Pulling ${remoteSlices.length} slices and ${remoteTypes.length} types from ${SOURCE_REPO}`,
     );

     let pulledSlices = 0;

     console.log(`Pulling existing slices... (0/${remoteSlices.length})`);
     await Promise.all(
       remoteSlices.map(async (model) => {
         await createCustomTypeLimit(() =>
           manager.slices.createSlice({
             libraryID: "./src/slices", // Use one slice library path from the slicemachine.config.json file
             model: model,
           }),
         );
         pulledSlices++;
         console.log(
           `Pulling existing slices... (${pulledSlices}/${remoteSlices.length})`,
         );
       }),
     );

     console.log("Pulled existing slices");

     let pulledTypes = 0;

     console.log(`Pulling existing types... (0/${remoteTypes.length})`);
     await Promise.all(
       remoteTypes.map(async (model) => {
         await createCustomTypeLimit(() =>
           manager.customTypes.createCustomType({ model }),
         );
         pulledTypes++;
         console.log(
           `Pulling existing types... (${pulledTypes}/${remoteTypes.length})`,
         );
       }),
     );

     console.log("Pulled existing types");
     console.log("Synced data with Prismic");

     // Reuse the default environment (main repository)
     await manager.project.updateEnvironment({ environment: undefined });

     console.log("Synced in %os", Math.round((performance.now() - start) / 1000));
   }

   main();
   ```

4. **Open Slice Machine**

   Go to `http://localhost:9999`. Switch to the environment you'll be using to complete the upgrade.

   > You can make sure Slice Machine is targeting your environment by checking the `.env.local` file in at the root of your code. It's updated every time you switch environment to target the matching endpoint.

5. **Activate Legacy Slice Upgrader**

   Go to `http://localhost:9999/labs` and activate the upgrader.

   With the Legacy Slice Upgrader activated, you can now head to the Custom Types page in Slice Machine to start upgrading Legacy Slices.

# Migrate your slices

In Slice Machine, go to the custom types page. A **Migrate legacy slice** button is now displayed on each Legacy Slice.

You can select one of three options:

* **[Upgrade slice](#upgrade-slice):** Converts a legacy slice to a new shared slice
* **[Convert to slice variation](#convert-to-slice-variation):** Adds a legacy slice as a variation of an existing shared slice
* **[Merge with another slice](#merge-with-another-slice):** Merges a legacy slice with an existing shared slice with the same model definition

> We recommend upgrading slices one at a time. Push changes to your environment, test, and validate before upgrading the next slice.

You'll need to update your code when upgrading, converting, or merging slices.

Your repository supports both legacy and upgraded slices during migration, keeping your project live. Remove legacy slice support once complete.

> We recommend using the Slice Simulator to iterate on the components of your upgraded slices. Learn more on the [Slices](https://prismic.io/docs/slices.md#simulate-slices) page.

## Upgrade slice

Without existing shared slices, this is the only option. It converts the legacy slice to a new shared slice.

1. **Select “Upgrade slice”**

   Slice Machine will generate a `slices/` folder at the root of your app or in its `src/` directory. Each upgraded slice will get automatically typed in `prismicio-types.d.ts` at the root of your app. Each upgraded slice will also get its own folder generated in `slices/` containing:

   * An `index.tsx` for the slice's React or Vue component
   * A `model.json` describing the slice's structure
   * A `mock.json` for the slice simulator

2. **Build or import your component**

   In the upgraded slice's `index.tsx`, build or import your slice's React/Vue component.

   For example, we upgraded the homepage's `Text` slice and imported our existing `TextHome` react component in the `Text` slice's `index.tsx`:

   ```jsx filename=slices/Text/index.tsx collapsed
   import { Content } from "@prismicio/client";
   import { SliceComponentProps } from "@prismicio/react";
   import { TextHome } from "@/components/TextHome";

   /**
    * Props for `Text`.
    */
   export type TextProps = SliceComponentProps<Content.TextSlice>;

   /**
    * Component for "Text" Slices.
    */
   const Text = ({ slice }: TextProps): JSX.Element => {
     return (
       <section
         data-slice-type={slice.slice_type}
         data-slice-variation={slice.variation}
       >
         <TextHome slice={slice} />
       </section>
     );
   };

   export default Text;
   ```

3. **Launch the Slice Simulator**

   Check that your fields have been correctly mapped into the slice's React component. The slice should be displayed with mock content filling its fields and you should be able to see it update when editing the mock content.

   Learn more about the slice simulator in our [documentation](https://prismic.io/docs/slice-machine.md#simulate-slices).

   <VideoCardList>
     <VideoCard title="Video" description="Learn how to upgrade and rename a Hero slice." href="https://www.youtube.com/watch?v=OTygSPKnScM" />
   </VideoCardList>

4. **Import the components object**

   The first time you upgrade a slice, Slice Machine generates a global index in your app in `slices/index.ts` . This file exports a `components` object that must be passed to all your `<SliceZone>` in order to display the new shared slices. Learn more about the Slice Zone in our documentation ([Next](https://prismic.io/docs/technical-reference/prismicio-react.md?version=v2#slicezone), [Nuxt](https://prismic.io/docs/technical-reference/prismicio-vue/v3.md#slicezone), [SvelteKit](https://prismic.io/docs/technical-reference/prismicio-svelte/v0.md#slicezone)).

   Import the `components` object from the global index in your pages and pass it to `<SliceZone>`. You only need to do this once.

   ```tsx filename=app/page.tsx {3}
   import { SliceZone } from "@prismicio/react";
   import { createClient } from "@/prismicio";
   import { components } from "@/slices";

   function Page() {
     const client = createClient();
     const page = await client.getSingle("homepage");

     return (
       <SliceZone
         slices={page.data.body}
         components={components} // [!code highlight]
       />
     );
   }
   ```

   <VideoCardList>
     <VideoCard title="Video" description="Learn how to import slice components into your Slice Zones." href="https://www.youtube.com/watch?v=ncshvUIqGyk" />
   </VideoCardList>

## Convert to a slice variation

Available once you have a shared slice. Converts a legacy slice into a variation of an existing shared slice.

Variations help organize slices and give editors flexibility.

For example, if you originally have multiple `Hero` slices across your custom types, you can upgrade the first and convert the others into variations. This way you will have one `Hero` slice with multiple variations sharing the same `model.json` and the same `index.tsx`. You can then conditionally display the different components.

1. **Select "Convert to a slice variation"**

2. **Import the variation**

   Import the variation component in the slice's index and use conditional rendering to display the slice:

   ```tsx filename=slices/Hero/index.tsx
   import { Content } from "@prismicio/client";
   import { SliceComponentProps } from "@prismicio/react";

   import HeroHome from "@/components/Hero/HeroHome";
   import HeroTitleOnly from "@/components/Hero/HeroTitleOnly";
   import HeroWithBlueBackground from "@/components/Hero/HeroBlueBackground";

   /**
    * Props for `Hero`.
    */
   export type HeroProps = SliceComponentProps<Content.HeroSlice>;

   /**
    * Component for "Hero" Slices.
    */
   function Hero({ slice }: HeroProps) {
     switch (slice.variation) {
       case "default":
         return <HeroHome slice={slice} />;
       case "heroTitleOnly":
         return <HeroTitleOnly slice={slice} />;
       case "heroBlueBackground":
         return <HeroWithBlueBackground slice={slice} />;
     }
   }
   ```

3. **Launch the Slice Simulator**

   Open the slice simulator and check the right component is displayed by switching variations:

   <VideoCardList>
     <VideoCard title="Video" description="Learn how to convert a legacy slice into a variation of an existing shared slice." href="https://www.youtube.com/watch?v=agRuJOeFPg0" />
   </VideoCardList>

## Merge with another slice

Available when the legacy slice has the same model definition as an existing shared slice (matching field IDs and types). Field configurations aren't compared, so this may not be preferred.

Use this when slices are identical—**same fields and same components**.

Make sure the fields share the same configurations as well (dimensions in image fields, formatting options in rich text fields, etc).

## If multiple slices have the same ID

Slice Machine generates IDs from slice names, which must be unique.

If multiple slices across custom types share a name, the upgrade modal shows an error.

For example, after upgrading a `Text` slice from `home`, upgrading a different `Text` slice from `blog_article` requires renaming it in the upgrade form. Slice Machine maps the new ID to the legacy ID.

```json {6}
{
  "id": "BlogContent",
  "type": "SharedSlice",
  "name": "BlogContent",
  "legacyPaths": {
    "blog_article::body::text": "default"
  }
}
```

# Push to an environment

1. **Review your changes**

   Once you're happy with your modifications, go to the **Review changes** page in Slice Machine.

2. **Choose an environment**

   Make sure you're targeting a non-production environment and push your changes.

   > After pushing your changes, your documents will be upgraded automatically. To reflect the changes in the API and flush the cache, you need to publish a document. Any will do.

3. **Enable live preview**

   Go to your environment's Page Builder, then to an upgraded page.

   Enable the [live preview](https://prismic.io/docs/nextjs.md#set-up-live-previewing) in the top right menu. The slice simulator URL should be `https://your-site.com/slice-simulator`. If you're working locally, it should be the same URL as the `localSliceSimulatorURL` property from your `slicemachine.config.json` (such as `http://localhost:3000/slice-simulator`).

   You should see live previews of your upgraded slices in the table of slice.

4. **Update the API**

   Make a small change in any field (like adding a space in a rich text) and save the document. Publish it to update the API.

<VideoCardList>
  <VideoCard title="Video" description="Learn how to activate the slice simulator in the Page Builder and update your API." href="https://www.youtube.com/watch?v=VzSJhWVUR9I" />
</VideoCardList>

> If there are issues or conflicts, you can [resync your environment](https://prismic.io/docs/environments.md#resync-content) with production. Fix the issues, and push your models from Slice Machine to your environment again.

<VideoCardList>
  <VideoCard title="Video" description="Learn how to reset your models if you encounter issues." href="https://www.youtube.com/watch?v=_pyuK2C09Dc" />
</VideoCardList>

# Push to production

1. **Merge your Git branch**

   After reviewing the upgraded pages in your Prismic repository, merge the Git branch used for the upgrade with the branch used for production.

2. **Review your changes**

   Go back to Slice Machine and select production in the environment dropdown. You should see all your upgraded models in the “review changes” page.

   Make sure you're targeting your repository's production and push your changes.

3. **Enable live preview**

   Go to your Prismic repository, check your production is using the shared slices by checking the slice library in any document (click the + button to add a slice). [Set up live preview](https://prismic.io/docs/migrate-to-slice-machine.md#enable-live-preview) in the page builder's top right menu. The slices previews should appear.

4. **Update the API**

   Make a small change in any field (like adding a space in a rich text) and save the document. Publish it to update the API.

# Clean your code

After upgrading all models and confirming your project uses only shared slices, delete references to old models in your `<SliceZone>` components.

You're now fully migrated to Slice Machine!
