Repository navigation
Description
Split out of #104, where the six 0.5/0.6 fields landed (#106) but this did not: it is a submission flow, not a field.
The case, measured
From publishing a 17-talk conference by hand (the same BiznagaFest 2026 session behind #97): all 17 documents carry an identical partOf block (id, name, url, type: "multipart") and an identical partOf.offers — the set's shared admission. The only things that differ per talk are name, startDate, speakers and tags.
So the editor asks a human to retype a byte-identical block seventeen times, for a field the spec requires to be equal by value across the set (D032). A typo in one partOf.id breaks the grouping silently.
What it would do
Fill in the shared block once — partOf identity plus the shared admission — then fill in only the per-part fields, and generate N documents in one pass.
Why it is not just another repeater
It lands in the batch submission path, not the field tables: submitRecurringBatch() / proposeBatchChangeUrl in apps/editor/src/main.ts, the same pipeline that proposes a generated series as one issue rather than loading it into the one-by-one import queue. The form half (FIELD_SPECS / REPEATER_SPECS) is already done and is not what this needs.
Do it together with #51
#51 asks for arbitrary, non-regular dates for a multipart event, because "+ Add recurrence" is strictly rule-based. That is this same mechanism: N documents sharing one partOf filled in once, through the same generation/review/submission pipeline. The difference is only what varies per part — a date in #51, a date plus name/speakers/tags here.
Scoping them separately risks two competing repeaters ("+ Add session" and "+ Add talk") that do almost the same thing. They want one UX pass covering: where it lives in the form, how it interacts with the "Part of" series-linking wizard, and whether it is its own row type or a mode of the existing recurrence rows.
Open questions
- How are
idand the filename slug minted per part?suggestSeriesSlugis day-level, which collides when several talks share a day — the conference case, unlike the weekly-meetup case it was written for. - A table of parts, or one at a time? 17 rows of 4 fields is a different widget from the recurrence rows.
- What happens when the shared block is edited after generating — rewrite all 17 files, or leave them?
Already built, so not blocking
- The consistency check exists.
sharedOffersConsistentis a feed-level keyword in@opentechevents/validate, andbuild-feed --checkruns the feed keywords (build-feed: 0.5 support, run the feed keywords in --check, and keep partOf.offers consistent (plus: ote-migrate does not exist) #97, done). Divergence between parts is caught today. - The editor writes both halves correctly as of feat(editor): give the six 0.5/0.6 fields a form, so adopters can publish them #106:
partOf.offersandoffers[].scope, serialized through one shared helper precisely so the parts match by value. What is missing is only the shortcut that avoids typing it 17 times.
Related: #51 (the sibling, do them together), #97 (the --check half, done), #104 (the fields, done).
Activity