Full-Stack Project¶
This tutorial walks through setting up a monorepo project with a FastAPI backend and a Next.js frontend, both powered by Honey Badgeria's architecture layer.
Scaffold the Monorepo¶
This creates:
my_app/
├── hbia.yaml # Root monorepo configuration
├── README.md
├── back/ # FastAPI + HBIA backend
│ ├── flows/ # YAML flow definitions
│ │ └── example_flow.yaml
│ ├── vertices/ # Python handlers
│ │ └── greetings.py
│ ├── tests/ # Backend tests
│ │ └── test_flow_example.py
│ ├── infra/ # Infrastructure (auth, etc.)
│ │ └── auth.py
│ ├── app.py # FastAPI application
│ ├── manage.py # Management script
│ ├── settings.py # Backend settings
│ ├── requirements.txt
│ ├── hbia.yaml
│ └── .env # Environment variables
├── front/ # Next.js + HBIA frontend
│ ├── app/ # Next.js App Router
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── globals.css
│ ├── graph/ # UI, State, Effect, Event YAMLs
│ │ └── counter/
│ │ ├── ui/
│ │ ├── state/
│ │ ├── effects/
│ │ └── events/
│ ├── primitives/ # Reusable UI components
│ ├── services/ # API service layer
│ ├── hbia-runtime/ # Generated TypeScript (from codegen)
│ ├── hbia.yaml
│ ├── package.json
│ ├── tsconfig.json
│ ├── next.config.ts
│ ├── tailwind.config.ts
│ └── postcss.config.js
└── AGENTS.md
Backend Setup¶
The backend follows the same patterns described in the FastAPI Integration tutorial. Define flows in YAML, implement handlers in Python, and HBIA generates REST endpoints.
Frontend Setup¶
The frontend uses HBIA's reactive graph system — a fundamentally different approach to frontend architecture.
The Four Graphs¶
Instead of building UIs with traditional component-based patterns where components own state, effects, and event handling, HBIA decomposes the frontend into four interconnected reactive graphs:
- UI Graph — Component hierarchy. Pure render functions with no hooks, no state, no effects.
- State Graph — State ownership. Typed fields, mutations, and effect triggers.
- Effect Graph — Side effects triggered by state changes or events.
- Event Graph — User interaction flows mapping to ordered mutation sequences.
The fundamental rule: Events → mutate State → trigger Effects → State drives UI.
Define a UI Component¶
# graph/dashboard/ui/Dashboard/dashboard_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
UI nodes are pure render functions. They:
- Read state via
reads(subscriptions) - Emit events via
events - Have
children(composing the component tree) - Never contain hooks, state management, or side effects
Define State¶
# graph/dashboard/state/FilterState/state.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:
region: '"all"'
category: '"all"'
State nodes declare:
fields— Typed data the state holds.mutations— Named operations that can modify the state.triggers— Effects that fire when this state changes.initial— Default field values.
Define Effects¶
# graph/dashboard/effects/fetch_chart_data/effect.yaml
effect: fetch_chart_data
watch:
- FilterState.dateRange
- FilterState.region
handler: handlers/fetch_chart_data
effect_type: side_effect
mutates:
- ChartState
debounce_ms: 300
Effects declare:
watch— State fields that trigger this effect when they change.on_event— Events that trigger this effect (alternative to watch).handler— Path to the handler implementation.effect_type—side_effect(API calls, etc.) orderived(computed state).mutates— Which state nodes this effect can write to.debounce_ms— Optional debounce in milliseconds.
Define Events¶
# graph/dashboard/events/refresh_chart.yaml
event: refresh_chart_event
flow:
- ChartState.set_loading
- FilterState.reset_filters
source: ChartHeader
guards:
- is_not_loading
Events declare:
flow— Ordered list of mutations to execute.source— Which UI component emits this event.guards— Conditions that must be true for the event to proceed.
Generate the TypeScript Runtime¶
Once your YAML definitions are complete, generate the runtime:
This generates:
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
└── index.ts # Re-exports
The generated runtime has:
- No external dependencies — pure TypeScript + React hooks.
- Pub/sub reactivity — state changes notify subscribers.
useSyncExternalStore— React integration via the standard React API.- Full auditability — every file is readable and inspectable by AI agents.
Use in React Components¶
import { useHBIAState, HBIAProvider } from './hbia-runtime';
// In your app root
function App() {
return (
<HBIAProvider>
<Dashboard />
</HBIAProvider>
);
}
// In a component
function Dashboard() {
const dateRange = useHBIAState(s => s.FilterState.dateRange);
const loading = useHBIAState(s => s.ChartState.loading);
// Pure render — no hooks for state management
return (
<div>
{loading ? <Spinner /> : <ChartCanvas />}
</div>
);
}
Frontend CLI Commands¶
# Inspect a UI graph
hbia ui-inspect graph/dashboard/
# Show graph structure
hbia ui-graph graph/dashboard/
# Validate YAML definitions
hbia ui-validate graph/
# Lint for best practices
hbia ui-lint graph/
# Generate TypeScript runtime
hbia ui-codegen graph/ --output hbia-runtime/
Running the Full Stack¶
Development¶
With Docker¶
What's Next?¶
For deeper dives into each system: