Hygraph
Docs

#Migrate to Hygraph

Migrating to Hygraph involves two distinct phases: rebuilding your schema, then importing your content. Hygraph gives you the Management SDK and Content API to handle both programmatically, as well as a UI-based option for schema creation.

This guide covers the full migration flow, from exploring your existing data to importing content, along with tips for specific field types such as assets, rich text, and relations.

#Prerequisites

  • An active Hygraph project
  • A Permanent Auth Token with Management API access (for schema creation via the SDK)
  • A Permanent Auth Token with Content API mutations enabled (for content import)
  • An export of your existing content in JSON or CSV format

#Step 1: Explore your current data

Before creating anything in Hygraph, examine the structure of your existing project and map it to Hygraph's data model.

Plan your schemaPlan your schema

Work through the following questions:

  • What models and fields do you currently have, and how do they map to Hygraph's field types?
  • How do your models relate to each other?
  • Are there structures you want to normalize or improve as part of the migration?
  • Which data belongs in Hygraph, and which belongs elsewhere? For example, you may want image assets in Hygraph but video assets in a dedicated streaming service.

Export your existing content to JSON or CSV so you can inspect field names, content types, and relations.

The examples in this guide use the following CSV of authors:

oldId,firstName,lastName
1,Stephen,King
2,Frank,Herbert
3,Brian,Herbert
4,Kevin,Anderson
5,Agatha,Christie
6,Haruki,Murakami
7,Isaac,Asimov

Hygraph supports over a dozen field types, from strings, booleans, and dates to polymorphic union types and remote field resolvers. You get a small set of system fields out of the box, but everything else is defined by you.

#Step 2: Create your schema

Create your schemaCreate your schema

Create your schema before importing any content. You have two options: the Management SDK or the Hygraph UI. The SDK is faster for large or complex schemas and gives you a repeatable record of what was created.

#Use the Management SDK

The Management SDK lets you create models, fields, enumerations, components, and remote sources programmatically. All changes are submitted as a single transaction. If any operation fails, the entire batch rolls back automatically.

Install the SDK:

npm install @hygraph/management-sdk

Initialize the client:

const { Client } = require('@hygraph/management-sdk');
// endpoint is your High Performance Content API URL
// found in Project Settings > Endpoints > High Performance Content API
const client = new Client({
authToken,
endpoint,
name, // optional
});

Use createModel to create a model:

client.createModel({
apiId: '<your_api_id>',
apiIdPlural: '<your_api_id_plural>',
description: '<your_model_description>',
displayName: '<Your model name>',
});

To create two models, Author and Book:

client.createModel({
apiId: 'Author',
apiIdPlural: 'Authors',
displayName: 'Author',
});
client.createModel({
apiId: 'Book',
apiIdPlural: 'Books',
displayName: 'Book',
});

Use createSimpleField to add fields to a model. The example below shows all available options. Use only the ones you need:

client.createSimpleField({
apiId: '<your_api_id>',
description: '<your_description>',
displayName: '<your_display_name>',
embeddableModels: '<embeddable_models>',
embedsEnabled: '<boolean>',
formConfig: '<form_config_json>',
formExtension: '<form_extension>',
formRenderer: '<form_renderer>',
isHidden: '<boolean>',
isList: '<boolean>',
isLocalized: '<boolean>',
isRequired: '<boolean>',
isTitle: '<boolean>',
isUnique: '<boolean>',
migrationValue: '<migration_value>',
parentApiId: '<parent_api_id>',
position: '<int>',
tableConfig: '<table_config_json>',
tableExtension: '<table_extension>',
tableRenderer: '<table_renderer>',
type: SimpleFieldType.STRING,
validations: '<SimpleFieldValidationsInput>',
visibility: '<VisibilityTypes>',
});

To add a required string field to the Author model:

client.createSimpleField({
parentApiId: 'Author',
type: SimpleFieldType.STRING,
apiId: 'favoritePastime',
displayName: 'Author Favorite Pastime',
isRequired: true,
visibility: VisibilityTypes.ReadWrite,
});

Full migration example

The script below creates an Author model with firstName and lastName fields:

// migration.js
const { Client, SimpleFieldType } = require('@hygraph/management-sdk');
const client = new Client({
authToken: '<your_permanent_auth_token>',
endpoint: '<your_content_api_endpoint>',
});
// Create the Author model
client.createModel({
apiId: 'Author',
apiIdPlural: 'Authors',
displayName: 'Author',
});
// Add firstName field to Author
client.createSimpleField({
parentApiId: 'Author',
apiId: 'firstName',
displayName: 'First Name',
type: SimpleFieldType.STRING,
});
// Add lastName field to Author
client.createSimpleField({
parentApiId: 'Author',
apiId: 'lastName',
displayName: 'Last Name',
type: SimpleFieldType.STRING,
});
// Preview all changes before committing
const changes = client.dryRun();
console.log(changes);

Run the script from the command line:

node migration.js

Review the changes array to confirm the operations that will be applied. Once you are satisfied, replace dryRun() with run() to commit the changes:

async function runMigration() {
const result = await client.run(true);
if (result.errors) {
throw new Error(result.errors);
}
console.log(result.name);
}
runMigration();

Once the migration runs, verify the result by checking the schema editor in Hygraph or introspecting your endpoint.

If your schema includes components, enumerations, or remote source fields, create those at the schema level before adding them to models. See the Management SDK field creation examples for instructions.

Additional resources:

#Use the UI

To create your schema in the Hygraph UI, navigate to the schema editor and create your models, then add fields to each one. The getting started guide covers creating models and adding fields.

#Step 3: Plan your content migration

With your schema in place, review your existing content and map it to the new structure before importing anything.

Order matters when content is relational. For example, you must create asset entries before creating content entries that reference them, otherwise the relation cannot be established at import time.

As you plan, identify:

  • Which content needs to be migrated first to unblock dependent content
  • Which content is critical vs. supporting, so you can prioritize accordingly
  • Where the shape of your existing data differs from your new input types, and what transformation is needed

#Step 4: Import your content

Import assets before content entries. Relations cannot be established until the assets they reference exist. How you upload assets depends on which asset system your project uses.

API EndpointsAPI Endpoints

#Assets

Projects created after February 2024 use the Hygraph Asset Management system. Projects older than that use the Legacy asset system. The upload process differs between the two:

  • Hygraph Asset Management: Asset uploads are part of the native GraphQL API. Upload through createAsset mutations instead.
  • Legacy asset system: Uses a dedicated HTTP upload endpoint at /upload appended to your project URL.

To check which system your project uses, navigate to Project Settings > Access > Endpoints and look for an asset upload endpoint. If one is listed, your project uses the legacy system. If not, it uses Hygraph Asset Management.

You will need a Permanent Auth Token with Mutations access enabled to upload assets.

Assets follow the same environment and authorization settings as all other content in your project.

After uploading, publish your assets before they can be served alongside published content. For full asset upload documentation, see Uploading assets.

Upload by file — Hygraph Asset Management

First, create the asset via mutation to receive the upload URL and credentials:

Then upload the file using the credentials from the response:

curl --request POST \
--url $URL \
--form X-Amz-Date=$DATE \
--form key=$KEY \
--form X-Amz-Signature=$SIGNATURE \
--form X-Amz-Algorithm=$ALGORITHM \
--form policy=$POLICY \
--form X-Amz-Credential=$CREDENTIAL \
--form X-Amz-Security-Token=$SECURITY_TOKEN \
--form file=@./test.jpg

Upload by remote URL — Hygraph Asset Management

mutation uploadByUrl {
createAsset(
data: {
uploadUrl: "https://images.unsplash.com/photo-1682687218147-9806132dc697"
}
) {
id
url
}
}

Upload by file — legacy asset system

Upload by remote URL — legacy asset system

#Content entries

To find your Content API endpoint, go to Project Settings > Access > Endpoints > High Performance Content API.

Use GraphQL mutations to create content entries. Hygraph auto-generates mutations for every model you create. Because existing data rarely maps 1:1 to your new schema, you will likely need to transform your dataset to match your new input types before importing.

The script below shows a complete import example using the CSV authors file from Step 1:

// Import necessary libraries
const { GraphQLClient, gql } = require('graphql-request');
const csvToJson = require('csvtojson');
require('dotenv').config();
// Initialize GraphQL client
const client = new GraphQLClient(process.env.HYGRAPH_ENDPOINT, {
headers: {
authorization: `Bearer ${process.env.HYGRAPH_TOKEN}`,
},
});
// Build a mutation from a data row
function createMutation(data) {
return gql`
mutation MyMutation {
createAuthor(data: {
firstName: "${data.firstName}",
lastName: "${data.lastName}",
oldId: "${data.oldId}"
}) {
id
}
}
`;
}
// Run the migration
async function run() {
// Load and parse the CSV
const data = await csvToJson().fromFile('./data.csv');
// Build mutations from each row
const mutations = data.map((item) => createMutation(item));
// Execute each mutation with a 1-second delay between requests
mutations.forEach((mutation, index) => {
setTimeout(() => {
console.log(`Running mutation ${index + 1} of ${mutations.length}`);
client.request(mutation).then((response) => {
console.log(response);
});
}, (index + 1) * 1000);
});
}
run();

See rate limits for guidance on request frequency.

#Rich text

Hygraph stores rich text as an Abstract Syntax Tree (AST) based on Slate. If your existing content stores rich text as HTML or another format, you need to convert it before importing.

  1. Convert: Use Hygraph's HTML-to-Slate AST converter to transform your existing rich text into the correct AST format.
  2. Import: Use a create mutation with a RichTextAST variable to import the converted content.

For additional rich text utilities, see the Hygraph rich text helpers.

#Relations

There are two approaches to migrating relational content.

Option 1: Create with nested mutations

Use a create mutation with a nested create to build both sides of a relation in one request. For subsequent entries that share the same related record, use a connect mutation instead of creating a duplicate.

Option 2: Create separately, then connect

Create all entries for each model first using create mutations, then wire them together using update mutations or update many mutations. This approach is more straightforward but requires more total mutations.

#Migration best practices

Follow these guidelines to keep your migration predictable and recoverable:

  • Plan the full migration before you start. Map your existing schema to Hygraph models and fields, and identify any transformations needed.
  • Use the migration as an opportunity to improve your schema. Hygraph features like components can reduce duplication. Restructure where it makes sense.
  • Migrate in dependency order. Assets must exist before content entries that reference them. Shared models must exist before models that connect to them.
  • Prioritize critical content. Identify your most important content and migrate it first, before supporting or supplementary content.
  • Avoid large, complex mutations. If a model connects to many other models, do not try to create and connect everything in a single mutation. Space requests out and stay within rate limits.

#What's next

  • Management SDK: Full reference for creating and updating schema elements programmatically.
  • Content API mutations: Reference for create, update, connect, and nested mutations.
  • Upload assets: Full documentation for asset uploads, including both legacy and current asset systems.
  • Rate limits: Understand request limits before running large-scale imports.
  • Field types: Reference for all field types available in Hygraph.