Diagram
100%

Drag to pan · Scroll to zoom · + / − to zoom · 0 to fit · Esc to close

Diagram
100%

Drag to pan · Scroll to zoom · + / − to zoom · 0 to fit · Esc to close

Diagram
100%

Drag to pan · Scroll to zoom · + / − to zoom · 0 to fit · Esc to close

Skip to content

1. Think in Blueprint ​

Blueprint separates what a domain means from how the platform executes it.

The authoring language is the direct Dart DSL. Canonical definition JSON, database DDL, protocol manifests, effective UI, and conformance artifacts are derived from it; none is a parallel authored source of truth.

ConcernOwnerExample
GrammarBlueprint packagesField, Facet, Action, Rule, Evidence
Domain programProduct blueprintops.area, activate, Area Type
ConfigurationTenant/site datagrants, thresholds, bindings, assignments
ExecutionGeneric runtimevalidate, plan, lock, commit, emit, record
ProjectionGeneric consumersPostgres, API, UI, timelines, analytics

This is similar to source code, a configured process, and an operating system:

The three planes ​

Declaration ​

Stable, versioned intent:

  • fields and relationships;
  • facets and entities;
  • actions, rules, lifecycles, and events;
  • evidence and audit requirements;
  • modules, exports, and extension references;
  • DB and UI hints.

Configuration ​

Values that vary by customer, environment, tenant, site, or time:

  • effective grants and qualifications;
  • policy values and locks;
  • assignments and calendars;
  • evidence-source bindings;
  • external-system bindings;
  • licensed application availability.

Configuration is not copied into the declaration. The runtime resolves it into an effective view and snapshots every value that influences a decision.

Execution ​

The domain-neutral interpreter:

The first complete blueprint ​

A small blueprint can contain one module and one entity:

dart
final Entity areaEntity = Entity(
  name: 'area',
  title: 'Area',
  pluralTitle: 'Areas',
  db: const EntityDb(tableName: 'areas'),
  facets: const [
    IdentityFacet(),
  ],
);

final Blueprint learningBlueprint = Blueprint.single(
  name: 'learning_ops',
  version: '0.1.0',
  schema: 'ops',
  entities: [areaEntity],
);

This is intentionally incomplete as a useful domain model, but it demonstrates the nesting:

Blueprint.single is a convenience. A real portfolio commonly declares multiple modules explicitly.

The module name is the semantic namespace. Its Postgres schema and default table names are derived through DbNamingStrategy unless ModuleDb or EntityDb declares an exceptional physical override. Protocol references do not change when physical storage naming changes.

Names are contracts ​

Use separate names for separate purposes:

  • name: stable machine identifier, normally snake case;
  • title / pluralTitle: human labels;
  • the entity type, <module>.<name> such as ops.area, is globally stable;
  • db.tableName: physical storage identity, when it differs from the derived plural;
  • i18nKey: optional localization namespace.

Never derive a user-facing label from a database column when a declared title exists. Never use a title as a stable protocol identity.

Checkpoint ​

Explain this sentence in your own words:

Blueprint is domain-agnostic, a domain blueprint is domain-specific, and the execution runtime becomes domain-agnostic again.

Then continue to Fields, types, and rows.

Design principles: Why Blueprint.