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

---
id: c52482c8-47e9-41a9-b765-2d3cfe69c1ab
---

# Migrate a HubL theme to a project

> Learn how to migrate a classic HubL theme to the projects framework to build with React.

Migrating an existing HubL theme to the projects framework involves restructuring the theme directory, updating file extensions, and adding necessary configuration files. This guide outlines the steps to perform this migration.

After following the steps in this guide, you'll have built and deployed a copy of your existing theme using the projects framework. You can then use the theme in your HubSpot account like any other theme, including swapping your existing pages to the new templates or using them to create new pages.

<Tip>
  This migration will not replace your existing theme files. Instead, you'll recreate a subset of your previous files in a new project. As a result, there are some manual steps involved for moving existing pages to the new theme.
</Tip>

## Project setup

To build and deploy your theme on the latest version of the developer platform, you'll need to create a project to contain your theme and its assets. After creating the project, you'll then need to modify your theme directories and files to be compatible with the CMS React [project structure](/cms/start-building/introduction/react-plus-hubl/project-structure#project-structure) requirements.

Before starting the migration, your theme structure will resemble the one shown below.

```plaintext theme={null}
theme/
├── assets/
├── modules/
├── partials/
├── styles/
├── templates/
├── fields.json
└── theme.json
```

<Steps>
  <Step title="Create an empty project">
    * In the terminal, navigate to the directory where you'll be storing your project using the `cd` command.

    ```shell theme={null}
    cd Documents/Dev/serverless-function-project
    ```

    * Run `hs project create` to create a new project.

    ```shell theme={null}
    hs project create
    ```

    * Follow the terminal prompts to create your project. For the template, select **Create an empty project (no template)**.

    After following the prompts, the project will be created with the following structure.

    ```shell theme={null}
    projectName/
    ├── hsproject.json
    └── src/
    ```

    Next, you'll begin to build out the rest of the project to incorporate your theme.
  </Step>

  <Step title="Add a theme component">
    The `src/` directory in the project is what contains the project's various components, whether an app, theme, or CMS React module.

    * Create a new `theme` directory in `src`.

    ```shell theme={null}
    projectName/
    ├── hsproject.json
    └── src/
      └── theme/
    ```

    * In the `theme/` directory, create a `theme-hsmeta.json` file with the following content:

    ```json theme={null}
    {
      "uid": "my-cool-theme",
      "type": "theme",
      "config": {
        "themePath": "my-migrated-theme",
        "secretNames": []
      }
    }
    ```

    | Field       | Type   | Description                                                                                                                                                                                                                                            |
    | ----------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `uid`       | String | An internal unique identifier for the theme. Must be globally unique within the project. Can be any string up to 64 characters. Characters can be uppercase or lowercase, and can include numbers, underscores (`_`), dashes (`-`), and periods (`.`). |
    | `type`      | String | The type of component. Must be `theme`.                                                                                                                                                                                                                |
    | `themePath` | String | The path of the directory containing the [theme.json file](/cms/start-building/building-blocks/overview#theme-json) and theme assets.                                                                                                                  |

    <Tip>
      The file name `theme-hsmeta.json` is only for the purposes of this tutorial. You can name the file anything you'd like, as long as it ends in `-hsmeta.json`.
    </Tip>

    * In addition to the `-hsmeta.json` file, create a new directory that you'll be copy/pasting your original theme folder into. You can name this folder anything you'd like, but it will need to match the name set in the `themePath` field of `-hsmeta.json`.

    Your project so far should resemble the following:

    ```shell theme={null}
    projectName/
    ├── hsproject.json
    └── src/
      └── theme/
        ├── theme-hsmeta.json
        └── my-migrated-theme/
    ```
  </Step>
</Steps>

## Convert your theme files

With the skeleton of your project set up, you can now copy/paste your existing theme files into the project, then modify the theme structure to fit the CMS React requirements.

<Steps>
  <Step title="Add your theme files">
    Copy the contents of your theme folder into the `src/theme/my-migrated-theme/` directory. It's recommended to copy/paste rather than move the files so that you have your original as a backup. This should result in a structure similar to the following.

    ```shell theme={null}
    projectName/
    ├── hsproject.json
    └── src/
      └── theme/
        ├── theme-hsmeta.json
        └── my-theme/
          ├── assets/
          ├── modules/
          ├── styles/
          ├── templates/
          ├── fields.json
          └── theme.json
    ```
  </Step>

  <Step title="Rename HubL files and folders">
    To make your theme compatible with the latest version of the developer platform, you'll need to make the following updates to your files and folders:

    * Classic HubL (i.e., non-React) modules must be in a `hubl-modules` directory.
    * HubL module files and templates (including partials) must be renamed to include `.hubl` in the file extension, except for `.json` files.
      * `module.html` becomes `module.hubl.html`
      * `module.css` becomes `module.hubl.css`
      * `module.js` becomes `module.hubl.js`
      * `template.html` becomes `template.hubl.html`
      * `partial.html` becomes `partial.hubl.html`

    ```shell highlight={8-11, 15, 17-18} theme={null}
    projectName/
    ├── hsproject.json
    └── src/
      └── theme/
        ├── theme-hsmeta.json
        └── my-theme/
          ├── assets/
          ├── hubl-modules/
            ├── pricing-card.module
              ├── pricing-card.hubl.html
              ├── pricing-card.hubl.css
              ├── fields.json
              └── meta.json
          ├── styles/
            └── main.hubl.css
          ├── templates/
            ├── home.hubl.html
            └── about.hubl.html
          ├── fields.json
          └── theme.json
    ```

    Because you're renaming these files, you'll also need to update any references in your code to match the new extensions. For example, if one of the theme's stylesheets includes another, you would need to update the path to use `hubl.css`:

    ```css theme={null}
    {% include './objects/_layout.css' %}  /* [!code --] */
    {% include './objects/_layout.hubl.css' %} /* [!code ++] */
    ```

    <Warning>
      **Please note:**

      Keep in mind that these renamed files will look and function the same but will exist as new assets in your account. When swapping a page to a new `.hubl.html` template, existing page content will not be impacted (i.e., live website content will stay the same). However, if you want to update that content in the editor, you'll need to manually rebuild it by adding the new module to the page and recreating the content.
    </Warning>
  </Step>

  <Step title="Add a package.json file">
    In the directory that contains your `theme.json` file, add a `package.json` file to include the required dependencies: `@hubspot/cms-components` and `@hubspot/cms-dev-server`. You can use the example code below to get started:

    ```json theme={null}
    {
      "name": "cms-react-theme",
      "version": "1.0.0",
      "description": "CMS React theme",
      "scripts": {
        "start": "hs-cms-dev-server .",
        "deploy": "hs project upload"
      },
      "type": "module",
      "keywords": [],
      "dependencies": {
        "@hubspot/cms-components": "latest",
        "react": "^18"
      },
      "devDependencies": {
        "@hubspot/cms-dev-server": "latest"
      }
    }
    ```

    With the file added, install the dependencies by navigating into the directory via the terminal, then running `npm install`.
  </Step>

  <Step title="Deploy your project to HubSpot">
    With these changes in place, you can upload the theme to your account by running `hs project upload`. This command will build and deploy both your HubL and React assets, so you'll no longer need to use `hs upload`.

    If you would like to watch for changes (i.e., upload on save), you can use the project-specific watch command: `hs project watch`. However, this is less necessary when working with CMS React because you can run the local development server to view your local changes in real-time without deploying.
  </Step>
</Steps>

## Running local development

With your theme recreated on the developer platform, you can preview your theme assets (modules and templates) locally using the CMS local development server.

To start the local development server:

* In your terminal, ensure you're in the directory that contains your `theme.json` file.
* Run `npm run start`.
* Open [http://localhost:3000](http://localhost:3000) in your browser to view the local development server dashboard.

On the page, you should see your theme's HubL modules and templates, along with high-level information about them, such as template type.

* To view more information about a module, click the **module name**, then view its details in the right sidebar.
* To view the local preview of a module or template, click **View local version** in the *Actions* column.

<Frame>
  <img src="https://developers.hubspot.com/hubfs/Knowledge_Base_2023-24-25/developer/cms-dev-server-hubl-modules.png" alt="Screenshot showing the CMS local development server dashboard" />
</Frame>

While viewing the local version of a module or template, local changes that you save will automatically appear in the browser without needing to refresh.

<Warning>
  **Please note:**

  The local development server will not pick up on changes made to `.json` configuration files. To view changes to those files during local development, you'll need to upload them to your account first by running `hs project upload`.
</Warning>

<Frame>
  <img src="https://developers.hubspot.com/hubfs/Knowledge_Base_2023-24-25/developer/cms-local-dev-server-example.gif" alt="Screen capture video showing an example of modifying a module's local CSS and HTML files and viewing the changes in the browser" />
</Frame>

As you iterate, you can send your changes to your HubSpot account with `hs project upload` as needed.

<Warning>
  **Please note:**

  CMS assets built using projects will not be editable in the design manager. Instead, you'll continue managing and building locally using [hs project CLI commands](/developer-tooling/local-development/hubspot-cli/project-commands).
</Warning>

## Next Steps

Continue exploring HubSpot's developer platform by checking out some of the following resources:

* [Build CMS React modules](/cms/start-building/introduction/react-plus-hubl/modules)
* [Learn more about local development](/cms/reference/react/local-development)
* [Create Islands for client-side interactivity](/cms/reference/react/islands)
