Skip to content

Chart Object Model

This page names the chart objects and layers in the Dataface compile-to-render pipeline.

Use it when you need to answer questions like:

  1. What object am I looking at right now?
  2. Which layer owns this field or decision?
  3. Where does the final Vega-Lite spec actually come from?

For ownership rules and architectural constraints, also read Chart Rendering Architecture.

Terminology:

  • style is the authored presentation surface at both board and chart level
  • named reusable presets live in defaults yaml and are referenced through style.extends

Layer Summary

The chart pipeline has seven layers:

  1. Authored config layer
  2. Typed style preset and patch layer
  3. Compiled board style layer
  4. Compiled and resolved chart layer
  5. Style-to-renderer mapping layer
  6. Chart profile mapping layer
  7. Emitter / final spec layer

Object Stack

1. Authored Config Layer

This is the raw source material the user writes or built-in defaults provide.

  • Board or face YAML
  • layout
  • face-level style
  • chart definitions
  • chart-level style
  • Defaults YAML
  • style defaults
  • built-in style presets
  • palettes
  • user dataface.yml

This layer owns authored intent and defaults source material. It does not own the final runtime shape.

2. Typed Style Preset And Patch Layer

This is the typed style layer used during compile.

Key objects:

  • shared nested style primitives (live authored surfaces in style.py)
  • TitleStyle
  • RangeStyle
  • ScaleStyle
  • per-chart-type Compiled*StylePatch (generated via build_patch_model in style_model.py)
  • CompiledBarStylePatch, CompiledLineStylePatch, CompiledAreaStylePatch, ...
  • CompiledAxisStylePatch, CompiledLegendStylePatch, CompiledInferenceStylePatch
  • CompiledTableStylePatch, CompiledKpiStylePatch, CompiledSparkBarStylePatch, ...
  • ChartStylePatch
  • chart-local authored overlay; all fields Optional
  • style presets
  • named StylePatch collections
  • VegaLiteConfig
  • the Vega-Lite-facing output model built from the same shared primitives

This layer is where authored style input becomes typed patch input.

3. Compiled Board Style Layer

This is the authoritative shared compiled style object for one board or face.

Key objects:

  • StyleCompiled
  • required compiled style object
  • includes chart-facing style sections Dataface owns
  • includes chart inference defaults under style.charts.inference
  • includes non-Vega chart sections such as style.charts.table and style.charts.kpi
  • may include other presentation sections such as style.markdown
  • CompiledFace
  • compiled layout and nested-face structure
  • selected style preset name, if any
  • board-scoped compiled style context

This layer is produced from:

  • style preset referenced by style.extends
  • board style patch
  • inherited parent board style if nested
  • global style defaults

Why this is board-scoped instead of chart-level:

  • avoids duplicating the same defaults on every chart
  • matches nested face inheritance
  • keeps style precedence attached to the containing face

4. Compiled And Resolved Chart Layer

There are really three chart objects here.

  • ChartPatch
  • sparse authored chart input model
  • the thing board YAML should validate into first
  • optional by default where authored input is sparse
  • CompiledChart
  • normalized authored chart contract
  • fields like x, y, color, mark, encoding, config
  • chart-level style patch if present
  • still chart-definition-shaped
  • ResolvedChart
  • the data-aware chart object used by render
  • semantically resolved chart type and channels
  • effective chart style view
  • enriched only where fields were still unresolved

The boundary is:

  • ChartPatch is authored input validation shape
  • CompiledChart is compile output
  • ResolvedChart is chart-pipeline output

This layer is where chart semantics become render-ready.

The style rule is:

  • if a chart has no local style, it should reuse the board-scoped StyleCompiled directly
  • if a chart has local style, the pipeline should produce one effective chart style view for that chart
  • renderer code should consume that effective chart style view instead of repeating chart.style or face.style logic

5. Style-To-Renderer Mapping Layer

This is the explicit mapping seam between Dataface compiled style and renderer targets.

Key objects:

  • VegaLiteConfig
  • renderer-target config produced from StyleCompiled

Key function:

  • style_to_vega_lite(style: StyleCompiled) -> VegaLiteConfig (implemented in dataface/core/compile/style.py)

This layer owns:

  • naming differences between Dataface style and Vega-Lite config
  • dropping non-Vega chart sections before Vega-Lite emission
  • explicit field-by-field renderer mapping
  • any narrow renderer-specific style translation Dataface chooses to own

It should not own chart semantics.

6. Chart Profile Mapping Layer

This is the seam between Dataface chart meaning and renderer-specific chart structures.

Key objects:

  • MappedChart
  • mark
  • encoding
  • optional measured hints like label_width

Key module:

  • dataface/core/render/chart/profile.py

This layer owns mechanical chart-to-renderer translation, not style precedence.

7. Emitter / Final Spec Layer

This is the mechanical spec assembly layer.

Key modules:

  • dataface/core/render/chart/standard_renderer.py
  • dataface/core/render/chart/vega_lite_types.py
  • dataface/core/render/chart/geo.py

This layer takes:

  • ResolvedChart
  • MappedChart or geo-specific mapped state
  • effective chart style view
  • mapped VegaLiteConfig
  • data rows

and produces:

  • final Vega-Lite spec dict
  • or direct SVG-family output for non-Vega families

This layer should assemble, not reinterpret.

End-To-End Creation Flow

flowchart TD
    authored["Authored board YAML<br/>style + charts"]
    defaults["Defaults YAML<br/>style defaults + style presets + palettes + user config"]
    patches["Typed style patch layer<br/>shared primitives + StylePatch"]
    chart_patch["ChartPatch<br/>sparse authored chart input"]
    board_style["Board-scoped compiled style<br/>StyleCompiled"]
    compiled_chart["CompiledChart"]
    resolved_chart["ResolvedChart<br/>includes effective chart style view"]
    style_map["style_to_vega_lite<br/>StyleCompiled -> VegaLiteConfig"]
    chart_map["MappedChart<br/>chart semantic mapping"]
    geo_exception["Geo exception path<br/>projection + lookup + topojson contract"]
    emitter["Emitter layer<br/>standard_renderer / vega_lite_types / geo"]
    final_spec["Final Vega-Lite spec"]

    authored --> chart_patch
    authored --> patches
    defaults --> patches
    patches --> board_style
    chart_patch --> compiled_chart
    board_style --> style_map
    compiled_chart --> resolved_chart
    resolved_chart --> chart_map
    chart_map --> emitter
    style_map --> emitter
    resolved_chart -->|"geo families only"| geo_exception
    geo_exception --> emitter
    emitter --> final_spec

Nested Object View

Another useful mental model is to nest the objects by ownership:

  • Style system
  • shared nested style primitives
  • StylePatch
  • StyleCompiled
  • VegaLiteConfig
  • Face system
  • CompiledFace
  • Chart system
  • ChartPatch
  • CompiledChart
  • ResolvedChart
  • MappedChart
  • Final output system
  • Vega-Lite spec dict
  • SVG artifact for non-Vega families

Practical Rule Of Thumb

If you are touching a chart field or decision, ask which object should own it:

  • raw YAML or defaults source value:
  • authored/config layer
  • typed style patch or style preset:
  • StylePatch
  • sparse authored chart contract:
  • ChartPatch
  • shared compiled style for a board:
  • StyleCompiled
  • normalized chart contract:
  • CompiledChart
  • data-aware semantic resolution:
  • ResolvedChart
  • Dataface style to Vega-Lite config translation:
  • style_to_vega_lite
  • chart profile mapping (mechanical translation):
  • MappedChart in profile.py
  • final spec assembly:
  • emitter layer

If a change skips upward or downward across these boundaries, it probably needs more scrutiny.

Defaults Taxonomy

Most defaults that affect presentation should live in StyleCompiled.

The groups are:

Style Defaults

These become part of StyleCompiled.

Examples:

  • axis, title, legend, and mark styling
  • typography
  • palettes
  • board visual defaults
  • chart sizing and spacing defaults
  • chart inference defaults such as style.charts.inference
  • non-Vega chart sections like style.charts.table and style.charts.kpi
  • other presentation sections like style.markdown

Chart Semantic Defaults

These belong with chart contracts and chart resolution, not with style.

Examples:

  • unresolved type: auto
  • inferred field roles
  • inferred scale behavior
  • semantic sort, stack, and encoding decisions

Non-Style Engine Defaults

These should stay outside style and remain small.

Examples:

  • query and execution behavior
  • non-presentation runtime policy

Vega-Lite Defaults

These remain upstream Vega-Lite behavior for any field Dataface does not explicitly own.

Dataface does not need to materialize every Vega-Lite default in its own style model.