How BotContext Manages Bot State in the y-gui React Frontend

The y-gui frontend centralizes bot state management through a React context provider that fetches available bots from the backend, tracks the currently selected bot, and exposes setter functions to components throughout the application.

The y-gui repository implements a dedicated React context to manage bot state across its frontend application. This BotContext pattern ensures that bot configurations, selection state, and update mechanisms remain accessible to any component in the component tree without prop drilling.

BotContext Architecture and Data Flow

The state management architecture centers on the BotProvider component defined in frontend/src/contexts/BotContext.tsx. This provider encapsulates both the data fetching logic and the local state for tracking user selection.

Fetching Bot Configurations from the Backend

The provider initializes bot data by calling the /api/bots endpoint through the useAuthenticatedSWR hook. This returns an array of BotConfig objects representing all available bots configured in the system.

// From frontend/src/contexts/BotContext.tsx
const { data, isLoading } = useAuthenticatedSWR<BotConfig[]>('/api/bots');

The hook handles authentication headers and caching automatically, ensuring components receive fresh data while minimizing redundant network requests.

Tracking the Currently Selected Bot

Within the provider, a selectedBot state variable stores the currently active bot identifier as a string | undefined. The implementation automatically selects the first available bot when the data loads initially:

// From frontend/src/contexts/BotContext.tsx
useEffect(() => {
  if (data && data.length > 0 && !selectedBot) {
    setSelectedBot(data[0].name);
  }
}, [data, selectedBot]);

The setSelectedBot dispatcher is exposed through the context value, allowing descendant components to update the active bot programmatically.

Consuming and Updating Bot State in Components

Components throughout the y-gui application access bot state through the useBot custom hook, which provides type-safe access to the context value.

The useBot Hook for Safe Context Access

The useBot hook wraps React's useContext and enforces that components can only access bot state when rendered within a BotProvider:

// From frontend/src/contexts/BotContext.tsx
export function useBot() {
  const context = useContext(BotContext);
  if (context === undefined) {
    throw new Error('useBot must be used within a BotProvider');
  }
  return context;
}

This pattern prevents runtime errors and ensures developers receive immediate feedback when attempting to use bot state outside the provider hierarchy.

Persisting Bot Selection Per Chat

The MessageInput component implements per-chat persistence by synchronizing the selected bot to localStorage. This ensures that when users navigate between different chat sessions, each maintains its own bot preference.

// From frontend/src/components/MessageInput.tsx
useEffect(() => {
  const savedBot = localStorage.getItem(`chat_${chatId}_selectedBot`);
  if (savedBot) {
    setSelectedBot(savedBot);
  } else if (bots?.length) {
    setSelectedBot(bots[0].name);
  }
}, [bots, chatId]);

useEffect(() => {
  if (selectedBot) {
    localStorage.setItem(`chat_${chatId}_selectedBot`, selectedBot);
  }
}, [selectedBot, chatId]);

The storage key follows the pattern chat_<id>_selectedBot, isolating preferences between different conversation threads.

CRUD Operations and State Refresh

The BotSection component in the Settings page manages bot lifecycle operations. After creating, updating, or deleting bots through the backend API, it triggers a context refresh to update the global state.

// From frontend/src/components/Settings/BotSection.tsx
const { data: bots, mutate: mutateBots } = useAuthenticatedSWR<BotConfig[]>('/api/bots');

// After mutation
await api.post('/api/bot', newBot);
mutateBots();  // Refetches /api/bots, updating BotContext automatically

The mutateBots function invalidates the SWR cache and re-fetches the bot list, ensuring that BotContext receives the updated data and propagates changes to all consuming components.

Summary

  • BotContext centralizes bot state in frontend/src/contexts/BotContext.tsx, providing a single source of truth for available bots and the current selection.
  • The BotProvider fetches bot configurations from /api/bots using useAuthenticatedSWR and automatically selects the first bot on initial load.
  • Components access state through the useBot hook, which enforces provider boundaries and prevents undefined context errors.
  • Per-chat persistence is implemented in MessageInput using localStorage keys formatted as chat_<id>_selectedBot.
  • CRUD operations in BotSection trigger SWR mutations to refresh the global bot list and maintain synchronization across the application.

Frequently Asked Questions

How does BotContext handle authentication when fetching bots?

The context uses the useAuthenticatedSWR hook, which automatically includes authentication headers in the request to /api/bots. This ensures that only authorized users can retrieve the bot configuration list, and the hook handles token management and request deduplication.

What happens if no bots are configured in the backend?

If the /api/bots endpoint returns an empty array, the selectedBot state remains undefined. Components consuming the context should handle this case by disabling bot-dependent features or displaying empty states. The isLoading flag from SWR helps distinguish between loading and empty states.

Can multiple components modify the selected bot simultaneously?

Yes, any component that calls useBot() receives the setSelectedBot dispatcher. When invoked, it updates the context value, triggering a re-render of all components that consume the context. This pattern ensures UI consistency across the application without prop drilling.

How is the bot selection persisted across page refreshes?

While BotContext itself does not persist state to storage, consuming components like MessageInput implement persistence by writing the selected bot to localStorage using chat-specific keys (chat_<id>_selectedBot). On component mount, these components read from localStorage and call setSelectedBot to restore the previous selection.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →