Frontend Architecture Guide
UI Components Pattern
React Component Structure
// AgentCard.jsx
export const AgentCard = ({ agent, onSelect }) => {
const [isActive, setIsActive] = useState(false);
return (
<div
className={`agent-card ${isActive ? 'active' : ''}`}
onClick={() => {
setIsActive(!isActive);
onSelect(agent.id);
}}
>
<Avatar src={agent.avatar} alt={agent.name} />
<div className="agent-info">
<h3>{agent.name}</h3>
<p>{agent.role}</p>
<StatusBadge status={agent.status} />
</div>
</div>
);
};
Styling with CSS Modules
/* AgentCard.module.css */
.agent-card {
display: flex;
align-items: center;
padding: 1rem;
border: 2px solid #e2e8f0;
border-radius: 0.75rem;
cursor: pointer;
transition: all 0.2s ease;
}
.agent-card.active {
border-color: #3b82f6;
background-color: #eff6ff;
}
.agent-info {
margin-left: 1rem;
}
State Management Pattern
Zustand Store for Agents
// agentsStore.js
import { create } from 'zustand';
const useAgentsStore = create((set) => ({
agents: [],
selectedAgentId: null,
fetchAgents: async () => {
const response = await fetch('/api/agents');
const agents = await response.json();
set({ agents });
},
selectAgent: (id) => set({ selectedAgentId: id }),
updateAgentStatus: (agentId, status) =>
set((state) => ({
agents: state.agents.map(agent =>
agent.id === agentId ? { ...agent, status } : agent
)
})),
}));
API Integration Pattern
Service Layer with Error Handling
// agentService.js
export const agentService = {
async getAgents() {
try {
const response = await fetch('/api/agents', {
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Failed to fetch agents:', error);
throw error;
}
},
async createAgent(agentData) {
const response = await fetch('/api/agents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(agentData),
});
return response.json();
},
};
Best Practices
- Component Composition: Break down complex UIs into reusable components
- State Colocation: Keep state as close as possible to where it's used
- Error Boundaries: Wrap API calls in try-catch blocks with user feedback
- Performance: Use React.memo for expensive components, implement virtualization for long lists