docs/plans/2026-04-09-date-media-expansion-consensus-plan.md
Historical for the date half.
Current read:
Use this file as:
Create the real implementation plan for the remaining date and
media/embed expansion batch described in
.omx/specs/deep-interview-date-media-expansion-completion.md,
grounded in current law, research, and runtime.
date to one plain string payload on node.date and
plain <date>value</date> round-trip in
docs/editor-behavior/markdown-editing-spec.md.deferred and current render
behavior as only specified in
docs/editor-behavior/editor-protocol-matrix.md.Date and Media embed as locked only for the narrow
current contract, with richer expansion still in the feature-gap rows in
docs/editor-behavior/markdown-parity-matrix.md.new Date().toDateString() in
packages/date/src/lib/transforms/insertDate.ts
and the demo renderers write toDateString() back from the calendar in
apps/www/src/registry/ui/date-node.tsx
and
apps/www/src/registry/ui/date-node-static.tsx.<date>
element in
packages/markdown/src/lib/rules/defaultRules.ts.parseVideoUrl.ts, parseTwitterUrl.ts, and submit-time mutation in
packages/media/src/react/media/FloatingMedia/submitFloatingMedia.ts.audio / file /
video in
packages/markdown/src/lib/rules/mediaRules.ts,
but embed-specific richer metadata is still not first-class there.toDateString() is not a good long-term wire
format.date as one raw string.url plus whatever parsers infer at runtime.toDateString() contractChoose Option A, but keep the date node migration narrower than a full field rename.
That means:
date gets a canonical machine-readable value with derived render labels.media/embed gets explicit normalized metadata plus trust-boundary handling,
with provenance persisted only where it materially helps editing.Adopt a richer Plate-owned date node contract in @platejs/date:
dateYYYY-MM-DD calendar-day stringRecommended canonical node value:
{
date: "2026-03-23";
}
Markdown / MDX wire-shape decision for this batch:
<date>2026-03-23</date><date value="2026-03-23" />Recommended compatibility behavior:
<date>...</date> inputnode.date:
YYYY-MM-DDDate.prototype.toDateString() outputdate nodetoDateString() values from inserts or the calendar UILimited render behavior in scope:
dateYYYY-MM-DD as a calendar day without timezone drift instead
of relying on raw new Date(node.date)date node is encountered outside the markdown
fallback path, render it as literal fallback text instead of inventing a
parsed dayOut:
Adopt a richer normalized embed contract in @platejs/media:
url: canonical render/embed URLprovider: normalized provider slugid: normalized provider resource idsourceUrl: canonical user/source-facing URL when the edit surface needs to
preserve a user-facing URL different from urlNormalization-only metadata for this batch:
sourceKind may exist inside shared normalization helpers and testssourceKind does not need to become a serialized markdown/document field in
this batch unless a second durable consumer appearsRecommended boundaries:
Limited render behavior in scope:
sourceUrl when available instead of leaking
only provider embed URLs back to usersdate value.toDateString().YYYY-MM-DD, non-normalizable legacy markdown date input stays on an
explicit non-date fallback path, and existing non-canonical date nodes use
a literal renderer fallback instead of being silently reinterpreted.@platejs/media.media_embed metadata round-trips through explicit markdown/MDX
rules and tests instead of hidden fallback behavior.markdown-editing-spec.md, editor-protocol-matrix.md,
markdown-parity-matrix.md, the reopened expansion note, and public docs all
describe the same boundary.Files:
packages/date/src/lib/** for normalization/serializationpackages/dateWork:
@platejs/datetoDateString() to canonical dateFiles:
Work:
element.date as a free-form display stringdatedatenew Date(element.date) logic in app codeFiles:
Work:
Files:
packages/media/src/lib/media-embed/parseVideoUrl.tspackages/media/src/lib/media-embed/parseTwitterUrl.tspackages/media/src/react/media/useMediaState.tspackages/media/src/lib/media-embed/BaseMediaEmbedPlugin.tsWork:
parseMediaUrlparseIframeUrl as a trust-boundary helper, not the whole contracturl, provider, id, plus sourceUrl only
if the edit path truly needs itsourceKind as normalization/debug metadata unless a real serialized
consumer emergesmedia_embed metadataFiles:
media_embed markdown rule beside itWork:
media_embed instead of leaving ownership
optional or hidden behind fallback behaviorDate tests:
packages/date/src/lib/transforms/insertDate.spec.tsxpackages/date/src/lib/BaseDatePlugin.spec.tsxpackages/markdown/src/lib/dateElement.spec.tsapps/www/src/registry/ui/date-node.spec.tsxapps/www/src/registry/ui/date-node-static.spec.tsxMedia tests:
packages/media/src/lib/media/parseMediaUrl.spec.tspackages/media/src/lib/media-embed/parseIframeUrl.spec.tspackages/media/src/lib/media-embed/BaseMediaEmbedPlugin.spec.tspackages/media/src/react/media/FloatingMedia/submitFloatingMedia.spec.tspackages/media/src/react/media/useMediaState.spec.tsmedia_embed, preferably beside
packages/markdown/src/lib/mediaSurface.spec.tsFiles:
content/(plugins)/(elements)/date.mdx,
content/(plugins)/(elements)/media.mdx, and
content/(plugins)/(serializing)/markdown.mdxWork:
Packages likely touched:
@platejs/date@platejs/media@platejs/markdownMitigation:
Mitigation:
Mitigation:
sourceUrl as opt-in and justified by edit-flow reversibilitysourceKind out of the serialized contract unless a second durable
consumer appearsMitigation:
Mitigation:
dateTargeted tests:
bun test packages/date/src/lib/transforms/insertDate.spec.tsx \
packages/date/src/lib/BaseDatePlugin.spec.tsx \
packages/markdown/src/lib/dateElement.spec.ts \
packages/media/src/lib/media/parseMediaUrl.spec.ts \
packages/media/src/lib/media-embed/parseIframeUrl.spec.ts \
packages/media/src/lib/media-embed/BaseMediaEmbedPlugin.spec.ts \
packages/media/src/react/media/FloatingMedia/submitFloatingMedia.spec.ts \
packages/media/src/react/media/useMediaState.spec.ts \
packages/markdown/src/lib/mediaSurface.spec.ts \
apps/www/src/registry/ui/media-video-node.spec.tsx
Then run the new test files added in this batch for:
apps/www/src/registry/ui/date-node.spec.tsxapps/www/src/registry/ui/date-node-static.spec.tsxmedia_embed markdown round-trip coverageBuild:
pnpm install
pnpm brl
pnpm turbo build --filter=./packages/date --filter=./packages/media --filter=./packages/markdown --filter=./apps/www
Typecheck:
pnpm turbo typecheck --filter=./packages/date --filter=./packages/media --filter=./packages/markdown --filter=./apps/www
Fallback if filtered typecheck still hits unresolved workspace-package imports:
pnpm build
pnpm turbo typecheck --filter=./packages/date --filter=./packages/media --filter=./packages/markdown --filter=./apps/www
Lint:
pnpm lint:fix
Browser verification:
browser-use --connect http://127.0.0.1:9222
Verify the date demo path still shows:
Keep non-normalizable legacy markdown fallback and existing non-canonical
date node renderer fallback under explicit unit/spec coverage instead of
pretending browser demos cover them automatically.
Implement the remaining date/media expansion batch as a source-canonical contract upgrade, not as a UI-first product pass.
This is the smallest batch that actually fixes the architecture instead of adding more behavior on top of fuzzy data.
Relevant roles for the follow-up execution:
plannerarchitectcriticexplorerexecutortest-engineerverifierwritercode-reviewerralphSuggested lane order:
Suggested reasoning levels:
xhighhighhighhighteamSuggested staff split:
packages/date/**apps/www/src/registry/ui/date-node.tsxapps/www/src/registry/ui/date-node-static.tsxpackages/media/**packages/markdown/**Suggested reasoning levels:
xhighhighhighLaunch hints:
$team "Execute docs/plans/2026-04-09-date-media-expansion-consensus-plan.md"
omx team run docs/plans/2026-04-09-date-media-expansion-consensus-plan.md