Skip to content

Code Generation

HBIA generates a self-contained TypeScript runtime from your frontend YAML definitions. No Redux, no Zustand, no external state management library — the generated code is the runtime.

Overview

The FrontendCodegen reads your FrontendDomain objects and produces a complete set of TypeScript files:

from honey_badgeria.front.codegen import FrontendCodegen

codegen = FrontendCodegen(domains=[dashboard_domain, auth_domain])
generated_files = codegen.generate(output_dir="front/hbia-runtime")

CLI

hbia ui-codegen graph/ --output hbia-runtime/

Generated Files

hbia-runtime/
├── types.ts       # TypeScript interfaces from state definitions
├── store.ts       # Central pub/sub state store
├── effects.ts     # Effect watcher system
├── events.ts      # Event dispatcher
├── react.tsx      # React hooks & Provider component
└── index.ts       # Re-exports everything

types.ts

One interface per state node, plus an aggregate state type:

// Generated from FilterState/state.yaml
export interface FilterStateData {
  dateRange: DateRange;
  region: string;
  category: string;
}

// Generated from ChartState/state.yaml
export interface ChartStateData {
  series: ChartSeries[];
  loading: boolean;
}

// Aggregate state (all domains combined)
export interface HBIAState {
  FilterState: FilterStateData;
  ChartState: ChartStateData;
}

// Event payloads
export interface RefreshChartPayload {
  [key: string]: unknown;
}

store.ts

A central pub/sub state store:

class HBIAStore {
  private state: HBIAState;
  private listeners: Set<Listener> = new Set();

  // Subscribe to state changes
  subscribe(listener: Listener): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  // Get current state snapshot
  getSnapshot(): HBIAState {
    return this.state;
  }

  // Dispatch a mutation
  dispatch(mutation: string, payload: unknown): void {
    // Apply mutation to state
    // Notify all listeners
  }
}

Mutations are dispatched by name. The store applies the mutation, updates the state, and notifies all listeners.

effects.ts

The effect watcher system. Connects state changes to effect handlers:

// Watches FilterState.dateRange and FilterState.region
// When either changes, runs the handler after 300ms debounce
function watchFetchChartData(store: HBIAStore) {
  // Set up watchers based on effect.yaml definitions
  // Debounce if debounce_ms is configured
  // After handler runs, dispatch mutations to mutates targets
}

events.ts

Event dispatcher. Maps user events to mutation sequences:

// Generated from events/refresh_chart.yaml
function dispatchRefreshChart(store: HBIAStore, payload?: unknown): void {
  // Check guards: is_not_loading
  // Execute flow in order:
  //   1. store.dispatch("ChartState.set_loading", payload)
  //   2. store.dispatch("FilterState.reset_filters", payload)
}

react.tsx

React integration via useSyncExternalStore:

import { useSyncExternalStore } from 'react';

// Hook for reading state
export function useHBIAState<T>(selector: (s: HBIAState) => T): T {
  return useSyncExternalStore(
    store.subscribe.bind(store),
    () => selector(store.getSnapshot())
  );
}

// Provider wraps your app
export const HBIAProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  <HBIAContext.Provider value={store}>
    {children}
  </HBIAContext.Provider>
);

index.ts

Re-exports everything for clean imports:

export * from './types';
export * from './store';
export * from './effects';
export * from './events';
export * from './react';

Usage in React

Setup

// app.tsx
import { HBIAProvider } from './hbia-runtime';

function App() {
  return (
    <HBIAProvider>
      <Dashboard />
    </HBIAProvider>
  );
}

Reading State

import { useHBIAState } from './hbia-runtime';

function ChartCanvas() {
  const series = useHBIAState(s => s.ChartState.series);
  const loading = useHBIAState(s => s.ChartState.loading);

  if (loading) return <Spinner />;
  return <Chart data={series} />;
}

Dispatching Events

import { dispatchRefreshChart } from './hbia-runtime';

function ChartHeader() {
  return (
    <button onClick={() => dispatchRefreshChart(store)}>
      Refresh
    </button>
  );
}

Design Decisions

No External Dependencies

The generated runtime uses only:

  • TypeScript (types)
  • useSyncExternalStore (React 18+ built-in)
  • React.createContext / useContext (standard React)

No Redux, no Zustand, no MobX, no Jotai. The generated code is the state management library.

Pub/Sub Over Reducers

Instead of action → reducer → new state (like Redux), HBIA uses pub/sub:

  • Mutations directly modify state.
  • Listeners are notified of changes.
  • useSyncExternalStore handles React re-rendering.

This is simpler, more direct, and easier for AI agents to understand.

Full Auditability

Every generated file is readable TypeScript. An AI agent can:

  1. Read types.ts to understand the data model.
  2. Read store.ts to understand state management.
  3. Read effects.ts to understand side effects.
  4. Read events.ts to understand user interactions.
  5. Read react.tsx to understand React integration.

No black boxes. No framework internals to learn.