Skip to content
GitHub

Constraints and Scoped Names

bino supports constraints that let you conditionally include documents and inline layout children based on the target ReportArtefact’s labels, spec, or the current execution mode. This enables scenarios like mode-specific pages (preview-only debug views), environment-specific data sources, artefact-specific layouts, or conditional components within a page.

When building or previewing a specific ReportArtefact, bino evaluates the metadata.constraints on:

  • Every non-artefact document (DataSource, DataSet, LayoutPage, Asset, etc.)
  • Inline children of LayoutPage and LayoutCard (nested components)

A document or inline child is included only if all its constraints evaluate to true. Items without constraints are always included.

apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: debugPage
  constraints:
    - mode==preview
spec:
  # This page is only included when running `bino preview`
  children:
    - kind: Text
      spec:
        value: "Debug information - only visible in preview mode"

Constraints can be written in two equivalent formats. Both are fully supported and maintained.

Quick and readable for simple constraints:

metadata:
  constraints:
    - mode==preview
    - labels.env==prod
    - spec.format in [pdf,png]

Each constraint is a string with the format: <field> <operator> <value>

Better IDE support with autocomplete and validation:

metadata:
  constraints:
    - field: mode
      operator: "=="
      value: preview
    - field: labels.env
      operator: in
      value: [dev, staging, prod]

You can mix both formats in the same document:

metadata:
  constraints:
    - mode==preview                    # String format (quick)
    - field: spec.output.format        # Structured format (IDE autocomplete)
      operator: in
      value: [pdf, png]

Both formats have identical evaluation behavior and performance.

The left side (or field property) determines what is being checked:

Field PathDescriptionExample Values
modeCurrent execution modebuild, preview, serve
artefactKindType of artefact being builtreport, screenshot, document, livereport
labels.<key>Artefact’s metadata.labels.<key>Any string value
spec.<field>Artefact’s spec.<field>Format, orientation, etc.
OperatorDescriptionValue TypeString ExampleStructured Example
==Equalsstring, boollabels.env==prod{field: "labels.env", operator: "==", value: "prod"}
!=Not equalsstring, boolmode!=preview{field: "mode", operator: "!=", value: "preview"}
inValue in arrayarraylabels.env in [dev,prod]{field: "labels.env", operator: "in", value: ["dev", "prod"]}
not-inValue not in arrayarraymode not-in [serve]{field: "mode", operator: "not-in", value: ["serve"]}
  • String: For == and != operators
  • Boolean: Use true or false (in string format, write them without quotes)
  • Array: For in and not-in operators (in string format: [value1,value2])

Constraints are evaluated against the target ReportArtefact:

  • mode: The current execution mode: build, preview, or serve
  • labels: The artefact’s metadata.labels map
  • spec: The artefact’s spec fields (e.g., format, orientation, language)
ModeDescriptionCommand
buildBuilding artefacts for production output (PDF/HTML)bino build
previewLive preview during development with hot reloadbino preview
serveProduction serving via LiveReportArtefactbino serve
KindDescriptionArtefact Type
reportStandard data-driven PDF reportsReportArtefact
screenshotComponent screenshots for testingScreenshotArtefact
documentMarkdown-based documentsDocumentArtefact
livereportInteractive web reports with routesLiveReportArtefact
apiVersion: bino.bi/v1alpha1
kind: ReportArtefact
metadata:
  name: weeklyReport
  labels:
    env: prod
    region: europe
spec:
  title: Weekly Sales Report
  filename: weekly-report.pdf
  format: a4

Documents can now reference these labels and spec fields:

apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: sales_data
  constraints:
    - labels.env==prod
spec:
  type: postgres_query
  # ... production database connection

When multiple constraints are specified, all must match for the document to be included.

metadata:
  name: europeOnlyPage
  constraints:
    - labels.region==europe
    - mode==build

This page is included only when:

  1. The artefact has labels.region: europe, AND
  2. The command is bino build (not preview)

Show debug information or work-in-progress pages only during development:

# String format
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: dataDebugPage
  constraints:
    - mode==preview
spec:
  children:
    - kind: Table
      spec:
        dataset: raw_data

Or using structured format:

# Structured format
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: dataDebugPage
  constraints:
    - field: mode
      operator: "=="
      value: preview
spec:
  children:
    - kind: Table
      spec:
        dataset: raw_data

Use different data sources for development vs production:

# Development mock data
apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: sales
  constraints:
    - labels.env==dev
spec:
  type: inline
  content: |
    [{"region": "Test", "amount": 100}]
---
# Production database
apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: sales
  constraints:
    - labels.env==prod
spec:
  type: postgres_query
  connection:
    host: prod-db.example.com
    # ...

Match multiple environments at once:

apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: staging_data
  constraints:
    - labels.env in [dev,staging,qa]   # Matches any non-production environment
spec:
  type: postgres_query
  connection:
    host: staging-db.example.com

Or using structured format:

apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: staging_data
  constraints:
    - field: labels.env
      operator: in
      value: [dev, staging, qa]
spec:
  type: postgres_query
  connection:
    host: staging-db.example.com

Include a document in all modes except specific ones:

apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: mainPage
  constraints:
    - mode not-in [serve]   # Included in build and preview, but not serve
