Skip to content

What's New in the Component System

A summary of changes for template and component authors already familiar with {{ insert() }} and component.yml.

Parameter names: _alias and _ask

The alias and ask parameters on insert() have been renamed to _alias and _ask:

{# Before #}
{{ insert('nda', alias='confidentiality', ask="Include NDA?") }}

{# After #}
{{ insert('nda', _alias='confidentiality', _ask="Include NDA?") }}

Why: The old names were reserved — you couldn't have a component input called alias or ask. The _ prefix creates a clear namespace for VIBE directives, freeing all unprefixed names for your component's inputs.

The old names are no longer accepted; VIBE will report a validation error if you use them.

Positioning questions with _after

Instead of adding _insert_questions_ markers to your config.yml, you can now position component questions directly from insert():

{{ insert('signature_block', _alias='signer', _after='contract_value') }}

This places the component's interview questions immediately after contract_value — no config marker needed.

When combined with _ask, the gate question also appears at the _after position:

{{ insert('nda', _after='client_name', _ask="Include an NDA?") }}

The _insert_questions_ markers in config.yml still work; _after is an alternative that keeps positioning closer to the insert() call.

Followup questions with _follows

Use _follows to make component questions appear as visual follow-ups nested under a host question:

{{ insert('address_details', _follows='client_city') }}

When the user answers client_city, the component's questions (postal code, country) appear as sub-questions visually attached to it.

_after and _follows are mutually exclusive — _after positions questions in the main interview list, _follows nests them under a parent.

collection.yml replaces defaults.yml

The configuration file for component collections has been renamed from defaults.yml to collection.yml:

components/
└── legal_clauses/
    ├── collection.yml      ← preferred name
    ├── force_majeure.md
    └── governing_law.md

Both names are still recognized, but collection.yml is preferred. No action required — existing defaults.yml files continue to work.

Collection questions

Collections can now have their own interview questions, declared in collection.yml alongside inputs:

# collection.yml
inputs:
  PartyA:
    type: text
  PartyB:
    type: text

questions:
  ArbitrationPreferred:
    label: Do the parties prefer arbitration?
    type: bool

How they differ from inputs:

Inputs Collection questions
Who provides the value The host, via insert() or component_defaults The user, during the interview
Asked how many times N/A (not asked) Once per collection, regardless of how many components you insert
Use case Data the host knows (party names, dates) Details internal to the collection (clause variants, preferences)

Component templates reference collection questions as regular variables:

{% if ArbitrationPreferred %}
Any disputes shall be resolved by arbitration...
{% else %}
Any disputes shall be resolved by the courts of {{ Jurisdiction }}...
{% endif %}

Values passed via insert() take precedence over collection question answers, so hosts can override when needed:

{{ insert('legal_clauses.governing_law', ArbitrationPreferred=false) }}

When to use inputs vs. questions: If the host template naturally knows the value (party names, governing law, language), make it an input. If the value is a detail of how the collection's templates work internally (clause variants, formatting preferences), make it a question.

Grouped gates with _multichoice

When several optional components should be presented as a single multichoice (checkbox) question instead of separate Yes/No gates, use _multichoice:

{{ insert("clauses.ai", _ask="Artificial Intelligence", _multichoice="Commitments") }}
{{ insert("clauses.bench", _ask="Benchmarking", _multichoice="Commitments") }}
{{ insert("clauses.sla", _ask="Service Levels", _multichoice="Commitments") }}

All insert() calls that share the same _multichoice label are combined into one multichoice question. Each component's _ask label becomes a checkbox option. Checking an option opens that component's gate; unchecking it closes it.

Constraints:

  • _multichoice requires _ask (the option label).
  • _multichoice cannot be combined with _follows.
  • All members of a group that use _after must target the same question.

Placement uses the same mechanisms as standalone gates — _after, or a config marker named after the generated question ID. The ID is _mc_ followed by a slug of the label (e.g., _multichoice="Commitments"_mc_commitments). You can reserve its position in config.yml:

questions:
  title:
    type: text
  _mc_commitments: true   # marker — multichoice question appears here
  author:
    type: text

Automatic followup nesting for collection questions

When a component collection is gated by a _multichoice question, collection- level questions are now automatically nested as followups of the relevant checkbox option — provided the question is referenced by exactly one component template in the collection.

Questions referenced by two or more components (or by none) remain standalone, since there is no single obvious parent to attach them to.

This means the interview only shows a collection question when the user has selected the component that actually needs it, rather than displaying it unconditionally.

Input scoping

When you insert a template from a collection, VIBE now only validates the inputs that template actually uses — not every input the collection declares.

# collection.yml — declares three inputs
inputs:
  PartyA:
    type: text
  PartyB:
    type: text
  Jurisdiction:
    type: text

If force_majeure.md only references PartyA, then inserting it without providing PartyB or Jurisdiction is valid:

{{ insert('legal_clauses.force_majeure', PartyA=client_name) }}
{# No error — force_majeure.md doesn't use PartyB or Jurisdiction #}

This makes large collections practical. A clause library can declare dozens of inputs without every template needing all of them.

Summary of insert() parameters

All VIBE directive parameters use the _ prefix. Component input names are always unprefixed.

Parameter Purpose Example
_alias Unique instance name (required for multiple insertions of same component) _alias='party_a_sig'
_ask Gate question — user decides whether to include _ask="Include NDA?" or _ask=True
_after Position questions after a named host question _after='contract_value'
_follows Nest questions as follow-ups of a host question _follows='client_city'
_multichoice Group multiple components into one checkbox question _multichoice="Commitments"
(any other) Component input value PartyA=client_name