How We Migrated from SharePoint to DA for Edge Delivery Services

Adobe's Document Authoring (DA) tool is quickly becoming the preferred content management solution for Edge Delivery Services sites. Unlike SharePoint or Google Docs, DA provides native visual editing, seamless AEMaaCS integration, and authoring tools built specifically for modern web experiences.

When I showed our client the difference, their response was immediate: "we need this."

Fast forward a bit, I had the honor of being invited to speak on Adobe's Discord Thursday Frequency about how we migrated their Edge Delivery Services site from SharePoint-based authoring to DA.

Joined by my colleague Sean McAuliffe, we discussed with Adobe's Chris Millar on why to consider a migration to DA and how to approach it if your Edge Delivery site's content is currently managed in SharePoint or Google Docs.

The full recording covers our migration strategy, common pitfalls we encountered, and answers to community questions. Watch below!

Migrating from SharePoint to DA

Below is the outline that we covered during the session, with examples and documentation links.

Assess migration scope

Content inventory and testing plan

Use the Helix Admin Status API to give us the list of previewed and published content currently in SharePoint.

You also need to understand how much regression testing is needed — a DA migration is mostly QA effort than it is dev effort.

Review the upgrade documentation

Start by reading the DA Upgrade docs at https://docs.da.live/developers/guides/upgrading.

Then, decide your upgrade strategy (FStab swap vs. Origin swap) based on the pros and cons listed within https://docs.da.live/administrators/guides/upgrade-site. We chose the Origin swap  approach, the rest of the steps in this guide assume that approach but is largely still applicable even if you choose the FStab swap.

Perform an initial setup and content import

Do an initial site set up and content import into the new DA site, followed by a bulk preview, so that you can quickly identify any issues that need to be fixed.

Initial setup tasks

First, create the DA org and site folders in https://da.live/.

Then, create the new Edge Delivery site with modified site config. To do this, get your existing SharePoint config from the Admin API via GET https://admin.hlx.page/config/{org}/sites/{sharepoint-site}.json.

Then, use that as input to define the config of your new DA site via PUT https://admin.hlx.page/config/{org}/sites/{da-site}.json. Make sure you swap the content source URL with your new DA content URL.

Below is a before and after of what your site config might look like:

SharePoint config

{
  "version": 1,
  "code": {
      "owner": "aemsites",
      "repo": "my-repo",
      "source": {
          "type": "github",
          "url": "https://github.com/..."
      }
  },
  "content": {
      "source": {
          "url": "https://adobe.sharepoint.com/...",
          "type": "onedrive"
      },
      "contentBusId": "xyz"
  },
  "metadata": {
    ...
  },
  "cdn": {
      ...
  },
  "access": {
      ...
  },
  "sidekick": {
      "plugins": [...]
  }
}

DA config

{
    "version": 1,
    "code": {
        "owner": "aemsites",
        "repo": "my-repo",
        "source": {
            "type": "github",
            "url": "https://github.com/..."
        }
    },
    "content": {
        "source": {
            "url": "https://content.da.live/...",
            "type": "markup"
        }
    },
    "metadata": {
        ...
    },
    "cdn": {
        ...
    },
    "access": { ... },
    "sidekick": {
        "editUrlLabel": "Document Authoring",
        "editUrlPattern":
"https://da.live/edit#/your-org/your-site{{pathname}}",
        "plugins": [...]
    }
}

Then, configure DA Authentication on your organization: https://docs.da.live/administrators/guides/permissions

Initial content import

We need to get an inventory of all content that needs to be imported. Use the Status API which is documented with examples at https://docs.da.live/administrators/guides/restore-from-aem.

Once you have this list of pages from SharePoint, you should filter out any unneeded paths such as unused /drafts content.

You should also consider pages that exist but are not meant to be published live yet. For example, content authors may be actively working on a draft page in SharePoint as you are performing the DA migration.

To account for this, you can first get all items from "edit / preview" state (e.g. "select": ["preview", "edit"]). You would only want to import & preview these, but do not publish live.

