Skip to content

Blueprint UI hint vocabulary

Blueprint UI hints describe semantic product intent without importing Flutter. The fixed Blueprint UI and Studio runtimes translate that intent into CDX controls, views, routes, forms, docks, and shell contributions.

Cascade

Inheritable hints resolve one property at a time. The closest declaration wins:

text
entity -> module -> Blueprint -> platform default

An entity can therefore override only maxSortLevels while continuing to inherit maxGroupLevels from its module. Assembly materializes the effective value once onto the effective entity UI plan; renderers do not walk the Blueprint graph during every build.

dart
final blueprint = Blueprint(
  name: 'ops',
  version: '0.3.0',
  ui: const BlueprintUI(
    query: QueryUI(maxSortLevels: 3, maxGroupLevels: 3),
  ),
  modules: [
    Module(
      name: 'elog',
      schema: 'elog',
      version: '0.3.0',
      ui: const ModuleUI(
        query: QueryUI(maxGroupLevels: 2),
      ),
      entities: [
        Entity(
          name: 'activity',
          tableName: 'activities',
          facets: const [],
          ui: const EntityUI(
            list: ListUI.auto(
              query: QueryUI(maxSortLevels: 1),
            ),
          ),
        ),
      ],
    ),
  ],
);

The effective elog.activity query policy is one sort level and two group levels.

Domain-attached hints

These types live in vyuh_blueprint and travel with the domain declaration.

ScopeVocabularySemantic intent
BlueprintBlueprintUI, QueryUI, ActionPlacementUICross-module defaults such as query composition limits and default action placements.
ModuleModuleUI, NavigationCategoryUIIcon, visibility, access, category, route prefix, navigation hierarchy and disclosure behavior, query overrides, and module action placements.
EntityEntityUI, EntityUIOverride, ListUI, DetailUI, EditorUI, RelatedUIIcon, visibility, access, category, route prefix, typed list layouts/query, detail views, editors, relationships, read-only posture, priority, detail-tab extension refs, and entity action placements.
FacetFacetUI, UISectionKindForm/detail/lifecycle/evidence/audit/relationship/analytics section semantics, order, access, and initial collapse.
FieldFieldUI, UIFieldControl, UIFieldDerivationIntrinsic editor family, access, order, filtering, sorting, search, input posture, read-only/hidden posture, help, placeholder, option search, dependencies, transforms, and a custom editor ref.
CollectionListUI, ListLayoutUI, TableUI, GridUI, KanbanUI, CalendarUI, TreeUI, TimelineUI, CustomUIOrdered available layouts, default layout, layout-specific projection/query, and declarative content composition.
TableTableColumnUI, UIColumnAppearance, UIColumnViewportField placement, cell treatment, width, responsive visibility, initial visibility, and required visibility.
FormFormUI, FormSectionUI, EditorUI, EditorPartUIDerived or explicit form composition, sections, columns, editor presentation, tabs/steps, and operation support.
Field valueUIBooleanLabels, UIOptionSearchSemantic boolean labels and search posture for choices.
Field referenceUIReferenceHintTarget entity and picker projection for reference-shaped fields.
RelationshipRelationshipUI, UIRelationshipPresentationPicker/rendering mode, projection, option search, editor/detail/inverse visibility, inline create, order, access, picker ref, and renderer ref.
ActionAction, ActionScope, ActionUIFacet-owned action semantics, target cardinality, icon, access, order, confirmation, destructive posture, presentation defaults, tooltip, and custom capture form ref.
Action placementActionPlacementRef, ActionPlacementUI, ActionUIRefExtensible placement identity plus ordered references into the effective facet action catalog.
Cross-cuttingUIIcon, UIVisibility, UIPlacement, UIAccess, UIAccessRule, UIAccessFallbackPortable icons, discoverability, read/write/execute gates, and denied-state behavior.

UIFieldControl currently supports automatic, text, multiline text, number, decimal, checkbox, date, date-time, enum select, reference picker, JSON, evidence, signature, checklist, photo capture, instrument capture, and custom editors.

Module navigation

Module and category menu behavior is declared with the Blueprint. Renderers preserve these values; they do not decide which groups are collapsible.

dart
ui: const ModuleUI(
  collapsible: true,
  initiallyCollapsed: false,
  navigationCategories: [
    NavigationCategoryUI(
      name: 'execution',
      title: 'Execution',
      collapsible: false,
    ),
    NavigationCategoryUI(
      name: 'configuration',
      title: 'Configuration',
      collapsible: true,
      initiallyCollapsed: true,
    ),
  ],
),

Categories without a parentRef are flat sections within the module. A parentRef creates one nested category level. Entities join a declared category through EntityUI.category or EntityUIOverride.category.

collapsible controls whether the label is an interactive disclosure. initiallyCollapsed controls its initial expansion state and may only be true when collapsible is true. Subsequent expansion is runtime user state.

Field dependencies and transforms

A target field can declaratively depend on one or more other fields. The dependency belongs to FieldUI; it is not hard-coded into a semantic field such as CodeField, and the editor does not infer it from field names.

