---
url: 'https://dxpr.com/hc/documentation/learn-dxpr-builder/getting-started/migration-1x-to-3x'
title: 'Migrating from DXPR Builder 1.x or 2.x | DXPR'
author:
  name: Jurriaan
  url: 'https://dxpr.com/users/jurriaan'
date: '2023-11-06T09:44:46+00:00'
updated: '2026-10-23T14:31:17+00:00'
copyright: 'Copyright DXPR. All rights reserved.'
type: article
summary: 'Update in place; Composer swaps the code and `drush updatedb` converts the content'
tags:
  - 'Move from another builder'
image: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
published: true
og:
  site_name: DXPR
  updated_time: '2026-10-23T14:31:17+0000'
  'image:alt': 'DXPR, powered by Drupal: AI-powered Drupal for marketers.'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      mainEntity: {  }
    -
      '@type': TechArticle
      headline: 'Migrating from DXPR Builder 1.x or 2.x'
      description: 'Update in place; Composer swaps the code and `drush updatedb` converts the content'
      image:
        '@type': ImageObject
        url: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
        width: '1200'
        height: '630'
      datePublished: '2023-11-06T09:44:46+0000'
      dateModified: '2026-10-23T14:31:17+0000'
      author:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      mainEntityOfPage: 'https://dxpr.com/hc/documentation/learn-dxpr-builder/getting-started/migration-1x-to-3x'
      articleSection: 'Move from another builder'
    -
      '@type': WebPage
      '@id': 'https://dxpr.com/hc/documentation/learn-dxpr-builder/getting-started/migration-1x-to-3x'
      description: 'Update in place; Composer swaps the code and `drush updatedb` converts the content'
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://dxpr.com/'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
      inLanguage: en
---
[Help Center](/hc)/[Documentation](/hc/documentation) /[Learn DXPR Builder](/hc/documentation/learn-dxpr-builder) /[Start here](/hc/documentation/learn-dxpr-builder/start-here) /[Move from another builder](/hc/documentation/learn-dxpr-builder/migration) # Migrating from DXPR Builder 1.x or 2.x.

Update in place; Composer swaps the code and &#96;drush updatedb&#96; converts the content

 Learn DXPR BuilderStart hereMove from another builder

   ## In this guide

 Related guides

- [Updating](/hc/documentation/learn-dxpr-builder/getting-started/updating)
- [Changelog](/hc/documentation/learn-dxpr-builder/getting-started/changelog)
- [Configuration reference](/hc/documentation/learn-dxpr-builder/reference/config-reference)

DXPR Builder 3.x updates in place from any 1.x or 2.x release. Composer swaps the code, and `drush updatedb` runs the update hooks in `dxpr_builder.install` that convert configuration and content. This page lists what those hooks do, what changed for custom code, and how to verify the result. Release dates come from git tags; see [Older releases](/hc/documentation/learn-dxpr-builder/getting-started/changelog-older).

## Version history in brief

| Series | Drupal | Notes |
|---|---|---|
| 7.x-1.x | Drupal 7 | Sold as Glazed Builder, later renamed. |
| 1.x (8.x-1.x) | Drupal 8 and 9 | Module machine name `dxpr_builder` from the first 1.x release in May 2020. Last release 1.8.8. |
| 2.x | Drupal 9.3 to 11 | CKEditor 5, Key module support, first AI features. Last release 2.8.1. |
| 3.x | Drupal 10.2 and 11 | Bootstrap 5 only, Key module required, content migrations, AI page and image generation. |

The machine name did not change between 1.x and 3.x. Content still carrying Glazed-era markup must be migrated on 1.x or 2.x before upgrading; 3.x no longer rewrites the Glazed name (see below).

## Requirements before you start

- Drupal 10.2 or later, or Drupal 11 (`core_version_requirement` in `dxpr_builder.info.yml`).
- The Key module. It is a hard dependency in 3.x; `dxpr_builder_update_9020()` installs it if `drush updatedb` finds it missing.
- A product key issued for DXPR Builder 2.0.0 or later. Keys without a `dxpr_tier` claim are rejected by the settings form.
- A theme that provides Bootstrap 5, or the **Bootstrap 5** sideload option. Bootstrap 3 and 4 sideloading no longer exist.

