Composition / foldkit-composition

Conditions

A node shows only when its when holds over the page's context: what the page is drawn for, such as an audience, a locale or a feature flag. The Catalog declares the context as a Schema, and the application supplies its values when it draws:

ts
const Site = Catalog.make({
  blocks,
  roots: [Content.Section],
  context: Schema.Struct({ audience: Schema.Literals(['guest', 'member']) }),
})

Composition.Op.setWhen(id, [Composition.when.eq('audience', 'member')])
Renderer.render(SiteRenderer, page, h, { context: { audience: 'guest' } }) // left out
  • A when is a list, and every condition must hold: when.eq(key, value), when.isNull(key), when.isNotNull(key) and when.contains(key, text). They mean what foldkit-entity's Expr means: contains ignores case, folding ASCII only, and absent text contains nothing.
  • Checked against the context, by validate and by setWhen: a key the context does not declare, or a value its Schema refuses, is composition:unknown-context, never a node that silently never shows. A value is what the application gives, the field's decoded side: over Schema.NumberFromString, a condition names a number. A condition naming two operations is composition:invalid-condition.
  • Drawn without its context, a page fails closed: a node with conditions does not show. In edit mode it is drawn anyway, marked data-composition-hidden, so an author sees what a visitor would not. Composition.holds(when, context) is the same test.
  • when is presentation, not authorization. A member-only section hidden from guests is still in the Document a guest's page was drawn from. Content a guest must not receive belongs behind the CMS audience boundary or a server-authorized read.
  • Viewport is not a condition: the server cannot know it. A node hidden on narrow screens is an appearance.