- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
5.6 KiB
Frontend-Backend Alignment
This document describes the alignment between the frontend and the enhanced Go backend.
Architecture Overview
The frontend now communicates with the backend through:
- API Client Layer (
lib/api-client.ts): Base HTTP client with authentication - Service Layer (
services/*-api.ts): Type-safe API service functions - React Hooks (
hooks/api/*.ts): React Query hooks for data fetching and mutations - Backend Schemas (
schemas/backend/*.ts): Zod schemas matching backend domain models
API Endpoints
Authentication
POST /auth/login- JWT authentication
Organizations
GET /api/organizations- List all organizationsGET /api/organizations/:id- Get organization by IDPOST /api/organizations- Create organizationDELETE /api/organizations/:id- Delete organization
Sites
POST /api/sites- Create siteGET /api/sites/:id- Get site by IDGET /api/sites/business/:businessId- Get sites by businessGET /api/sites/nearby?lat=&lng=&radius=- Find sites within radiusDELETE /api/sites/:id- Delete site
Resource Flows
POST /api/resources- Create resource flowGET /api/resources/:id- Get resource flow by IDGET /api/resources/site/:siteId- Get flows by siteGET /api/resources/business/:businessId- Get flows by businessDELETE /api/resources/:id- Delete resource flow
Matching Engine
GET /api/matching/resource/:resourceId?max_distance_km=50&min_score=0.3&limit=20- Find matches for a resource
Data Models
Organization
- Simplified compared to frontend's previous model
- No embedded needs/offers (these are now separate ResourceFlow entities)
- Fields:
ID,Name,Sector,Description,LogoURL,Website,Address,Verified,CreatedAt,UpdatedAt
Site
- Represents a physical location
- Fields:
ID,Name,Address,Latitude,Longitude,SiteType,FloorAreaM2,OwnerBusinessID,CreatedAt,UpdatedAt
ResourceFlow
- Represents input/output resource flows
- Direction:
inputoroutput - Types:
heat,water,steam,CO2,biowaste,cooling,logistics,materials,service - Includes:
Quality,Quantity,TimeProfile,EconomicData,Constraints,ServiceDetails - Precision levels:
rough,estimated,measured - Source types:
declared,device,calculated
Match
- Represents a match between two resource flows
- Status:
suggested,negotiating,reserved,contracted,live,failed,cancelled - Includes:
CompatibilityScore,EconomicValue,DistanceKm,RiskAssessment,EconomicImpact,TransportationEstimate
Usage Examples
Using Organizations API
import { useOrganizations, useCreateOrganization } from '@/hooks/api';
function OrganizationsList() {
const { data: organizations, isLoading } = useOrganizations();
const createOrg = useCreateOrganization();
const handleCreate = async () => {
await createOrg.mutateAsync({
name: 'New Organization',
sector: '35.30',
description: 'Description',
});
};
// ...
}
Using Resource Flows API
import { useResourceFlowsByBusiness, useCreateResourceFlow } from '@/hooks/api';
function ResourceFlowsList({ businessId }: { businessId: string }) {
const { data: flows } = useResourceFlowsByBusiness(businessId);
const createFlow = useCreateResourceFlow();
const handleCreate = async () => {
await createFlow.mutateAsync({
business_id: businessId,
site_id: 'site-id',
direction: 'output',
type: 'heat',
quantity: {
amount: 500,
unit: 'kWh',
temporal_unit: 'per_hour',
},
quality: {
temperature_celsius: 65.0,
physical_state: 'liquid',
},
});
};
// ...
}
Using Matching API
import { useFindMatches } from '@/hooks/api';
function MatchesList({ resourceId }: { resourceId: string }) {
const { data: matchesData } = useFindMatches(resourceId, {
max_distance_km: 30,
min_score: 0.3,
limit: 10,
});
// matchesData.matches contains the array of matches
// matchesData.count contains the count
}
Authentication
The AuthContext has been updated to:
- Use the API client's
loginfunction - Decode JWT tokens to extract user information
- Store tokens in localStorage
- Automatically include Bearer tokens in API requests
Migration Notes
Breaking Changes
-
Organization Model: The frontend's previous organization model included embedded
needsandoffers. These are now separateResourceFlowentities that must be created independently. -
Field Naming: Backend uses Go's default JSON encoding (capitalized field names) for main structs, but snake_case for nested structs. The schemas reflect this.
-
Data Structure: Organizations no longer contain resource flows directly. Use
useResourceFlowsByBusiness(businessId)to fetch related resource flows.
Next Steps
- Update components that display organizations to use the new API hooks
- Create components for managing resource flows separately
- Implement match visualization and management UI
- Add error handling and loading states throughout
- Consider adding optimistic updates for better UX
Field Name Convention
Note: The backend Go structs use capitalized field names (Go's default JSON encoding) for main entities, but nested structs use snake_case JSON tags. The frontend schemas match this convention:
- Main struct fields:
ID,Name,Sector, etc. (capitalized) - Nested struct fields:
temperature_celsius,cost_in, etc. (snake_case)
If the actual API responses differ, adjust the schemas accordingly.