📦 Module Architecture
The web frontend is organized into self-contained layers. Each module handles a specific responsibility in the React component hierarchy and data flow.
Pages (691 files)
Lazy-loaded route components
Entire features: agent canvas editor, chat interface, semantic search, knowledge base, dataset management, document viewer, user settings, admin panels. Each page fetches its own data via React Query hooks.
agent/— Visual graph DSL editor (100+ node support)next-chats/— Real-time streaming chatnext-search/— Semantic search interfacedataset/,chunk/— Knowledge base managementdocument-viewer/— Multi-format document renderingmemory/,user-setting/,admin/— Supporting features
Components (252 files)
Shadcn-based UI primitives + custom RAGFlow components
Reusable building blocks: buttons, dialogs, forms, tabs, sliders, and graph-specific components (canvas nodes, xyflow wrappers, RagFlow form builder). Styled with Tailwind CSS; theme variables stored in localStorage.
ui/— Shadcn primitives (Dialog, Select, Accordion, etc.)canvas/— Graph editor nodes and edgesxyflow/— React Flow (v12) integration wrappersragflow-form/— Dynamic form builder for agent DSL
Services (14 files)
REST API client layer + React Query integration
Decoupled service wrappers for each backend endpoint. Each method returns a React Query useQuery/useMutation definition. Enables deduplication, caching, optimistic updates, and automatic refetch on focus.
agent-service— CRUD agent definitions, graph DSLchat-service— Send messages, stream responsesknowledge-service— File uploads, vector searchuser-service,admin-service— User & system management
🏗️ Data Flow Architecture
The frontend follows a predictable data flow: React Router → Page Component → Hooks (useQuery/useMutation) → Service Layer → REST API.
🔄 Narrated Walkthrough: Send a Chat Message
Trace how a user message flows through the system:
- User opens chat page → React Router lazy-loads
pages/next-chats/index.tsx - Page mounts → Calls
useChatRequest()(custom hook insrc/hooks/) - Hook wraps React Query →
useQuery("chat-history", () => chatService.fetchHistory()) - Service fetches →
chatService.tsmakes GET/api/v1/chats/history - Data cached → React Query stores in client-side cache; renders
ChatListcomponent - User types message → Triggers
onChangeevent in<ChatInput />component - User clicks send → Handler calls
useChatSendMutation.mutate({message}) - Mutation executed →
chatService.sendMessage()POSTs to/api/v1/chats/send - Optimistic update → Message immediately appears in UI (before server response)
- Server responds with EventSource → Streaming SSE connection opens; backend chunks response
- First chunk arrives →
EventSource.onmessagetriggered; chunk appended to message - Chunks stream in → React state updates incrementally (no full re-render); user sees real-time typing effect
- Stream ends → EventSource closes;
onclosefinalizes message in cache - Cache invalidated →
queryClient.invalidateQueries("chat-history")refetches latest state
🎨 Design Systems & Styling
Theme persistence: Dark/light mode toggle uses localStorage key neutra-ip-theme. ThemeProvider in src/app.tsx syncs theme across all routes on mount and refresh.
Localization: i18next with TypeScript namespaces in src/locales/ (en, zh, ja, ko, etc.). Loaded upfront (no lazy i18n); 16+ locales available. Language selector in user settings.
⚡ Performance Optimizations
- Code splitting: Vite's rollupOptions manually chunks by feature (agent, chat, search) + vendor groups
- Lazy routes: React.lazy() + Suspense defers page JS until route is visited
- Query deduplication: React Query avoids duplicate requests for same data within stale time
- Immer state updates: Zustand with Immer middleware enables efficient immutable updates (no manual spread)
- Memoization: useCallback/useMemo in hot paths (canvas rendering, large lists)
📊 Codebase Statistics
🔗 Cross-Module Connections
The Pages, Components, and Services modules are tightly integrated:
- Pages → Components: Import UI primitives from components/ (buttons, dialogs, forms)
- Pages → Services: Call service layer methods via useQuery/useMutation hooks
- Components → Services: Agent Canvas Canvas & Execution — Canvas & Execution" class="xref">Graph canvas components (xyflow/) fetch node definitions from services
- Hooks bridge everything: useAgentRequest(), useChatRequest(), useKnowledgeRequest() wrap service → React Query integration
🚀 Getting Started with Web Frontend
cd /path/to/ragflow/web
npm install
npm run dev # Starts Vite dev server on :9222
npm run build # Builds optimized bundles
npm run preview # Preview production build locally
npm run lint # Check code quality
Dev environment: http://localhost:9222; Vite auto-proxies backend API calls (see vite.config.ts proxy config).