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¶
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.
useSyncExternalStorehandles 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:
- Read
types.tsto understand the data model. - Read
store.tsto understand state management. - Read
effects.tsto understand side effects. - Read
events.tsto understand user interactions. - Read
react.tsxto understand React integration.
No black boxes. No framework internals to learn.