## Migration steps

1. Back up the database and files:

    ```bash
    drush sql:dump --result-file=backup.sql

    ```
2. Update the code with Composer. 3.x is currently published as pre-releases, so allow them:

    ```bash
    composer require 'drupal/dxpr_builder:^3.0@beta' --with-all-dependencies

    ```
3. Run the update hooks and rebuild caches:

    ```bash
    drush updatedb
    drush cache:rebuild

    ```

    Several 3.x hooks process every DXPR Builder field value in batches (see below). On large sites they take minutes, not seconds.
4. Open `/admin/dxpr_studio/dxpr_builder/settings`and check the **License** section. After update 9020 the **Storage method** is **Key module**and the **Key** is `DXPR Builder JWT`(`dxpr_builder_jwt`).
5. Check **Sideload Bootstrap files** on the same page. Sites that had Bootstrap 3 or 4 selected are now on **Bootstrap 5**.
6. Open `/admin/dxpr_studio/dxpr_builder/ai_settings`and decide whether the three AI toggles, which default to on, should stay on.
7. Visit pages that use DXPR Builder and confirm they render and edit correctly.

## What the update hooks do

Hooks numbered 8005 to 8025 shipped in 1.x. A 1.x site runs everything from 8026 onwards; a 2.8.0 or 2.8.1 site runs 8040 and 9014 onwards. The function names are `dxpr_builder_update_NNNN()`.

### Added in 2.x (run when coming from 1.x)

| Hook | What it does |
|---|---|
| 8026 | Updates the central DXPR Builder user storage. |
| 8027 | Adds the licence info block and a "DXPR Builder User" column to the People view. |
| 8028 | Creates the `dxpr_lock` table for content locking. |
| 8029 | Adds the licences block to the user licences dashboard. |
| 8030 | Switches the Bootstrap setting after the "Bootstrap 3 Light" option was removed. |
| 8031 | Enables the licence info block where it was installed disabled. |
| 8032 | Removes blocked users from licence storage. |
| 8033 | Initialises `drm_last_contact`. |
| 8034 | Installs the `dxpr_user_is_disavowed` user field and the avow/disavow user actions. |
| 8035 | Initialises the `hide_reminders` setting. |
| 8036 | Migrates CKEditor 4 toolbar button names in profiles to CKEditor 5. |
| 8037 | Adds a default image style for fast-loading images. |
| 8038 | Clears caches to register the Key module integration services. |
| 8039 | Repairs image styles with incomplete `image_scale_and_crop` settings. |
| 9007 | Creates the `ai_tone_of_voice` and `ai_agent_commands` vocabularies with default terms. |
| 9008 | Sets `ai_enabled` to true and removes the old `ai_page_enabled` key. |
| 9009 | Moves `drm_last_contact` from configuration to state. |
| 9010 | Clears caches. |
| 9011 | Enables the AI Assistant and AI Tone of Voice buttons in every profile. |
| 9012 | Restores `ai_page_enabled` with default true. |
| 9013 | Sets the AI output filtering defaults (`ai_output_allowed_domains`). |
| 9015 | Adds `ai_image_enabled` with default true. |

### Added in 3.x (run when coming from 1.x or 2.x)

| Hook | What it does |
|---|---|
| 8040 | Normalises `bootstrap` to `bs5`; the `1` (Bootstrap 3) and `bs4` values are rewritten. |
| 9014 | Batch: converts Owl Carousel markup in content to the Bootstrap carousel (`src/Migration/OwlCarouselMigration.php`). |
| 9016 | Adds `ai_user_model_selection` with default true. |
| 9017 | Batch: converts circliful circle counters to Bootstrap progress markup (`CircleCounterMigration.php`). |
| 9018 | Batch: converts legacy progress bar markup to the Bootstrap progress structure (`ProgressBarMigration.php`). |
| 9020 | Installs the Key module, moves `json_web_token` into the Key entity `dxpr_builder_jwt`, sets `api_key_storage` to `key` and clears the clear-text value. |
| 9021 | Backfills the `type` property of user templates from their markup. |
| 9022 | Batch: adds `data-entity-type` and `data-entity-uuid` to internal `/node/N` links (`EntityLinkMigration.php`). |
| 9023 | Batch: repairs text format, summary and deleted deltas that update 9022 lost on `text_with_summary` fields. |
| 9024 | Batch: enriches aliased internal links the same way as 9022 (`AliasLinkMigration.php`). |
| 9025 | Clears `tone_of_voice_vocabulary` when it points at a vocabulary that no longer exists. |
| 9026 | Clears a clear-text `json_web_token` left in the settings when the key lives in a Key entity. |

