When converting between JSON and Markdown/HTML, some node types or fields cannot be represented natively.
@lyfie/luthor-headless preserves that data in metadata envelopes stored as HTML comments.
Comments are appended to source output:
<!-- luthor:meta v1 {"id":"featureCard:1:1","type":"featureCard","path":[1],"node":{"type":"featureCard","version":1,"payload":{"title":"AI Draft"}},"fallback":"[Unsupported featureCard preserved in markdown metadata]"} -->Source implementation:
packages/headless/src/core/metadata-envelope.tsjsonToMarkdown and jsonToHTML)prepareDocumentForBridge(...) sanitizes the JSON for source-safe conversion.appendMetadataEnvelopes(...) appends envelopes as <!-- luthor:meta v1 ... -->.markdownToJSON and htmlToJSON)extractMetadataEnvelopes(...) strips and parses envelope comments.rehydrateDocumentFromEnvelopes(...) restores preserved data.replace: for unsupported node types. The original node is restored by path.merge: for supported node types where extra metadata must be patched back onto native fields.markdown.ts intentionally keeps markdown-editable fields native (for example image alt text and embed captions) while storing non-native extras in merge envelopes. This supports manual markdown edits without losing richer metadata.
Legacy comments are still supported for backwards compatibility:
<!-- luthor:iframe {...} --><!-- luthor:youtube {...} -->markdown.ts and html.ts.ENVELOPE_VERSION stable unless the format truly changes.packages/headless/src/core/metadata-envelope.test.ts, packages/headless/src/core/markdown.test.ts, and packages/headless/src/core/html.test.ts.luthor:meta v1 comments appear when expected.LegacyRichEditor, MDEditor, HTMLEditor, and HeadlessEditorPreset in @lyfie/luthor disable many metadata-heavy features by default to keep source workflows predictable.