# Migrate Sitecore presentation to Uniform

> This section guides you through the process of migrating presentation layer from Sitecore to Uniform.

Source: https://docs.uniform.app/docs/integrations/content/sitecore/migrate-existing

This guide shows how to migrate presentation layer from Sitecore to Uniform.

## Benefits

1. Minimize your dependency on Sitecore and keep sourcing content from it. In other words, use Sitecore as a headless CMS. This simplifies migration and provides you with more future options.
2. Use modern visual experience management tools from Uniform with integrated personalization and A/B testing.
3. Build experiences with any front-end technology, not constrained by what Sitecore supports. Build with Next.js app router, Remix, etc.
4. Combine content from other sources within a single component.

In this section you will perform the following migration:

|  | Before migration | After migration |
| --- | --- | --- |
| Content | Managed in Sitecore | Managed in Sitecore |
| Front-end technology | Sitecore renderings & layouts built with MVC | Uniform components (React / Vue) |
| Layout instructions | Sitecore presentation details | Uniform composition |
| Site delivery | Sitecore CD instances | CDN / front-end cloud |

> **Tip:**
>
> This tutorial involves writing a bit of code. Uniform provides the [finished code](#finished-code) if you prefer not to have to write the code yourself.

## Enable Canvas services

1. In Content Editor, navigate to **sitecore > system > Uniform > Site Configurations > website > Configuration**.
2. Add an item using the template `Configure: Canvas Integration Service...`
3. Set the following fields:

   - **ApiKey**: Use the value from when you created the Uniform API key
   - **ProjectId**: Use the project ID value from when you created the Uniform API key
   - **Page Component Id**: `page`

   > **About this step:**
   >
   > The Uniform connector uses these settings to communicate with
   > the Uniform service. The one exception is the **Page Component Id**.
   > This is a value that's used during the component migration process
   > that you run in the next section.
4. Publish the site.

> **Info:**
>
> Before the Canvas-specific settings can be configured, some
> other steps must be completed. You will return to the site
> configuration later.

## Run migration tool

The Uniform Migration Tool serializes the various presentation
settings in Sitecore into a format so they can be pushed into
Uniform Canvas.

### Serialize renderings

1. Open a browser window to `/sitecore/admin/uniform/canvas/migration/components` on your Sitecore instance.
2. Tick the option **Skip components not used on pages included into sitemap (MVC only)**.

   > **About this step:**
   >
   > This option ensures that only components that are used in your
   > site are serialized. This setting can significantly reduce the
   > number of items that need to be serialized.
3. Tick the option **Generate zip**.

   > **About this step:**
   >
   > By default, the serialized components are generated as separate
   > files on the Sitecore server. This option results in a zip file
   > being generated that you can download. This enables you to
   > push the serialized components to Uniform using the Uniform CLI.
4. Click **Run serialization**.
5. When the serialization process is finished, a zip file will be
   sent to your browser. Popup blocking may prevent the file from
   being available, so check your browser you will see a
   summary in the **DEBUG** section.

   ![](https://docs.uniform.app/images/integrations/content/sitecore/v7/popup-blocked.png)

### Push components to Canvas

1. On your local development machine, unzip the zip files to the current directory.
2. Open a terminal to the folder where you downloaded the zip files from the previous section.
3. Enter the following command:

   ```shell
   npm i -g @uniformdev/cli @uniformdev/canvas
   ```
4. Create a file named `.env`
5. Set the values from when you created the Uniform API key:

_For the US region:_

```shell
UNIFORM_PROJECT_ID=
UNIFORM_API_KEY=
```

_For the EU region:_

```shell
UNIFORM_PROJECT_ID=
UNIFORM_API_KEY=
UNIFORM_CLI_BASE_EDGE_URL=https://eu.uniform.global
UNIFORM_CLI_BASE_URL=https://eu.uniform.app
```

1. Enter the following command:

   ```shell
   uniform canvas component push canvas_components
   ```
2. You will see output that indicates 5 components were pushed to Canvas:

   ```shell
   [A] Page (pid: page)
   [A] Sample MVC Sublayout (pid: sampleMvcSublayout)
   [A] Sample MVC Layout (pid: sampleMvcLayout)
   [A] Sample MVC Inner Sublayout (pid: sampleMvcInnerSublayout)
   [A] Sample MVC Rendering (pid: sampleMvcRendering)
   ```
3. In Canvas you will see the 5 components.

   ![](https://docs.uniform.app/images/integrations/content/sitecore/v7/component-library-after-push.png)

### Serialize pages

1. Open a browser window to `/sitecore/admin/uniform/canvas/migration/compositions` on your Sitecore instance.
2. Tick the option **Generate zip**.
3. Click **Run serialization**.
4. When the serialization process is finished, a zip file will be sent to your browser. Popup blocking may prevent the file from being available, so check your browser you will see a summary in the **DEBUG** section.

### Push compositions to Canvas

1. In the terminal, enter the following command (you will need to change the folder path where your extracted files are):

   ```shell
   uniform canvas composition push canvas_compositions_################/canvas_compositions
   ```
2. You will see output that indicates 2 compositions were pushed to Canvas:

   ```shell
   [A] Pattern: [Sample/Sample Item] (pid: 76036f5e-cbce-46d1-af0a-4143f9b557aa)
   [A] Home (pid: 110d559f-dea5-42ea-9c1c-8a5df7e70ef9)
   ```
3. In Canvas, navigate to the composition library.
4. Click the 1 composition that's displayed.

   ![](https://docs.uniform.app/images/integrations/content/sitecore/v7/composition-library-after-push.png)
5. Click **Save > Publish**.
6. Navigate to the pattern library.
7. Click the 1 pattern that's displayed.

   ![](https://docs.uniform.app/images/integrations/content/sitecore/v7/pattern-library-after-push.png)
8. Click **Save > Publish**.

## Create the front-end

Now that you have the layout from Sitecore presentation details
migrated to Canvas, you need to create an application that
uses the layout and implements the front-end components used
in that layout.

> **Tip:**
>
> This example uses Next.js as the front-end framework, but you
> can use any front-end technology you want. The layout and
> components defined in Canvas are technology agnostic.

### Create web app

Since you are migrating your site to a new front-end,
you must create the web app where you will define that
front-end.

1. Open a command-line interface (CLI).
2. Enter the following commands:

   ```shell
   npx create-next-app sample-mvc-site
   cd sample-mvc-site
   ```
3. Create a file named `.env`
4. Add a file `.env` and define the following variables:

   | Name | Value |
   | --- | --- |
   | `UNIFORM_API_SITENAME` | `website` |
   | `UNIFORM_API_KEY` | Your Uniform API key. Use the same value as you configured on the Canvas Integration Service in Sitecore. |
   | `UNIFORM_PROJECT_ID` | Your Uniform Project ID. Use the same value as you configured on the Canvas Integration Service in Sitecore. |
   | `UNIFORM_API_URL` | Your Sitecore URL. Use the same value as you configured in the Uniform integration. |
   | `SITECORE_API_KEY` | Your Sitecore API key or any GUID if you use Sitecore 8.2. Use the same value as you configured in the Uniform integration. |
   | `UNIFORM_API_TOKEN` | Your Uniform API token |

   The file will look like the following:

_For the US region:_

```shell
UNIFORM_API_TOKEN=
UNIFORM_PROJECT_ID=
UNIFORM_API_URL=
UNIFORM_API_SITENAME=website
UNIFORM_API_KEY=
SITECORE_API_KEY=
```

_For the EU region:_

```shell
UNIFORM_API_TOKEN=
UNIFORM_PROJECT_ID=
UNIFORM_API_URL=
UNIFORM_API_SITENAME=website
UNIFORM_API_KEY=
SITECORE_API_KEY=
UNIFORM_CLI_BASE_EDGE_URL=https://eu.uniform.global
UNIFORM_CLI_BASE_URL=https://eu.uniform.app
```

1. If your Sitecore instance uses self-signed SSL certificate, define the extra variable:

   - **Name**: `NODE_TLS_REJECT_UNAUTHORIZED`
   - **Value**: `0`

### Add npm packages

To add Uniform functionality to your web app, you
must add a number of npm packages. Some of these packages
are publicly available and some require an npm access
token.

Enter the following commands:

```shell
npm i dotenv @uniformdev/canvas @uniformdev/canvas-react @uniformdev/cli
npm i @uniformdev/canvas-sitecore
```

### Add Uniform configuration

You must configure Next.js to load Uniform settings when it runs.

1. Open the file `next.config.js`.
2. Change the contents to the following:

   ```js
   const { uniformNextConfig } = require('@uniformdev/next-server');
   module.exports = uniformNextConfig();
   ```

### Port assets

The Sitecore layout and components include some links to static
assets in Sitecore. These must be ported to the Next.js application
or else you will still have a dependency in your app to your
Sitecore CD server.

1. Get the contents the CSS file by opening your browser to `https://your-sitecore-instance/default.css`.
2. In your Next.js app, replace the content of the file `styles/globals.css` with the CSS from the Sitecore server.
3. Download the image from `https://your-sitecore-instance/-/media/Default%20Website/cover.ashx`.
4. In your Next.js app, copy the image file to the folder `public`.
5. In `styles/global.css`, find the following line:

   ```css
   background: white url('-/media/Default Website/cover.ashx') no-repeat;
   ```
6. Replace the previous line with the following:

   ```css
   background: white url('/cover.jpeg') no-repeat;
   ```
7. Download the image from `https://your-sitecore-instance/-/media/Default Website/sc_logo.ashx`.
8. In your Next.js app, copy the image file to the folder `public`.
9. Download the image from `https://your-sitecore-instance/sitecore/images/favicon.ico`.
10. In your Next.js app, copy the image file to the folder `public`.

### Create components

You need to create the React components that are used to implement
the front-end. This involves porting code from Sitecore to React.
The following files on your Sitecore server represent the presentation
logic that you will port to React:

| Component | File |
| --- | --- |
| Sample MVC Layout | `...\Website\Views\Shared\Sample MVC Layout.cshtml` |
| Sample MVC Sublayout | `...\Website\Views\Sample\SampleMvcSublayout.cshtml` |
| Sample MVC Inner Sublayout | `...\Website\Views\Sample\SampleMvcInnerSublayout.cshtml` |
| Sample MVC Rendering | `...\Website\Views\Sample\SampleMvcRendering.cshtml` |

#### Component: Sample Layout

In this component, the webcontrol `sc:placeholder` is replaced with a React component `UniformSlot`.
Create a file `components/SampleLayout.jsx`:

```typescript
import Head from 'next/head';
import { UniformSlot } from '@uniformdev/canvas-react';
export function SampleLayout() {
  return (
    <>
      <Head>
        <title>Welcome to Sitecore</title>
      </Head>
      <div id="MainPanel">
        <UniformSlot name="main"></Slot>
      </div>
    </>
  );
}
```

> **Tip:**
>
> The Sitecore layout also includes a link to the CSS file `/default.css`,
> which is located on the Sitecore server at `C:\inetpub\wwwroot\default.css`.
> In order for these styles to be applied to your page, the contents
> of this css file can be added to the React file `styles/global.css`.
>
> This file includes a style that sets an image. You must change
> the URL to be fully qualified by adding the hostname for your
> Sitecore server. For example, `https://yoursitecore/-/media/Default Website/cover.ashx`.

#### Component: Sample Sublayout

Create a file `components/SampleSublayout.jsx`:

```js
import { UniformSlot } from '@uniformdev/canvas-react';
export function SampleSublayout() {
  return (
    <div id="CenterColumn">
      <UniformSlot name="centercolumn" />
    </div>
  );
}
```

#### Component: Sample Inner Sublayout

Create a file `components/SampleInnerSublayout.jsx`:

```js
import { UniformSlot } from '@uniformdev/canvas-react';
export function SampleInnerSublayout() {
  return (
    <div id="InnerCenter">
      <div id="Header">
        <img src="/sc_logo.png" alt="Sitecore" id="scLogo" />
      </div>
      <div id="Content">
        <div id="LeftContent">
          <UniformSlot name="content" />
        </div>
      </div>
      <div id="Footer">
        <hr className="divider" />&#169; {new Date().getFullYear()} Sitecore
      </div>
    </div>
  );
}
```

#### Component: Sample Rendering

This component displays fields from the Sitecore data source item.
If the data source item isn't selected, it uses a context item
(a page item) instead. Uniform makes the item available as a prop
that's passed to the component. In the next section you will wire
this up.

Create a file `components/SampleRendering.jsx`:

```js
export function SampleRendering({ model }) {
  return (
    <div>
      <h1 className="contentTitle">{model.Title}</h1>
      {/* rich text field needs to be rendered via dangerouslySetInnerHTML */}
      <div className="contentDescription" dangerouslySetInnerHTML={{ __html: model.Text }}></div>
    </div>
  );
}
```

> **Note:**
>
> The `model` field name was chosen by a convention that will be explained in next sections.

### Map component name to implementation

Each component defined in Canvas has a _public ID_. When you
serialized the components from Sitecore, Uniform generated
this value from the Sitecore item name.

When your web app reads composition definitions from Canvas,
the composition and the components that are assigned to the
composition are identified using this value.

You must provide instructions to your web app on how to map the
_public ID_ to the front-end implementation of that component.
In your web app, React components provide that implementation.

Create a file `lib/resolveRenderer.js`:

```js
import { SampleLayout } from '../components/SampleLayout';
import { SampleSublayout } from '../components/SampleSublayout';
import { SampleInnerSublayout } from '../components/SampleInnerSublayout';
import { SampleRendering } from '../components/SampleRendering';
import { DefaultNotImplementedComponent } from '@uniformdev/canvas-react';
const mapping = {};
mapping['sampleMvcLayout'] = SampleLayout;
mapping['sampleMvcSublayout'] = SampleSublayout;
mapping['sampleMvcInnerSublayout'] = SampleInnerSublayout;
mapping['sampleMvcRendering'] = SampleRendering;
export const resolveRenderer = (component) => {
  if (component?.type) {
    const implementation = mapping[component.type]
    if (implementation) return implementation;
  }
  return DefaultNotImplementedComponent
};
```

## Add Uniform to page

In Canvas you have a composition that represents the home page
and describes the layout for the page. You have a number of
React components that represent the implementation of those
components. Now you must configure the Next.js app to use the
information from the Canvas composition in order to render
the page using the React components you implemented.

### Add composition component

Replace the contents of the file `pages/index.jsx` with the following:

```js
import { UniformComposition, UniformSlot } from "@uniformdev/canvas-react";
import { resolveRenderer } from "../lib/resolveRenderer";
export default function Home({ composition }) {
  return (
    <UniformComposition data={composition} resolveRenderer={resolveRenderer}>
      <UniformSlot name="layout" />
    </UniformComposition>
  );
}
```

> **About this code:**
>
> The component UniformComposition accepts props that represent the
> composition (which is retrieved from Canvas) and a function
> that resolves the React component that corresponds to the
> public id for a component from Canvas.
>
> This code also adds a component to render the slot _layout_.
> When the Uniform migration tool serializes pages, it creates
> compositions for Canvas. Each composition includes a slot
> named _layout_. All the presentation details that the
> migration tool extracted from the Sitecore item is included
> in this slot.

### Retrieve the composition

1. Add the following code to the top of the file `pages/index.jsx`:

   ```js
   import {
       CanvasClient,
   } from "@uniformdev/canvas";
   import { UniformComposition, UniformSlot } from "@uniformdev/canvas-react";
   import { resolveRenderer } from "../lib/resolveRenderer";
   async function getComposition(slug) {
       const client = new CanvasClient({
       apiKey: process.env.UNIFORM_API_KEY,
       projectId: process.env.UNIFORM_PROJECT_ID,
       });
       const { composition } = await client.getCompositionBySlug({
       slug,
       });
       return composition;
   }
   export default function Home({ composition }) {
       return (
       <UniformComposition data={composition} resolveRenderer={resolveRenderer}>
           <UniformSlot name="layout" />
       </UniformComposition>
       );
   }
   ```
2. Add the following code to the file `pages/index.jsx`:

   ```jsx
   import {
       CanvasClient,
   } from "@uniformdev/canvas";
   import { UniformComposition, UniformSlot } from "@uniformdev/canvas-react";
   import { resolveRenderer } from "../lib/resolveRenderer";
   async function getComposition(slug) {
       const client = new CanvasClient({
       apiKey: process.env.UNIFORM_API_KEY,
       projectId: process.env.UNIFORM_PROJECT_ID,
       });
       const { composition } = await client.getCompositionBySlug({
       slug,
       });
       return composition;
   }
   export async function getStaticProps() {
       const slug = "/";
       const composition = await getComposition(slug);
       return {
       props: { composition },
       }
   }
   export default function Home({ composition }) {
       return (
       <UniformComposition data={composition} resolveRenderer={resolveRenderer}>
           <UniformSlot name="layout" />
       </UniformComposition>
       );
   }
   ```

### Add enhancer

When you retrieve the composition from Canvas, Sitecore item ids
are included in the data. You must use an enhancer to retrieve
the fields for those items.

1. Add the following code to the file `pages/index.jsx`:

   ```jsx
   import {
       CanvasClient,
       enhance,
       EnhancerBuilder,
   } from "@uniformdev/canvas";
   import { UniformComposition, UniformSlot } from "@uniformdev/canvas-react";
   import {
       createItemEnhancer,
       getPageItemId,
       noopLogger,
       parseUniformServerConfig,
   } from "@uniformdev/canvas-sitecore";
   ...
   ```
2. Add the following code:

   ```jsx
   export async function getStaticProps() {
       const slug = "/";
       const composition = await getComposition(slug);
       const config = parseUniformServerConfig(process.env, noopLogger, true);
       return {
       props: { composition },
       };
   }
   ```
3. Add the following code:

   ```jsx
   export async function getStaticProps() {
       const slug = "/";
       const composition = await getComposition(slug);
       const config = parseUniformServerConfig(process.env, noopLogger, true);
       const pageId = getPageItemId({ composition });
       return {
       props: { composition },
       };
   }
   ```
4. Add the following code:

   ```jsx
   export async function getStaticProps({ preview }) {
       const slug = "/";
       const composition = await getComposition(slug);
       const config = parseUniformServerConfig(process.env, noopLogger, true);
       const pageId = getPageItemId({ composition });
       const itemEnhancer = createItemEnhancer({
       pageId,
       config,
       isPreview: preview,
       });
       return {
       props: { composition },
       };
   }
   ```
5. Add the following code:

   ```jsx
   export async function getStaticProps({ preview }) {
       const slug = "/";
       const composition = await getComposition(slug);
       const config = parseUniformServerConfig(process.env, noopLogger, true);
       const pageId = getPageItemId({ composition });
       const itemEnhancer = createItemEnhancer({
       pageId,
       config,
       isPreview: preview,
       });
       const enhancers = new EnhancerBuilder().component(
       [
           "sampleMvcLayout",
           "sampleMvcSublayout",
           "sampleMvcInnerSublayout",
           "sampleMvcRendering",
       ],
       (builder) => builder.data("model", itemEnhancer)
       );
       return {
       props: { composition },
       };
   }
   ```
6. Add the following code:

   ```jsx
   export async function getStaticProps({ preview }) {
       const slug = "/";
       const composition = await getComposition(slug);
       const config = parseUniformServerConfig(process.env, noopLogger, true);
       const pageId = getPageItemId({ composition });
       const itemEnhancer = createItemEnhancer({
       pageId,
       config,
       isPreview: preview,
       });
       const enhancers = new EnhancerBuilder().component(
       [
           "sampleMvcLayout",
           "sampleMvcSublayout",
           "sampleMvcInnerSublayout",
           "sampleMvcRendering",
       ],
       (builder) => builder.data("model", itemEnhancer)
       );
       await enhance({ composition, enhancers });
       return {
       props: { composition },
       };
   }
   ```

## Start the web app

When you run the web app, you should see the page from the default
Sitecore site, but Sitecore isn't handling page rendering. Sitecore
is only acting as a headless CMS.

1. In the terminal, enter the following command:

   ```bash
   npm run dev
   ```
2. Open your browser to `http://localhost:3000`

## Finished code

You can get the finished code described in this tutorial on [GitHub](https://github.com/uniformdev/uniform-docs-examples/tree/integrations/sitecore/migrate-sample-mvc-site-finished).