Status API Example:

curl  -X POST \
  'https://admin.hlx.page/status/geometrixx/outdoors/main/index' \
  --header 'Accept: */*' \
  --header 'X-Auth-Token: {{YOUR_AEM_ADMIN_API_TOKEN}}' \
  --header 'Accept-Encoding: gzip' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "pathsOnly": true,
    "select": ["preview", "edit"],
    "paths": [
      "/*"
    ]
}

Then, call the Status API again to get all items with a "live" status (e.g. "select": ["live"]). These are the paths that you can confidently publish live in DA since they have already been published live in your SharePoint-based site.

Status API Example:

curl  -X POST \
  'https://admin.hlx.page/status/geometrixx/outdoors/main/index' \
  --header 'Accept: */*' \
  --header 'X-Auth-Token: {{YOUR_AEM_ADMIN_API_TOKEN}}' \
  --header 'Accept-Encoding: gzip' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "pathsOnly": true,
    "select": ["live"],
    "paths": [
      "/*"
    ]
}

Once you have your list of URLs to import from your SharePoint-based site, use DA's bulk importer app at https://da.live/apps/import.

Then, bulk preview and publish content using DA's bulk operations tool at https://da.live/apps/bulk.

Now that our site is previewed in the new DA origin, we can perform our QA regression testing to identify any broken features which defines our list of development tasks to resolve.

Dev considerations

Branching Strategy Decision

Before making any code changes, you need to decide how you want manage that code in Github.

We considered whether to push backward-compatible changes directly to main or to manage breaking changes in a dedicated feature branch. Ultimately, we opted for the feature branch approach and temporarily pointed our CDN to that branch during the go-live cutover (more on this below).

Local development

The --url option for the aem up command came in handy. With this, you can point to different content sources in case you need to switch between SharePoint and DA for testing any changes.

aem up --url https://main--sharepoint-site--org.aem.page
aem up --url https://main--da-site--org.aem.page

Block updates due to HTML differences

There were some minor places where moving to DA "broke the contract" between the markup and our blocks.

1. Nested lists (most common in headers and footers).

DA & AEM's XWalk delivery will wrap the contents of list items in p elements. This is better but required adjustment.

DA HTML example

DA HTML

SharePoint HTML example

SharePoint HTML

2. Table rendering differences (less common).

SharePoint sends a thead and tbody where DA just sends one tbody element. This was a nested block situation, which is an edge-case, since doing this is not typically supported or recommended in Edge Delivery Services.

Example of nested block in Edge Delivery Services. Don't do it!

Nested block. Not a recommended authoring pattern.

DA HTML example

DA HTML

SharePoint HTML example

SharePoint HTML

Solutions

The solutions were quick and mostly involved updating the existing block code to identify elements differently. We chose to simply support DA only (breaking changes) and not try to support both DA and SharePoint.

Example code change in our blocks to fix the nested lists HTML differences:

Before

JS code example

After

JS code example

Sheet differences between DA & SharePoint

Query Index: We had to define new query indexes since Excel functions were previously used to create partitions in the query-index spreadsheet, but this is not possible with DA since there is no physical spreadsheet to manipulate the index.

We moved from having a single query-index.json endpoint that uses the sheet parameter, to defining multiple indexes with unique endpoints e.g. blogs-index.json, press-releases-index.json, etc.

We simply updated a utility function in scripts.js and passed the new argument when calling this function:

Before

JS code example

After

JS code example

Sorting: Excel functions were previously used to pre-sort the query-index before publishing to Edge Delivery. We had to move this sorting logic client-side while also considering query-index size, using browser caching for larger sizes. Perhaps query-index sorting via Edge Delivery will be possible in the future.

Data types: Field data types are strongly typed in DA whereas SharePoint delivered some fields in a string format regardless of its underlying data type, e.g. arrays.

Other config tasks

