Schemas / Migration

Migrating from v0.3 to v0.4

You only need to migrate a document if you want its v0.4 lifecycle fields. Documents stay valid against the hosted v0.3 contracts until you move them. For each document you do move, the work is small: point $schema at the v0.4 URL, set schemaVersion to "0.4.0", and rewrite any lifecycle metadata in the new shape.

Start here

v0.4 is a lifecycle release. It standardizes a canonical status field across every manifest entity, centralizes deprecation records in a new shared lifecycle fragment, accepts an explicit deprecated: false assertion in native manifests, and moves every contract URL from the v0.3 /schemas/v0.3/… addresses to /schemas/v0.4/…. Nothing is converted automatically, and migrating is an explicit, document-by-document or profile-by-profile decision.

This guide compares v0.4 with the hosted v0.3 contracts: the snapshot served from /schemas/v0.3/, whose $id values are https://designlasagna.recipes/v0.3/<file>. The v0.3 copy shipped inside @designlasagna/schemas@0.4.0 is already stricter: its platform mappings are closed, usage is removed, and its $id differs. Validating against that copy surfaces the platform-mapping break before you migrate. Package 0.4.0 tightened the v0.3 contracts as well, so you meet that change when you upgrade the package, whether or not you move documents to v0.4.

At a glance

Required, and may break existing documents

  • Native manifests: new $schema URL under /schemas/v0.4/, and schemaVersion: "0.4.0".
  • message in a deprecation record must be a non-empty string.
  • Platform mappings in tokens and DTCG extensions are closed, and usage is removed.

Optional

  • A status field on every entity.
  • An explicit deprecated: false in native manifests.
  • Per-entity lifecycle extensions in CEM manifests.

Migration checklist

All documents

  1. Inventory. List your v0.3 documents (tokens, utilities, icons manifests; CEM manifests; DTCG files with recipes.designlasagna extensions) and the consumers of each.
  2. Choose what moves. Migrate only documents whose consumers support v0.4. Everything else stays on v0.3, which remains published.

Native track

  1. Declare the format. Set $schema to the v0.4 URL (for example https://designlasagna.recipes/schemas/v0.4/tokens.json) and schemaVersion: "0.4.0".
  2. Rewrite lifecycle metadata. Add status where relevant and convert deprecated to the record shape. Use deprecated: false only where an explicit negative assertion is wanted.
  3. Drop removed data. Remove PlatformMapping.usage and any custom platform keys from tokens.

CEM and DTCG track

  1. CEM. Keep the standard CEM schemaVersion; author status and deprecated in the extension fields.
  2. DTCG. Keep the standard $deprecated boolean/string mirror; put the structured record in recipes.designlasagna; add status where useful; remove PlatformMapping.usage and any custom platform keys.
  3. Select the profile. Select lifecycle profile 0.4 in the consuming project or resolver config.

Both tracks

  1. Tooling. Install @designlasagna/schemas@0.4.0 (or a later 0.4.x), import from the v0.4/ paths, and register all six v0.4 schemas by $id for offline validation.
  2. Validate both directions. Migrated documents validate against the v0.4 contracts; unmigrated documents continue to validate against v0.3.

Before and after

These examples are adapted from the package's lifecycle migration document, and the site's tests validate them against the contracts.

Native example

Tokens, utilities and icons share the same lifecycle fields; this is a tokens manifest. Opt in at the manifest root, and put status and deprecated on each entry.

v0.3

{
  "$schema": "https://designlasagna.recipes/schemas/v0.3/tokens.json",
  "schemaVersion": "0.3.0",
  "tokens": [
    {
      "id": "color.old",
      "resolved": {
        "default": "#0b5fff"
      },
      "deprecated": {
        "message": "Use color.new."
      }
    }
  ]
}

v0.4

{
  "$schema": "https://designlasagna.recipes/schemas/v0.4/tokens.json",
  "schemaVersion": "0.4.0",
  "tokens": [
    {
      "id": "color.old",
      "resolved": {
        "default": "#0b5fff"
      },
      "status": "deprecated",
      "deprecated": {
        "message": "Use color.new.",
        "replacement": "color.new",
        "removal": "2027-01-01"
      }
    }
  ]
}

DTCG example

Keep the standard $deprecated mirror and add the structured record to the vendor extension. Only the extension payload is checked against the contract.

Before

{
  "color": {
    "old": {
      "$type": "color",
      "$value": "#0b5fff",
      "$deprecated": "Use color.new."
    }
  }
}

After

{
  "color": {
    "old": {
      "$type": "color",
      "$value": "#0b5fff",
      "$deprecated": "Use color.new.",
      "$extensions": {
        "recipes.designlasagna": {
          "status": "deprecated",
          "deprecated": {
            "message": "Use color.new.",
            "replacement": "color.new"
          }
        }
      }
    }
  }
}

CEM example

Keep the standard deprecated string and add sibling fields. Do not use an object in deprecated. The attribute and its values are deprecated independently.

Before

{
  "name": "size",
  "deprecated": "Use variant."
}

After

{
  "name": "size",
  "deprecated": "Use variant.",
  "status": "deprecated",
  "replacement": "variant",
  "removal": "2027-Q1",
  "deprecatedValues": [
    {
      "value": "medium",
      "message": "Use large.",
      "replacement": "large"
    }
  ]
}

Format version v0.4 vs package release 0.4.0

v0.4 is the schema format version — the set of contracts under /schemas/v0.4/ and the v0.4 section of these docs. 0.4.0 is the npm release version of @designlasagna/schemas that ships those files (@designlasagna/schemas@0.4.0, import paths @designlasagna/schemas/v0.4/*.json). The two move together but are different things:

  • In a manifest's $schema, use the format version in the URL: https://designlasagna.recipes/schemas/v0.4/tokens.json.
  • In a native manifest's schemaVersion field (a plain semver string), write "0.4.0" for a v0.4-format manifest — "0.3.0" for one that stays on v0.3.
  • When installing or importing contracts, pin the package release: @designlasagna/schemas@0.4.0.

See the schema overview for the same format-vs-release distinction.

Lifecycle selection

Native manifests
Opt in Per document: v0.4 $schema URL and schemaVersion: "0.4.0"
Otherwise The document stays on v0.3
CEM
Opt in Select lifecycle profile 0.4 in project or resolver config
Otherwise Legacy profile; v0.4 fields are not applied
DTCG
Opt in Select lifecycle profile 0.4 in project or resolver config
Otherwise Legacy profile; v0.4 fields are not applied

Nothing converts automatically; the full selection rules are in the lifecycle reference.

What changed per contract

The per-contract breakdown, with breaking changes marked, is in the v0.4.0 changelog entry.

What did not change

  • Root manifest requirements; schemaVersion is still a plain string.
  • Extension namespaces: the CEM $extensions key and DTCG recipes.designlasagna.
  • Deprecation records still require message; removal and replacement stay optional strings.
  • v0.3 documents stay valid against the hosted v0.3 contracts.
  • v0.2 contracts are untouched.

References

All schemas