Skip to content

Unified Container Pattern

Idea from block grouping work (July 2026). Extends the Conversation V2 direction to all container-like blocks.

Observation

Today we have three container-like blocks that each store sub-blocks as properties on the parent object: Form, Slider, and Conversation. Each has its own reordering logic, its own sub-block management, and its own quirks. Block Groups, added later, use a different and simpler pattern: children are separate entries in creativeBlocks with a parent reference back to the group.

The group pattern is better:

  • Reordering works the same way as top-level blocks (fractional indexing on order)
  • No special-case code for "sub-blocks stored as object properties"
  • Undo/redo, copy/paste, duplicate all work without per-container-type handling
  • Blocks can be moved in and out of containers with just a parent field change
  • Nesting works naturally (groups inside groups)

The idea

Make the group pattern the universal container mechanism. Conversation, Form, and Slider become specialized groups rather than fundamentally different block types:

BlockWhat it really is
FormGroup with allowedSubBlocks: [formInput, submitButton, text, graphic] + form-specific config (submit action, validation, success message)
ConversationGroup that controls flow progression + chat styling (message/choice/response properties)
SliderGroup with slide navigation + transition config
Block GroupGeneric group, no specialized behavior

Each keeps its unique configuration (form submission, flow progression, slide transitions) but the child-block storage, ordering, copy/paste, undo, and nesting all use the same code path.

What this enables

  • Mixed content in conversations: Put a Graphic inside a Conversation and position it relative to the chat. Today this is impossible because Conversation is a closed system.
  • Forms with arbitrary content: Add a Text block between form inputs for instructions, or a Graphic for branding, without hacking it with custom CSS.
  • Nesting: A Conversation inside a Group, so its position is locked relative to other elements. Or a Form inside a Slider slide.
  • Simpler codebase: One reordering system, one copy/paste system, one undo system. Today each container type has its own version of these.

Migration path

This doesn't need to happen all at once. The Conversation V2 plan already moves in this direction with FlowGroup and MessageHolderV2. A possible sequence:

  1. Conversation V2 (already planned) -- new rendering layer, keeps existing data model but adds flow-group concept
  2. Form migration -- move form inputs from parent-object properties to separate creativeBlocks entries with parent: 'formProperties'. Form reordering is the most fragile today, so this has the highest payoff.
  3. Slider migration -- same treatment for slider slides
  4. Unify -- extract shared container logic (allowedSubBlocks, child management) into a common system

Each step is backward-compatible: a containerVersion flag (like conversationVersion) gates the new behavior, and existing creatives keep working on the old path.

  • conversation-v2-plan.md -- V2 rendering layer (Chunk 1-5)
  • feasibility.md -- Problem analysis for conversation specifically
  • ../../BlockGrouping/progress.md -- Block grouping implementation notes

Internal documentation