spec:
  # ...

Include components only for specific artefact types:

# Include this data source only in ReportArtefacts (not DocumentArtefacts)
apiVersion: bino.bi/v1alpha1
kind: DataSource
metadata:
  name: complex_dashboard_data
  constraints:
    - artefactKind==report
spec:
  type: postgres_query
  # ... complex query for dashboard

Or exclude from specific artefact types:

# Include everywhere except ScreenshotArtefacts
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: fullPage
  constraints:
    - artefactKind not-in [screenshot]
spec:
  # Full page layout

Create different layouts for different output formats:

apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: summaryPage
  constraints:
    - spec.format==a4
spec:
  pageFormat: a4
  # A4-optimized layout
---
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: summaryPage
  constraints:
    - spec.format==xga
spec:
  pageFormat: xga
  # Screen-optimized layout

Or using in for multiple formats:

apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: printPage
  constraints:
    - spec.format in [a4,letter,legal]   # Any print format
spec:
  # Print-optimized layout

Constraints also work on inline children of LayoutPage and LayoutCard. This allows you to conditionally include or exclude specific components within a layout:

apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: dashboardPage
spec:
  pageLayout: split-vertical
  children:
    # This card only appears in build mode
    - kind: LayoutCard
      metadata:
        name: productionCard
        constraints:
          - mode==build
      spec:
        cardLayout: full
        children:
          - kind: Table
            spec:
              dataset: production_data

    # This card only appears in preview mode
    - kind: LayoutCard
      metadata:
        name: debugCard
        constraints:
          - mode==preview
      spec:
        cardLayout: full
        children:
          - kind: Text
            spec:
              value: "Debug view - not included in final PDF"

    # This table always appears (no constraints)
    - kind: Table
      spec:
        dataset: summary_data

Inline child constraints support the same syntax as document-level constraints, including structured format:

children:
  - kind: ChartStructure
    metadata:
      name: europeChart
      constraints:
        - field: labels.region
          operator: in
          value: [europe, emea]
    spec:
      dataset: regional_data
Use CaseRecommended FormatWhy
Simple equality checkStringMore concise: labels.env==prod
Multiple values (in operator)EitherBoth work well; structured has clearer array syntax
Want IDE autocompleteStructuredJSON Schema provides field/operator suggestions
Quick prototypingStringFaster to type
Team prefers YAML validationStructuredBetter schema enforcement
Mixed team (devs + analysts)BothLet each choose their preference

With constraints, metadata.name uniqueness is per artefact after filtering, not global.

This means:

  • The same name can appear multiple times in your configuration
  • After applying constraints for a specific artefact, each kind must have unique names
  • Different artefacts can include different documents with the same name (if constraints prevent both from matching the same artefact)
# Both documents have the same name
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: mainPage
  constraints:
    - labels.variant==simple
spec:
  # Simple layout
---
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
  name: mainPage
  constraints:
    - labels.variant==detailed
spec:
  # Detailed layout

With two artefacts:

apiVersion: bino.bi/v1alpha1
kind: ReportArtefact
metadata:
  name: simpleReport
  labels:
    variant: simple
spec:
  # Uses the first mainPage
---
apiVersion: bino.bi/v1alpha1
kind: ReportArtefact
metadata:
  name: detailedReport
  labels:
    variant: detailed
spec:
  # Uses the second mainPage

If constraints allow two documents with the same name and kind to match a single artefact, bino fails with an error:

artefact "weeklyReport": duplicate LayoutPage name "mainPage" - defined in report.yaml #3 and report.yaml #7 (after applying constraints)

Constraints are validated at build/preview/serve time. Errors are reported immediately with helpful hints:

constraint error in DataSet "sales_ds": missing operator
  constraint: labels.env prod
  hint: use '==', '!=', 'in', or 'not-in' to compare values, e.g., 'mode==preview'
constraint error in LayoutPage "europeOnlyPage": label "region" not defined on artefact
  constraint: labels.region==europe
  hint: add 'labels.region' to the ReportArtefact's metadata
constraint error in DataSource "sales": spec field "unknown" not found
  constraint: spec.unknown==value
  hint: check that the spec field exists on the ReportArtefact
constraint error in LayoutPage "page1": expected array format [value1,value2,...], got "pdf"
  constraint: spec.format in pdf
  hint: use array syntax like [value1,value2] for 'in' and 'not-in' operators
  • ReportArtefact documents cannot have constraints (they define the context, not consume it)
  • Only top-level and nested spec fields are accessible; arrays are not traversable
  • All constraints in a list must pass (AND logic); OR logic requires multiple documents
  1. Use labels for logical groupings: Define labels like env, region, or variant on artefacts rather than relying solely on spec fields
  2. Keep constraints simple: Complex filtering logic is hard to debug; prefer clear, single-purpose constraints
  3. Use in for multiple values: Instead of multiple documents, use labels.env in [dev,staging] to match multiple values
  4. Document your constraints: Add comments explaining why a constraint exists, especially for non-obvious cases
  5. Test with preview first: Use bino preview to verify constraint behavior before building
  6. Avoid duplicate names when possible: Even though scoped names are supported, unique names reduce confusion
  7. Choose format consistently: Pick string or structured format for your project and use it consistently