Fruitful Docs
GuidesTransform

Write the normalize transform

Bridge a binding that emits a different def than your transform consumes.

The transform module has three entry points fixed by the runtime: normalize, materializeRecords, and buildView. normalize is optional and exists for one situation: a binding whose emits is not the def your transform takes as input.

When you need it

transform.input is the def the transform consumes. When every transform-feeding binding the package pins emits the same def, input is that def and can be omitted. When they differ, declare input and export normalize for every binding whose emits is something else:

"transform": {
  "input": "com.example.blog.post@^1.0.0#extract",
  "hooks": { "file": "blog-plugin.js" },
  "records": ["com.example.blog.post@^1.0.0"]
}

The registry refuses a manifest where neither holds.

Write it

normalize receives items in the binding's emitted shape and returns items in the input shape:

import type { ContentPipelineModule } from 'workspace.packages.feed-package-runtime';

const plugin = {
  normalize(items, context) {
    if (context.binding !== 'legacy-archive') return items;
    return items.map((item) => ({
      ...item,
      fields: {
        title: item.fields['headline'],
        href: item.fields['link'],
        date: item.fields['published'],
      },
    }));
  },
  materializeRecords(items) { /* ... */ },
  buildView({ handler, root, records }) { /* ... */ },
} satisfies ContentPipelineModule;

export default plugin;

The output is validated against transform.input before materializeRecords runs. Items that do not conform are dropped and reported as rejections rather than failing the capture, so watch the validation summary's rejection counts after adding a normalizer.

Keep the rest pure

All three entry points run in the capability-free sandbox: no host, no network, no filesystem, no timers. Conversions that need URL, Intl, or base64 come from the declared stdlib. See Plugin runtime environment.

Reference: transform, transformHooks.

On this page