DEV Community

Cover image for Moving from Wordpress to Builder.io
Yoav Ganbar for Builder.io

Posted on • Originally published at builder.io on

Moving from Wordpress to Builder.io

Written by Gustavo Garcia

Moving content from your existing CMS can be much easier than you think. Already use a CMS like Wordpress? Do you have tools to export your content to a defined structure like JSON or other? If so, you have a pretty easy path to move your content to Builder.

Export your content

This section shows you how to migrate your content to Builder.io.

Export your content on a defined structure you can work with, as an example JSON format. Make sure you have your content well-defined in block structures like this example:

<div style="padding-top: 8px" classname="title">...</div>
Enter fullscreen mode Exit fullscreen mode

This example would be parsed to:

{"tag": "div", "classname": "title", "style": {"padding-top": "8px"}, "children": ...}
Enter fullscreen mode Exit fullscreen mode

Create some custom components in code that translates to your components from your CMS. For example, let's say we have a Hero Component that exists in your current CMS and is exported:

{
   "layout_type":"HERO",
   "props":{
      "id":"",
      "title":"This is my hero title",
      "subtitle":{
         "text":"My hero subtitle with a cool slogan",
         "tag":"h2"
      },
      "media":{
         "type":"image",
         "image":{
            "ID":11029,
            "id":11029,
            "title":"What is the universe?",
            "filename":"sample-file.svg",
            "url":"https://cool-wordpress/wp-includes/images/media/default.svg",
            "alt":"What is the universe?",
            "description":"What is the universe?",
            "caption":"What is the universe?",
            "name":"hero-v1",
            "mime_type":"image/svg+xml",
            "type":"image",
            "subtype":"svg+xml",
            "icon":"https://cool-wordpress/wp-includes/images/media/default.png",
            "width":704,
            "height":528,
            "sizes":{
               "thumbnail":"https://cool-wordpress/wp-includes/images/media/default-v3.svg",
               "thumbnail-width":"150",
               "thumbnail-height":"150",
               "medium":"https://cool-wordpress/wp-includes/images/media/default-v3.svg",
               "medium-width":"300",
               "medium-height":"300"
            }
         }
      },
      "background":"custom",
      "backgroundColor":"#123833",
      "colorModifier":"white",
      "size":"s",
      "hasButton":true,
      "button":{
         "label":"Click here",
         "action":{
            "type":"link",
            "value":"/call-to-action"
         }
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

This would turn into a custom component in your code such as:

import React from 'react'
import MyCustomButton from './components/MyCustomButton'

// defined props like title, subTitle, hasButton, buttonLink
export function Hero({
  title, subTitle, hasButton, buttonLink
  }) {
  return (
    <div>
      <h1>{title || 'Default hero title'}</h1>
      <h3>{subTitle || 'Default hero subtitle'}</h3>
      {
        hasButton && (
          <MyCustomButton link={buttonLink} />
        )
      }
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Register your created custom components in Builder.io so you can use them within the Visual Editor:

import { Builder } from '@builder.io/react';
import { Hero } from './Hero'

Builder.registerComponent(Hero, {
  name: 'Hero',
  inputs: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'subtitle',
      type: 'text',
    },
    {
      name: 'hasButton',
      type: 'boolean',
    },
    {
      name: 'buttonLink',
      type: 'text',
    },
  ],
})
Enter fullscreen mode Exit fullscreen mode

Create your migration script

Now that you have your content exported and your custom components ready, it's time to get that content into Builder.io so you can edit and publish. Below we have written some step-by-step instructions on how to create your migration script.

Your migration script should:

  • Read your content from your exported files (in this example JSON files) looking for blocks and content of interest, which will be now parsed to your custom components:
const contentJson = require('./content.json')

const MODEL_NAME = 'blog-page'

async function main() {
  console.log('starting script...', contentJson.title)
  const blocks = <any>[]

  contentJson?.body?.map((layoutItem: any) => {
    let options: any = {
      category: layoutItem.layout_type,
      title: layoutItem.props.title?.text,
      subtitle: layoutItem.props.subtitle?.text,
    }

    if (layoutItem.layout_type === 'Hero') {
      options = {
        ...options,
        type: layoutItem.props.type,
        image: layoutItem.props.image,
        content: layoutItem.props.content,
        hasButton: layoutItem.props.hasButton,
        button: layoutItem.props.button
      }
    } else if (layoutItem.layout_type === 'Text') {
      // ... if you have a custom component for text blocks
      options = {
        ...options,
        content: layoutItem.props.content,
      }
    } 
    // ... continue to identify your blocks of interest
    }

    // push your components to your blocks array to be rendered on the model layout
    blocks.push({
      "@type": "@builder.io/sdk:Element",
      "@version": 2,
      component: {
        "name": layoutItem.layoutType,
        options,
      }
    })
  })

Enter fullscreen mode Exit fullscreen mode

As in the above example, when you find a block of interest, identify the custom component that best suits that block and add the custom component with its options to the blocks array to be rendered on your model layout — in this case blog-page.

Finally, write your content to Builder.io using the Write API so you can edit and publish from the editor:

async function postData(body: any) {
  const res = await axios({
    method: 'post',
    url: `https://builder.io/api/v1/write/${MODEL_NAME}`,
    headers: {
      'Authorization': 'Your private space key goes here',
      'Content-Type': 'application/json',
    },
    data: body,
  });

  return res;
}

// each time you iterate over a page,
// you can call the write API to create a new entry
// with the blocks identified

const res = await postData(
    {
      name: contentJson.url.replaceAll('/', ''),
      query: [
        {
          "property": "urlPath",
          "operator": "is", // can be `startsWith` to match any urls that starts with value
          "value": contentJson.url // must start with /
        }
      ],
      data: {
        title: contentJson.title,
        url: contentJson.url,
        metaTags: contentJson.metaTags,
        blocks: blocks,
      }
    }
  )
Enter fullscreen mode Exit fullscreen mode

So the final migration script on this example should be like this:

const axios = require('axios');
const contentJson = require('./content.json')

async function postData(body: any) {
  const res = await axios({
    method: 'post',
    url: `https://builder.io/api/v1/write/${MODEL_NAME}`,
    headers: {
      'Authorization': 'Your private space key goes here',
      'Content-Type': 'application/json',
    },
    data: body,
  });

  return res;
}

const MODEL_NAME = 'blog-page'

async function main() {
  console.log('starting...', contentJson.title)
  const blocks = <any>[]

  contentJson?.body?.map((layoutItem: any) => {
    let options: any = {
      category: layoutItem.layout_type,
      title: layoutItem.props.title?.text,
      subtitle: layoutItem.props.subtitle?.text,
    }

    if (layoutItem.layout_type === 'Hero') {
      options = {
        ...options,
        type: layoutItem.props.type,
        image: layoutItem.props.image,
        content: layoutItem.props.content,
        hasButton: layoutItem.props.hasButton,
        button: layoutItem.props.button
      }
    } else if (layoutItem.layout_type === 'Text') {
      // ... if you have a custom component for text blocks
      options = {
        ...options,
        content: layoutItem.props.content,
      }
    } 
    // ... continue to identify your blocks of interest
    }

    // push your components to your blocks array to be rendered on the model layout
    blocks.push({
      "@type": "@builder.io/sdk:Element",
      "@version": 2,
      component: {
        "name": layoutItem.layoutType,
        options,
      }
    })
  })


  const res = await postData(
    {
      name: contentJson.url.replaceAll('/', ''),
      query: [
        {
          "property": "urlPath",
          "operator": "is", // can be `startsWith` to match any urls that starts with value
          "value": contentJson.url // must start with /
        }
      ],
      data: {
        title: contentJson.title,
        url: contentJson.url,
        metaTags: contentJson.metaTags,
        blocks: blocks,
      }
    }
  )
  console.log('new entry added', res.status, res.statusText)
}

main().catch(err => {
  console.log(err)
})
Enter fullscreen mode Exit fullscreen mode

Additional considerations

This article showed how to migrate blog pages exported from Wordpress as JSON format files. Even so, you could use this same process to migrate any content to Builder.io exported from the most famous and used of CMSs on the market.

Conclusion

Migrating content from your existing CMS to Builder.io can be straightforward and fast — just make sure to export your content in a way that you can read it while keeping your components as well-defined as possible. This will help a lot in the migration process. Using these techniques, you can smoothly migrate hundreds or even thousands of pages as many of our customers do!

Visually build with your components

Builder.io is a headless CMS that lets you drag and drop with your components right within your existing site.

Try it out Learn more

// Dynamically render your components
export function MyPage({ json }) {
  return <BuilderComponent content={json} />
}

registerComponents([MyHero, MyProducts])
Enter fullscreen mode Exit fullscreen mode
Read the full post on the Builder.io blog

Top comments (0)