AEM Assets integration: If you have an AEM Cloud license, and especially if you already had the AEM Assets plugin configured in Sidekick for your SharePoint site, you can easily configure the integration for DA described in https://docs.da.live/administrators/guides/setup-aem-assets.

Block & Template Library:  Configuring the Blocks and Templates library in DA is easy and does not require any development effort, allowing authors to further build it out as they see fit, see https://docs.da.live/administrators/guides/setup-library.

Enable Universal Editor: DA supports both doc-based authoring and WYSIWYG authoring for the same site and even the same page based on your preferences. See https://docs.da.live/administrators/guides/setup-universal-editor

Note that instrumenting all blocks for UE is not critical path to launch, and it requires more development work. I'd recommend launching with doc-based authoring first before spending the extra effort of supporting the UE for all blocks.

Go-live

Cutover options

We saw 2 ways to approach the cutover:

  1. Keep all changes backward/forward compatible with SharePoint and continuously merge each code change into main. This provides a quicker cutover process since you only need to update your CDN to reference the new DA origin URL (assuming Origin swap approach is used). However, the need for dual compatibility increases dev  and QA complexity.
  2. Keep all changes in a dedicated branch, continuously synced with main, temporarily point to that branch during cutover. We used this approach.

Go-live readiness tasks

These are assuming the  Origin swap approach was chosen:

  1. Configure CDN to point to new Edge Delivery origin:  If you have multiple CDN environments mapped to your custom domain, e.g. dev.example.com, stage.example.com, you can configure CDN to point to your DA origin URL and perform UAT via the stage URL.
  2. Site regression testing: As with any go-live plan, ensure site regression testing and UAT has been successfully completed and signed off on.
  3. Configure CDN push invalidation on new site:  You can do this for your lower environments first if you have lower CDN environments/domains. Then, ensure it is configured for your production URL as you near the go-live cutover date. We did this about 2 or 3 days prior to go-live just to validate that push invalidation works smoothly in prod prior to launch.

Cutover plan (day of go-live):

This is almost literally what our cutover plan on the day of go-live looked like, using the notion of a dedicated da development branch that we kept separate from main throughout the project.

  1. Keep everything in the da branch, ensure it has the latest from main branch, all conflicts resolved.

  2. On day of go-live, Deploy a Prod CDN config that is pointing to the da branch instead of main, i.e. https://da--da-site--org.aem.live/.

  3. The site is now live in prod on DA (we're not done yet!).

  4. In Github, merge da branch into main, DO NOT DELETE da BRANCH YET.

    • This branch is serving the code to your production site, thus prematurely deleting this branch will cause issues.
  5. Smoke test the main DA origin (https://main--da-site--org.aem.live/).

  6. Update the CDN configs to route requests to https://main--da-site--org.aem.live/ for all DA paths.

  7. Site is still live on DA, referencing the main branch for all origins, we can now safely delete the da branch.

  8. Done!

The rollback plan was even simpler: just point the CDN back to the original SharePoint-based Edge Delivery URL in the event of any unforeseen issues during cutover. The above cutover plan should help mitigate that from happening with zero downtime.

Project timeline

This entire migration project took us about 1 to 2 weeks of planning and about 2 to 3 weeks of execution, inclusive of  content import, development changes, QA regression testing, and client UAT.

The small investment to move to DA pays significant dividends to your team. Especially since using this tool comes at no additional license cost on top of your existing AEM license.

Conclusion

Upgrading your Edge Delivery Services site from SharePoint-based authoring to DA is not a technically complex task but it does require planning and coordination. This post represented our personal experience based on the specific technology stack and requirements we were working with, but hopefully a lot of this is reusable and relevant for anyone else considering a DA migration.

In our experience, Adobe provides excellent support through Slack/Discord as well as thorough documentation linked below. Feel free to also contact me if you need any tips or have questions.

Most importantly, our client was thrilled to be able to use the new tool so quickly and enhance their content authoring workflows. Additional training was hardly necessary since they were already familiar with concepts of document-based authoring, and we walked them through the newer features such as Live Preview, Universal Editor, Block Library, and more.