Skip to content

migrations.json: keep existing content

This file describes how saved content moves from one definition version to another. Use it when changing the shape of content that owners have already edited.

A new project starts with []. If version 2 renames hero.title to hero.headline and adds hero.eyebrow, the migration can be:

migrations.json
[
{
"fromVersion": 1,
"toVersion": 2,
"operations": [
{
"operation": "move",
"from": "hero.title",
"to": "hero.headline"
},
{
"operation": "default",
"path": "hero.eyebrow",
"value": "Welcome"
}
]
}
]
Operation Effect Example
move Move an existing value to a new path Keep the owner’s headline while renaming its key.
default Supply a value only when the path is absent Add an eyebrow without replacing an existing value.
retire Remove a field from the new content shape Deliberately stop using an obsolete field.

fromVersion and toVersion refer to definition.json.version, not SDK/npm versions. The destination version must be higher, and there must be a complete migration path from the saved definition to the new one.

For this rename, update the definition’s nested field ID, its defaults, the component’s content.hero.headline access, and any references to that path. The editor section still refers to top-level hero, so that section does not need to change. Regenerate types afterward.

Paths are dot-separated. For list-item fields, services.*.title means the title in each service. A move must use the same number of wildcards on both sides.

A move into a different existing value is a conflict, not permission to overwrite the owner’s choice. Review the reported conflict. Older retained revisions preserve their prior content. retire intentionally removes a field from the new candidate, so use it only when the field is genuinely no longer needed.

These are declarative JSON operations. Do not add functions, script paths or executable migration files. Run validation and review staged content before publication.