There is no update 9019.

### Content migrations

3.x runs content migrations in batch only; there is no render-time conversion any more. The migration status page (`/admin/dxpr_studio/dxpr_builder/migration-status`) and the status report list pending content. The update hooks above migrate it, and so do the **Run now** and **Run all pending migrations** actions on that page. Migrations are services tagged `dxpr_builder.content_migration`(`dxpr_builder.services.yml`). A batch that records failures is not marked complete; the failed items are logged and stay pending.

The `glazed_to_dxpr` string rewrite that 1.x and 2.x applied at render time has been removed. The Glazed name was dropped with 1.0.0 in May 2020 and all Glazed and Carbide era content is assumed to have been migrated by those releases. The rewrite was a plain string replacement. On sites whose content merely mentions Glazed (support articles, documentation links), it would have rewritten prose and broken links instead of migrating markup. Sites that still hold Glazed class names in stored content should run the 2.x release first.

## Changes for custom code

### Field formatter

The field formatter id is `dxpr_builder_text`(label "DXPR Builder", `src/Plugin/Field/FieldFormatter/DxprBuilderFormatter.php`), unchanged since 1.x. It has one setting, `profile`, which is empty for the role-based default or a profile id. Check that every builder field still uses this formatter on its view display; update 9023's repair is limited to fields that do.

### Hooks

`dxpr_builder.api.php` documents the 3.x hooks. Rename the Glazed Builder ones as follows:

| Glazed Builder hook | DXPR Builder 3.x hook |
|---|---|
| `hook_glazed_builder_classes()` | `hook_dxpr_builder_classes_alter(array &$dxpr_builder_classes)` |
| `hook_glazed_builder_buttons_folders()` | `hook_dxpr_builder_element_buttons_folders_alter(array &$dxpr_element_buttons_folders)` |
| `hook_glazed_builder_elements_folders()` | Removed; no replacement hook. |
| none | `hook_dxpr_builder_icon_sets_alter(array &$icon_sets)`, new. Icon sets are declared in `MODULE.dxpr_icon_sets.yml` files. |

### CSS and utility classes

Custom CSS that targets Glazed class names must use the DXPR names, such as `dxpr-theme-util`, `panel-dxpr` and `dxpr-builder`. Utility classes exposed in the editor are provided through `hook_dxpr_builder_classes_alter()`.

### Configuration and deployment

- Remove `json_web_token` from any committed configuration; after update 9020 the key lives in the `dxpr_builder_jwt` Key entity. That Key uses the **Configuration** provider, so the key is still exported as `key.key.dxpr_builder_jwt`. Switch it to the **File** or **Environment**provider at `/admin/config/system/keys` to keep it out of exports.
- Configuration exports now include the two AI vocabularies and their terms.
- Profiles export CKEditor 5 button names in `inline_buttons` and `modal_buttons`.

## Troubleshooting

If content does not display correctly after the update:

1. Run `drush cache:rebuild`.
2. Check `/admin/reports/dblog` for messages from the `dxpr_builder` channel; batch migrations log the items they skip.
3. Confirm the view display of each builder field still uses the **DXPR Builder** formatter.
4. Confirm the theme loads Bootstrap 5, or enable sideloading at `/admin/dxpr_studio/dxpr_builder/settings`.

## What's next?

- [Updating](/hc/documentation/learn-dxpr-builder/getting-started/updating): routine updates within a series
- [Changelog](/hc/documentation/learn-dxpr-builder/getting-started/changelog): what each release changed
- [Configuration reference](/hc/documentation/learn-dxpr-builder/reference/config-reference): every key the update hooks touch