Skip to content

Frontend DSL Reference

This page documents the YAML format for all four frontend graph types.

Directory Structure

Each domain (logical section of the app) has a directory with four subdirectories:

graph/
  dashboard/
    ui/
      Dashboard/
        dashboard_node.yaml
        dashboard_view.tsx
      ChartHeader/
        header_node.yaml
        header_view.tsx
    state/
      FilterState/
        state.yaml
        interface.ts
        mutations.ts
      ChartState/
        state.yaml
        interface.ts
    effects/
      fetch_chart_data/
        effect.yaml
        handler.ts
    events/
      refresh_chart.yaml
      export_chart.yaml

UI Node YAML

component: Dashboard
view: dashboard_view
reads:
  - FilterState.dateRange
  - FilterState.region
  - ChartState.series
  - ChartState.loading
events:
  refresh: refresh_chart_event
  export: export_chart_event
children:
  - ChartHeader
  - ChartCanvas
  - ChartLegend
props:
  variant: full

Fields

Field Required Type Description
component Yes str Component name (PascalCase)
view Yes str View function/file identifier
reads No list[str] State field subscriptions (StateName.fieldName)
events No dict[str, str] Event bindings: {action: event_name}
children No list[str] Child component names
props No dict[str, str] Static properties

Naming Convention

  • Component names: PascalCase (e.g., Dashboard, ChartHeader)
  • View identifiers: snake_case (e.g., dashboard_view)

State Node YAML

state: FilterState
interface: FilterStateData
fields:
  dateRange: DateRange
  region: string
  category: string
mutations:
  - set_date_range
  - set_region
  - set_category
  - reset_filters
triggers:
  - fetch_chart_data
  - update_url_params
initial:
  dateRange: '{ start: null, end: null }'
  region: '"all"'
  category: '"all"'

Fields

Field Required Type Description
state Yes str State node name (PascalCase + "State")
interface Yes str TypeScript interface name
fields Yes dict[str, str] Field names → TypeScript types
mutations Yes list[str] Named mutation operations
triggers No list[str] Effects triggered on state change
initial No dict[str, str] Default values (quoted strings)

Field Types

Field types are TypeScript types:

fields:
  count: number
  name: string
  active: boolean
  items: Item[]
  config: Record<string, unknown>
  dateRange: DateRange          # Custom interface

Initial Values

Initial values are string representations of TypeScript values. Quote strings within the YAML:

initial:
  region: '"all"'                              # string literal
  count: '0'                                    # number
  active: 'true'                                # boolean
  items: '[]'                                   # empty array
  dateRange: '{ start: null, end: null }'       # object literal

Effect YAML

effect: fetch_chart_data
watch:
  - FilterState.dateRange
  - FilterState.region
on_event:
  - chart_refresh_clicked
handler: handlers/fetch_chart_data
effect_type: side_effect
mutates:
  - ChartState
  - NotificationState
debounce_ms: 300

Fields

Field Required Type Description
effect Yes str Effect identifier
watch No list[str] State fields that trigger this effect
on_event No list[str] Events that trigger this effect
handler Yes str Path to handler implementation
effect_type Yes str "side_effect" or "derived"
mutates No list[str] State nodes this effect can write to
debounce_ms No int Milliseconds to debounce

Note

At least one of watch or on_event must be provided. An effect with neither has no trigger and will never execute.

Effect Types

  • side_effect — Performs external operations (API calls, analytics, localStorage). Separated from state computation.
  • derived — Computes new state from existing state. Like a computed property, declared explicitly.

Event YAML

event: refresh_chart_event
flow:
  - ChartState.set_loading
  - FilterState.reset_filters
source: ChartHeader
guards:
  - is_not_loading
  - is_authenticated

Fields

Field Required Type Description
event Yes str Event identifier
flow Yes list[str] Ordered mutation sequence
source No str Component that emits this event
guards No list[str] Preconditions for execution

Flow Items

Each item in flow is either:

  • A mutation: StateName.mutation_name (e.g., ChartState.set_loading)
  • An effect trigger: effect_name (e.g., fetch_chart_data)

Items execute in the declared order.

Cross-Graph References

The four graphs reference each other through consistent naming:

UI reads → State fields        (e.g., "FilterState.dateRange")
UI emits → Events              (e.g., "refresh_chart_event")
Events dispatch → Mutations    (e.g., "FilterState.reset_filters")
State triggers → Effects       (e.g., "fetch_chart_data")
Effects watch → State fields   (e.g., "FilterState.region")
Effects mutate → State nodes   (e.g., "ChartState")

All references use the format NodeName.field_or_mutation where applicable. Validation checks that all cross-references resolve to actual nodes and fields.

Loading From Disk

from honey_badgeria.front.dsl import (
    load_ui_graph,
    load_state_graph,
    load_effect_graph,
    load_event_graph,
)
from honey_badgeria.front.graph import FrontendDomain

ui = load_ui_graph("graph/dashboard/ui/")
state = load_state_graph("graph/dashboard/state/")
effects = load_effect_graph("graph/dashboard/effects/")
events = load_event_graph("graph/dashboard/events/")

domain = FrontendDomain("dashboard", ui, state, effects, events)