> ## Documentation Index
> Fetch the complete documentation index at: https://flatfile.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart Portal 2 Upgrade

> Moving on up... to the Platform

> [!WARNING]
>
> **Legacy Documentation**: This documentation is maintained for backward
> compatibility purposes only. For the latest features and best practices,
> please refer to the current documentation.

## Overview

This guide is designed to help you quickly transition from Portal 2 to the new
and improved Platform. Using our
[V2 Shim package](https://www.npmjs.com/package/@flatfile/v2-shims) for
assistance with the transition, you can get started on the new Platform within a
few hours. To help you compare and contrast between your Portal 2 implementation
and the Platform implementation, we created
[this Github Repository](https://github.com/FlatFilers/Upgrade-Portal) as a way
to help you see the upgrade process from beginning to the end.

## Before You Begin

With the new Platform, comes a brand new place to sign up for it. Before getting
started on your upgrade, you'll need to [sign up](https://platform.flatfile.com)
for a new account.

## Install the V2 Shims package

Before you can start using all the wonderful tools in this guide to implement
Flatfile, you'll need to install a couple of packages, the V2 Shims and Flatfile
API packages.

> [!NOTE]
>
> If you are using our `@flatfile/react` package, be sure to install version
> 7.9.1 or higher to get the latest Platform React component.

```bash JavaScript theme={null}
npm install @flatfile/v2-shims @flatfile/api
```

```bash React theme={null}
npm install @flatfile/v2-shims @flatfile/api @flatfile/react@7.9.1
```

## Convert Your Config

The Portal 2 configuration is what contains your settings and fields in your
Portal implementation.

```js JavaScript theme={null}
const importer = new FlatfileImporter(
    "YOUR_LICENSE_KEY",
    { } // This is your configuration object
)
```

```jsx React theme={null}
<FlatfileButton
    licenseKey="YOUR_LICENSE_KEY"
    customer={{ userId: '1234' }}
    settings={} // This is your configuration object
>
    Import Contacts
</FlatfileButton>
```

You'll be able to use this configuration object with the V2 Shims package to
configure your new implementation. Keep in mind that the below snippets use a
couple of new concepts like a [Job](https://flatfile.com/docs/core-concepts/jobs.md) and
[Listener](https://flatfile.com/docs/legacy-docs/tutorials/projects/meet-the-listener). While you don't need to learn about
these to get started, they are useful for adding new functionality onto your
importer at some point in the future.

```js Portal 2 JavaScript theme={null}
import FlatfileImporter from '@flatfile/adapter'

const config = {
    type: 'Contacts',
    fields: [
        {
            key: 'name',
            label: 'Name',
            description: 'Contact name',
            validators: [
                { validate: 'required' }
            ]
        }
    ]
}

const importer = new FlatfileImporter('LICENSE_KEY', config)
```

```js Platform JavaScript theme={null}
import { initializeFlatfile } from "@flatfile/javascript";
import { schemas } from "./schemas";
import { listener } from "../listeners/listener";
import { configToBlueprint } from "@flatfile/v2-shims";

const config = {
    type: 'Contacts',
    fields: [
        {
            key: 'name',
            label: 'Name',
            description: 'Contact name',
            validators: [
                { validate: 'required' }
            ]
        }
    ]
}

window.openFlatfile = ({publishableKey}) => {
    if (!publishableKey) {
        throw new Error(
            "You must provide a publishable key - pass through in index.html"
        );
    }

    const flatfileOptions = {
        publishableKey,
        name: 'Contact Space',
        workbook: configToBlueprint(config),
        listener,
        sidebarConfig: {
            showSidebar: false,
        },
        // Additional props...
    };

    initializeFlatfile(flatfileOptions);
};
```

```jsx Portal 2 React theme={null}
import { FlatfileButton } from "@flatfile/react"

const config = {
    type: 'Contacts',
    fields: [
        {
            key: 'name',
            label: 'Name',
            description: 'Contact name',
            validators: [
                {validate: 'required'}
            ]
        }
    ]
}

export default function App() {
    return (
        <div className="App">
            <FlatfileButton
                licenseKey="YOUR_V2_LICENSE_KEY"
                customer={{ userId: '1234'}}
                settings={config}
            >
            Import Contacts
            </FlatfileButton>
        </div>
    )
}
```

```js Platform React theme={null}
import { listener } from "./listener";
import { configToBlueprint } from "@flatfile/v2-shims";
import { FlatfileProvider, Space, Workbook } from "@flatfile/react";
import { useFlatfile, useListener } from "@flatfile/react";
import { Flatfile } from "@flatfile/api";

const FFApp = () => {
    const { open, openPortal, closePortal } = useFlatfile();

    // import file directly
    useListener(listener, []);

    return (
        <div className={"App"}>
        <div className={"contract"}>
            <button
                onClick={() => {
                    open ? closePortal() : openPortal();
                }}
            >
            {open ? "OPEN" : "CLOSE"} PORTAL
            </button>
        </div>

        <Space
            config={{
                metadata: {
                    sidebarConfig: {
                        showSidebar: true,
                    },
                },
            }}
        >
            <Workbook
            config={
                configToBlueprint(config as any) as Flatfile.CreateWorkbookConfig
            }
            onSubmit={(sheet) => {
                console.log("onSubmit", { sheet });
            }}
            ></Workbook>
        </Space>
        </div>
    );
};

const App = () => {
    return (
        <FlatfileProvider
            publishableKey={"pk_1234"}
            config={{
                displayAsModal: true,
            }}
        >
        <FFApp />
        </FlatfileProvider>
    );
};

export default App;
```

## Converting your Record Hooks

If you're transitioning from a V2 Record Hook to a Platform Record Hook in your
code, you can make the conversion by simply extracting and wrapping your
existing Record Hook code in the V2 Shim `convertHook` method.

> [!NOTE]
>
> If you're using V2 Record Hooks `mode` to split hooks on "init" or on
> "change", Platform does not have this mode functionality. It does, however,
> have better overall hooks performance and a new [Bulk Record
> Hook](https://flatfile.com/plugins/plugin-record-hook#additional-options)
> method that make `mode` unnecessary.

```js Portal 2 JavaScript theme={null}
const importer = new FlatfileImporter('LICENSE_KEY', config)

const recordHooksCallback = async (record) => {
    let out = {};

    if (record.firstName && !record.lastName) {
        out.lastName = {
            value: 'Rock',
            info: [
                {
                    message: 'No last name provided so welcome to the Rock fam.',
                    level: 'warning'
                }
            ]
        }
    }
    return out;
}

importer.registerRecordHook(recordHooksCallback);
```

```js Platform theme={null}
import { convertHook } from "@flatfile/v2-shims";

export default function (listener) {
    listener.filter({ job: "space:configure" }, (configure) => {
        // code from above
    });
    // new Record Hook code

    listener.use(
        recordHook('TestSheet', async (record, event) => {
            return convertHook(recordHooks)(record)
        })
    )
}
```

```jsx Portal 2 React theme={null}
import { FlatfileButton } from "@flatfile/react"
import flatfileConfig from "./config"

const recordHooksCallback = async (record) => {
    let out = {};

    if (record.firstName && !record.lastName) {
        out.lastName = {
            value: 'Rock',
            info: [
                {
                    message: 'No last name provided so welcome to the Rock fam.',
                    leval: 'warning'
                }
            ]
        }
    }
    return out;
}

export default function App() {
    return (
        <div className="App">
            <FlatfileButton
                licenseKey="YOUR_V2_LICENSE_KEY"
                customer={{ userId: '1234'}}
                settings={flatfileConfig}
                onRecordInit={recordHooksCallback}
                onRecordChange={recordHooksCallback}
            >
            Import Contacts
            </FlatfileButton>
        </div>
    )
}
```

```jsx Platform React - Embed theme={null}
// Be sure to use @flatfile/react 7.9.1 or later
import { listener } from "./listener";
import { configToBlueprint } from "@flatfile/v2-shims";
import { FlatfileProvider, Space, Workbook } from "@flatfile/react";
import { useFlatfile, useListener } from "@flatfile/react";
import { Flatfile } from "@flatfile/api";

const FFApp = () => {
    const { open, openPortal, closePortal } = useFlatfile();

    // import file directly
    useListener(listener, []);

    return (
        <div className={"App"}>
        <div className={"contract"}>
            <button
                onClick={() => {
                    open ? closePortal() : openPortal();
                }}
            >
            {open ? "OPEN" : "CLOSE"} PORTAL
            </button>
        </div>

        <Space
            config={{
                metadata: {
                    sidebarConfig: {
                        showSidebar: true,
                    },
                },
            }}
        >
            <Workbook
            config={
                configToBlueprint(config as any) as Flatfile.CreateWorkbookConfig
            }
            onSubmit={(sheet) => {
                console.log("onSubmit", { sheet });
            }}
            ></Workbook>
        </Space>
        </div>
    );
};

const App = () => {
    return (
        <FlatfileProvider
            publishableKey={"pk_1234"}
            config={{
                displayAsModal: true,
            }}
        >
        <FFApp />
        </FlatfileProvider>
    );
};

export default App;
```

```js Platform React - Listener theme={null}
import { convertHook } from "@flatfile/v2-shims";

const recordHooksCallback = async (record) => {
    let out = {};

    if (record.firstName && !record.lastName) {
        out.lastName = {
            value: 'Rock',
            info: [
                {
                    message: 'No last name provided so welcome to the Rock fam.',
                    leval: 'warning'
                }
            ]
        }
    }
    return out;
}

export default function (listener) {
    listener.filter({ job: "space:configure" }, (configure) => {
        // code from above
    });
    // new Record Hook code

    listener.use(
        recordHook('Contracts', async (record, event) => {
            return convertHook(recordHooksCallback)(record)
        })
    )
}
```

> [!NOTE]
>
> If you're using React and want more ideas on how you can implement your
> listener code or add plugins, check out our full React documentation
> [here](https://flatfile.com/docs/legacy-docs/tutorials/projects/meet-the-listener).