dart
const name = NameField();

const code = CodeField.configured(
  ui: FieldUI(
    filterable: true,
    sortable: true,
    searchable: true,
    derivation: UIFieldDerivation(
      sourceFields: [name],
      transforms: [
        UITrimTransform(),
        UIUpperCaseTransform(),
        UIReplacePatternTransform(
          pattern: r'[^A-Z0-9]+',
          replacement: '-',
        ),
        UIReplacePatternTransform(pattern: r'^-+|-+$'),
      ],
    ),
  ),
);

Table placement is configured once in the table layout:

dart
const list = ListUI(
  layouts: [
    TableUI(
      columns: [
        TableColumnUI(
          field: code,
          appearance: UIColumnAppearance.identity,
          required: true,
        ),
        TableColumnUI(field: name),
        TableColumnUI(field: description, visible: false),
      ],
    ),
  ],
);

TableUI.columns is the complete column catalog for that table layout. It contains both the columns shown initially and optional columns that a user may enable later. Set visible: false to keep a column in the chooser without showing it initially. Set required: true for identity columns that a renderer must keep visible.

UIFieldTransform is sealed. The platform-owned defaults are therefore typed and exhaustively handled:

TransformPurpose
UIJoinTransform(separator: ...)Combines multiple source values.
UITrimTransform()Removes leading and trailing whitespace.
UIUpperCaseTransform()Converts text to uppercase.
UILowerCaseTransform()Converts text to lowercase.
UIReplacePatternTransform(...)Applies a typed regular-expression replacement.

The default vocabulary can expand without making every declaration stringly-typed. A product-specific transform uses the single escape hatch, UIFieldTransformRef:

dart
const site = ReferenceIdField('site_id');
const room = TextField('room');

derivation: UIFieldDerivation(
  sourceFields: [site, room],
  transforms: [
    UIJoinTransform(separator: '/'),
    UIFieldTransformRef(
      'ops.location.key',
      arguments: {'prefix': 'LOC'},
    ),
  ],
),

Dot-qualified references are recommended because they make ownership visible. Blueprint UI resolves the reference against the host registry:

dart
BlueprintRecordEditor(
  // ...
  valueTransformers: {
    'ops.location.key': (context) {
      final prefix = context.arguments['prefix'] ?? 'LOC';
      return '$prefix:${context.value}';
    },
  },
);

RecordFieldTransformContext provides the current pipeline value, declared source values, a read-only form snapshot, reference arguments, the target field, and the create/update operation. Referenced transforms are deliberately pure and synchronous: source fields express dependencies, while the registry supplies implementation. Remote lookups belong in reference pickers, async validation, or an action—not in a keystroke transform.

By default, a derivation applies on create and follows its sources until the person edits the target. The editor then preserves the override and exposes a relink affordance. UIFieldDerivationOverride.always, applyOnCreate, and applyOnUpdate make that behavior explicit. During assembly/runtime, unresolved or ambiguous source refs and dependency cycles are rejected.

This feature provides editor defaulting and linked input behavior. A server-enforced invariant still belongs in validation, a database expression, or action execution so every client observes the same rule.

Typed collection layouts

ListUI owns one ordered list of typed ListLayoutUI declarations. The first layout is the default. Every layout owns the projection, initial filter, and initial order it consumes; layout-specific placement does not leak into FieldUI.

LayoutConfiguration
TableUITableColumnUI entries with typed fields, appearance, width, responsive threshold, initial visibility, and required visibility.
GridUIColumn-based grid using CardContentUI for each repeated item, with identity/status/media/body/badge fields, minimum width, and maximum columns.
KanbanUIRequired column field, optional swimlane field, and card content.
CalendarUIRequired start field, optional end/resource fields, scale, and event content.
TreeUIRequired id/parent fields, initial expansion, and node content.
TimelineUIRequired start field, optional end/lane fields, scale, and item content.
CustomUIStable renderer ref plus serializable configuration.

ListUI.auto() asks assembly to derive a conservative TableUI and GridUI from semantic identity and lifecycle fields. Use it for ordinary masters. Declare layouts explicitly whenever the entity has meaningful Kanban, calendar, tree, or timeline semantics.

Forms and editors

FormUI is the complete declarative form configuration. There is no separate “form structure” vocabulary:

  • FormUI.derived() orders input-capable fields using facet and field metadata.
  • FormUI.sections(...) contains ordered FormSectionUI declarations.
  • FormSectionUI selects facets and/or typed field refs and sets a one-to-four column layout.
  • EditorUI.form configures a single-form editor.
  • EditorPartUI.form configures one tab or step in a multipart editor.

EditorUI additionally controls create/update support, adaptive/dock/dialog/ full-screen presentation, parts, actions, and the custom widget escape hatch. Fields remain responsible for intrinsic input capability and editor behavior; forms decide composition and order.

Effective actions

Facets own action definitions. UI declarations never copy an action and never become a second action catalog. Assembly traverses the entity once and materializes one EffectiveActionCatalog, whose entries can be referenced as:

  • action_name when the name is unique in the entity
  • facet_name.action_name
  • module.entity.facet_name.action_name

Known placements are collection.toolbar, collection.menu, selection.toolbar, selection.menu, record.header, record.action-bar, record.menu, command-palette, tab.<tab-id>.toolbar, and tab.<tab-id>.menu. ActionPlacementRef is a value type, so a runtime can add another stable placement without extending an enum.

dart
final Entity holidayCalendar = Entity(
  name: 'holiday_calendar',
  tableName: 'holiday_calendars',
  ui: const EntityUI(
    actionPlacements: [
      ActionPlacementUI(
        placement: ActionPlacementRef.recordHeader,
        actions: [
          ActionUIRef(
            'governance.activate',
            presentation: UIActionPresentation.icon,
          ),
        ],
      ),
      ActionPlacementUI(
        placement: ActionPlacementRef.recordMenu,
        actions: [ActionUIRef('governance.retire')],
      ),
      ActionPlacementUI(
        placement: ActionPlacementRef('tab.audit.toolbar'),
        actions: [ActionUIRef('governance.export_audit')],
      ),
    ],
  ),
  facets: [
    Facet(
      name: 'governance',
      actions: [
        Action(name: 'activate', scope: ActionScope.record),
        Action(name: 'retire', scope: ActionScope.record),
        Action(name: 'export_audit', scope: ActionScope.record),
      ],
    ),
  ],
);

Placement declarations follow the same override cascade:

text
entity -> module -> Blueprint -> scope-derived platform default

The closest declaration replaces the less-specific declaration for the same placement. When no placements are declared, ActionScope.collection, ActionScope.selection, and ActionScope.record map to the collection toolbar, selection toolbar, and record action bar respectively.

At runtime, EffectiveActionResolver combines the precomputed catalog, effective placements, selected record/count, actor permissions, policies, roles, groups, grants, qualifications, evidence, lifecycle/data rules, and optional custom condition evaluator. It returns one EffectiveActionSet per placement. Each member is explicitly enabled, disabled, or hidden, with a reason and tooltip suitable for rendering. The server remains the final execution authority.

App and workspace UI

Product composition belongs to vyuh_blueprint, not to entity hints. It describes where domain intent appears:

AppEntityUIScope separates domain availability from product ownership. Every portfolio app can retain the complete entity graph for protocol, authorization, scope, and reference resolution while deriving CRUD routes, collections, navigation, and commands only for its selected modules/entities.

UI familyVocabulary
RoutingRouteUI, AppRouteKind
CollectionsEffectiveEntityUI, ListUI, ListLayoutUI, TableUI, GridUI, KanbanUI, CalendarUI, TreeUI, TimelineUI, CustomUI, RelatedUI
Record details and editingDetailUI, DetailUIKind, EditorUI, EditorUIKind
ActionsEffectiveActionCatalog, ActionPlacementUI, EffectiveActionSet
Work queues and analyticsInboxUI, InboxItemKind, DashboardUI, DashboardWidgetKind
DiscoverySearchUI, SearchMode, CommandPaletteUI, SavedViewUI
Settings and profileSettingsUI, LocalizationUI, ProfileUI, AppearanceUI
Workspace navigationWorkspace, Navigation, NavigationGroup, NavigationItem
Shell and scopeAppShell, AppScope, ActorUI, TenantUI, SiteUI, ScopeSelectorUI
MenusMenuBarUI, MenuUI, MenuItemUI, MenuItemKind, UserMenuUI
Status and activityStatusBarUI, StatusIndicator, StatusIndicatorContext, NotificationUI, ActivityStreamUI
Governance and executionInspectorUI, PolicyUI, AccessUI, EvidenceUI, AuditUI, ExecutionUI, OfflineExecutionUI
Reports and helpReportUI, ReportBlock, ReportBlockKind, ReportOutputKind, HelpUI, HelpFragment, HelpScope
Runtime postureRealtimeUI, OfflineUI, OfflineStrategy, SimulationUI, IntegrationUI, DemoUI

SearchUI defaults to the server-derived global_search projection. It combines id, the available human identity fields (code, name, title, label, display_name, username, and email), and additional readable fields explicitly marked searchable. CommandPaletteUI.searchRefs keeps these search declarations independent, allowing each command-palette tab to render as soon as its own provider completes.

Extension vocabulary

Declarative hints are not a closed rendering system. BlueprintExtensionRef provides stable server/client seams for action handlers, rule evaluators, policy resolvers, effect handlers, routes, widgets, detail tabs, empty states, dashboard widgets, report blocks, forms, and custom extensions. Domain hints attach symbolic refs such as FieldUI.editorRef, RelationshipUI.pickerRef, RelationshipUI.rendererRef, ActionUI.formRef, and EntityUI.detailTabRefs; client/server registries bind them to code.

Ownership rule

Use typed Blueprint hints for portable product intent, map them into generic enterprise contracts in vyuh_blueprint_ui, render those contracts through vyuh_studio_ui, and keep low-level mechanics and tokens in CDX. Use a stable extension ref when product-specific code is required.

Blue is the Vyuh Blueprint documentation surface.