Overview
The Pages module contains 691 lazy-loaded route components representing every feature in RAGFlow: from the visual agent editor to chat, search, dataset management, and admin panels. Each page is self-contained and fetches its own data via React Query hooks.
📑 Major Page Groups
Agent Canvas Editor
src/pages/agent/ — Visual graph editor for agent DSL
Chat Interface
src/pages/next-chats/ — Real-time streaming responses
index.tsx— Chat list & message thread view- Server-Sent Events (SSE) for streaming
- Optimistic message updates (appear before server response)
- Message history cached by React Query
Semantic Search
src/pages/next-search/ — Vector similarity search
- Query input with semantic embedding
- Result cards with relevance scores
- Filters for document type, date range
- Paginated results (100+ docs per query)
Knowledge Base
src/pages/dataset/, chunk/ — File management
Document Viewer
src/pages/document-viewer/ — Multi-format rendering
- PDF, Word, plain text, HTML preview
- Syntax highlighting for code blocks
- Highlight & annotate text
- Render chunks within document
📂 Directory Structure
src/pages/
├── agent/ # Visual graph editor
│ ├── index.tsx
│ ├── store.ts
│ └── utils/
├── next-chats/ # Chat interface
│ ├── index.tsx
│ ├── ChatList.tsx
│ └── ChatThread.tsx
├── next-search/ # Semantic search
├── dataset/ # KB management
├── chunk/ # Chunk viewer
├── document-viewer/ # PDF/doc preview
├── memory/ # Memory settings
├── user-setting/ # User profile
├── admin/ # Admin panel
└── login/ # Auth entry point
🔄 Data Fetching Pattern
All pages follow the same pattern:
- Page component mounts
- Calls custom hook (e.g.,
useAgentRequest()) which wraps React Query - Hook returns cached data or initiates fetch
- Component renders; React Query handles refetch on focus/stale time
- Mutations (create/update) trigger invalidation → auto-refetch
⚡ Code Splitting Strategy
Vite's rollupOptions in vite.config.ts manually chunks pages by feature:
- agent-chunk: agent/ pages + @xyflow/react (largest)
- chat-chunk: next-chats/ + EventSource logic
- search-chunk: next-search/ + semantic embedding
- admin-chunk: admin/ + user pages
Each chunk is lazy-loaded on route navigation. Shared dependencies (React, Zustand, etc.) in vendor.js.
🧪 Testing Pages
Most pages tested via E2E (Cypress/Playwright) due to complexity of canvas state. Unit tests focus on:
- Service integration (mocked React Query)
- Form validation & submission
- Event handlers (drag-drop, search filters)
Common Issues & Solutions
| Issue | Root Cause | Solution |
|---|---|---|
| Canvas doesn't render nodes | Zustand store not initialized | Call store.loadAgent(agentId) in useEffect |
| Chat messages don't stream | EventSource not opened | Check Content-Type header is text/event-stream |
| Search results stale | React Query cache not invalidated | Call queryClient.invalidateQueries('search') after mutation |
Next Steps
- Explore Components for UI building blocks
- Explore Services for REST API integration
- Deep-dive: Agent Canvas Editor for graph editing mechanics
Pages Module/{{SUBMOD_NAME}}/ — {{SUBMOD_TITLE}}
{{SUBMOD_PURPOSE}}
{{SUBMOD_DESC}}
📚 What is this & why does it exist?
{{SUBMOD_WHAT_WHY}} — Replace with 2-4 plain-English sentences explaining what this sub-module does and why it exists. No jargon. Target audience: someone who hasn't read the code.
💡 Real-world analogy
{{SUBMOD_ANALOGY}} — Replace with a vivid, concrete metaphor mapping this sub-module's core concept to everyday life (restaurant, airport, library, highway, etc.). 3-5 sentences.
🤔 Why Is It Designed This Way?
{{DESIGN_RATIONALE}} — 150+ words explaining the design choices: what pattern does this follow and why? What constraints shaped the implementation? What trade-offs were made and what was sacrificed?
| Design Choice | What Was Chosen | What Was Rejected | Why |
|---|---|---|---|
| Example: data layout | Array of structs | Struct of arrays | Random access pattern dominates; cache locality for single items matters more than SIMD sweeps |
Contents
Architecture
flowchart TD A["Component A"] --> B["Component B"] B --> C["Component C"] C --> D["Component D"]
Key Classes
| Class / Function | File | Purpose |
|---|---|---|
ClassName | file.h | Brief description |
Data Structures
| Type | Name | Description |
|---|---|---|
| enum | EnumName | Brief description |
Interactions
| Direction | Partner | Interface | Description |
|---|---|---|---|
| → | Other Module | methodName() | Brief description |
Configuration
| Knob / Parameter | Default | Description |
|---|---|---|
param_name | value | What it controls |
Directory Map
Source tree for {{SUBMOD_NAME}}
submod_name/
├── file_a.ext ← Role: brief annotation
├── file_b.ext ← Role: brief annotation
├── file_c.ext ← Role: brief annotation
└── index.ext ← Role: entry point
📑 Annotated Code Walkthrough
The most important code in this sub-module, annotated with WHY each piece exists:
{{KEY_FUNCTION_NAME}}
// Replace with actual code from the source
void key_function() {
// ← WHY: Explain the purpose of this line
// ← WHY: What constraint or requirement drives this?
}
Line-by-line:
- Line N: What this does and WHY — what would break if removed
- Line M: The design choice here — why this approach over the obvious alternative
⚠️ Edge Cases & Boundaries
| Edge Case | What Happens | Where in Code | Risk Level |
|---|---|---|---|
| Empty input | How it's handled | function_name:line | 🟢 Low |
| Concurrent access | How it's handled | function_name:line | 🔴 High |
Deep-Dive Highlights
Core mechanisms from this sub-module have been extracted into dedicated focus pages for in-depth exploration. Each page covers one algorithm, protocol, or subsystem with diagrams, code walks, and configuration details.
Deep-Dive Pages
Topic A Name Focus
Short description of what this focus page covers.
Topic B Name Focus
Short description of what this focus page covers.
Code Examples
Example: Typical Usage
// Replace with actual code example
void example() {
// ...
}