Skip to main content
ButterCMS also offers built-in migration options: the Migrations tool (Enterprise) for migrating content schemas, cloning environments, and moving content across sites or environments, and the Write API for programmatic content creation and updates.

Third-party migration tools

CMS2CMS

CMS2CMS offers automated migration between CMS platforms:
  • Automated content migration
  • Supports many source platforms
  • Handles media migration
  • Preserves SEO settings

Custom migration scripts

For full control, build custom migration scripts:

Node.js migration template

// migrate.js
const fs = require('fs');
require('dotenv').config();

const BUTTERCMS_API_URL = 'https://api.buttercms.com/v2';
const BUTTERCMS_WRITE_TOKEN = process.env.BUTTERCMS_WRITE_TOKEN;

class Migrator {
  constructor() {
    this.results = { success: [], errors: [] };
  }

  async createPage(pageData) {
    const response = await fetch(`${BUTTERCMS_API_URL}/pages/`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Token ${BUTTERCMS_WRITE_TOKEN}`
      },
      body: JSON.stringify(pageData)
    });

    if (response.ok) {
      this.results.success.push(pageData.slug);
      return await response.json();
    } else {
      const error = await response.text();
      this.results.errors.push({ slug: pageData.slug, error });
      return null;
    }
  }

  async migrateFromFile(filePath) {
    const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));

    for (const page of data.pages) {
      console.log(`Migrating: ${page.title}`);
      await this.createPage(page);
      await this.delay(200); // Rate limiting
    }

    return this.results;
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const migrator = new Migrator();
migrator.migrateFromFile('content.json')
  .then(results => {
    console.log('Success:', results.success.length);
    console.log('Errors:', results.errors.length);
  });

Python migration template

# migrate.py
import json
import time
import requests
from dotenv import load_dotenv
import os

load_dotenv()

BUTTERCMS_API_URL = 'https://api.buttercms.com/v2'
BUTTERCMS_WRITE_TOKEN = os.getenv('BUTTERCMS_WRITE_TOKEN')

class Migrator:
    def __init__(self):
        self.results = {'success': [], 'errors': []}
        self.headers = {
            'Authorization': f'Token {BUTTERCMS_WRITE_TOKEN}',
            'Content-Type': 'application/json'
        }

    def create_page(self, page_data):
        response = requests.post(
            f'{BUTTERCMS_API_URL}/pages/',
            json=page_data,
            headers=self.headers
        )

        if response.status_code in [200, 201, 202]:
            self.results['success'].append(page_data['slug'])
            return response.json()
        else:
            self.results['errors'].append({
                'slug': page_data['slug'],
                'error': response.text
            })
            return None

    def migrate_from_file(self, file_path):
        with open(file_path, 'r') as f:
            data = json.load(f)

        for page in data.get('pages', []):
            print(f"Migrating: {page.get('title')}")
            self.create_page(page)
            time.sleep(0.2)  # Rate limiting

        return self.results

# Usage
if __name__ == '__main__':
    migrator = Migrator()
    results = migrator.migrate_from_file('content.json')
    print(f"Success: {len(results['success'])}")
    print(f"Errors: {len(results['errors'])}")

Validation tools

JSON schema validation

const Ajv = require('ajv');
const ajv = new Ajv();

// Define schema for ButterCMS page
const pageSchema = {
  type: 'object',
  required: ['page_type', 'title', 'slug', 'fields'],
  properties: {
    page_type: { type: 'string', pattern: '^[a-z_]+$' },
    title: { type: 'string', minLength: 1 },
    slug: { type: 'string', pattern: '^[a-z0-9-]+$' },
    status: { enum: ['draft', 'published'] },
    fields: { type: 'object' }
  }
};

const validate = ajv.compile(pageSchema);

// Validate before import
function validatePages(pages) {
  const errors = [];
  for (const page of pages) {
    if (!validate(page)) {
      errors.push({
        page: page.title,
        errors: validate.errors
      });
    }
  }
  return errors;
}

Content diff tool

// Compare source and migrated content
async function diffContent(sourcePages, butterPages) {
  const differences = [];

  for (const source of sourcePages) {
    const butter = butterPages.find(p => p.slug === source.slug);

    if (!butter) {
      differences.push({
        slug: source.slug,
        issue: 'Missing in ButterCMS'
      });
      continue;
    }

    // Compare key fields
    if (source.title !== butter.fields.title) {
      differences.push({
        slug: source.slug,
        field: 'title',
        source: source.title,
        butter: butter.fields.title
      });
    }

    // Add more field comparisons...
  }

  return differences;
}

Migration workflow automation

GitHub Actions

# .github/workflows/migrate.yml
name: Content Migration

on:
  workflow_dispatch:
    inputs:
      source_file:
        description: 'Source data file'
        required: true
        default: 'content.json'

jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm install

      - name: Run migration
        env:
          BUTTERCMS_WRITE_TOKEN: ${{ secrets.BUTTERCMS_WRITE_TOKEN }}
        run: node migrate.js ${{ github.event.inputs.source_file }}

      - name: Upload results
        uses: actions/upload-artifact@v3
        with:
          name: migration-results
          path: migration_results.json

ButterCMS support services

Assisted migration

ButterCMS offers assisted migration services:
ServiceAvailabilityContact
WordPress blog importAll planssupport@buttercms.com
Full site migrationEnterprisesupport@buttercms.com
Custom migration supportEnterprisesupport@buttercms.com
Write API enablementOn requestsupport@buttercms.com

Getting help