Frontend Build and Deployment#
RAGFlow's frontend is a React 18 / TypeScript application (web/CLAUDE.md) built with Vite as the bundler (web/package.json). The compiled SPA is served by nginx running inside the Docker production container.
Tech Stack#
| Concern | Library / Tool |
|---|---|
| Framework | React ^18.2.0 |
| Build | Vite ^7.2.7 |
| Language | TypeScript ^5.9.3 |
| UI primitives | Radix UI + shadcn/ui |
| Styling | Tailwind CSS ^3 |
| State | Zustand |
| Data fetching | TanStack Query ^5 |
| i18n | react-i18next |
Key constraint: Node.js ≥ 18.20.4 (enforced via engine-strict=true in web/.npmrc). The .npmrc also pins the registry to https://registry.npmmirror.com/ .
Docker Multi-Stage Build#
The Dockerfile uses three stages:
base(lines 1–183) — Ubuntu 24.04 with system deps, nginx, and Node.js 20.x installed via the NodeSource repo .builder(lines 187–243) — Installs npm dependencies, then compiles the frontend:package.json/package-lock.jsonare copied first so source changes don't bust the npm install cache layer .- Builds via
VITE_BUILD_SOURCEMAP=false VITE_MINIFY=esbuild npm run buildwithNODE_OPTIONS="--max-old-space-size=8192".
production(lines 246–287) — Inheritsbase(no build tools), then copies only the compiledweb/distfrombuilder.
For China CI, pass --build-arg NEED_MIRROR=1 to switch npm (and APT/PyPI) to Aliyun mirrors .
Local Development Workflow#
All commands run from the web/ directory :
npm install # install dependencies
npm run dev # Vite dev server with HMR
npm run build # production build → web/dist/
npm run lint # oxlint
npm run test # Jest with coverage
The Vite dev server proxies API calls to a running RAGFlow backend. Changes to source files are reflected immediately via HMR — no rebuild required. To see changes in a Docker deployment, you must npm run build and then rebuild/restart the container .
Common pitfall: Editing files under
web/src/and then accessing the running Docker container will show the old build. Always rebuild after source changes intended for production.
Nginx Configuration and SPA Routing#
At runtime, entrypoint.sh selects a nginx config variant based on the API_PROXY_SCHEME environment variable and copies it to /etc/nginx/conf.d/ragflow.conf before starting nginx .
API_PROXY_SCHEME value | Config used | Backend ports |
|---|---|---|
| (unset / default) | ragflow.conf.python | 9380 (API), 9381 (admin) |
python | ragflow.conf.python | 9380 (API), 9381 (admin) |
go | ragflow.conf.golang | 9384 (API/skills), 9383 (admin) |
hybrid | ragflow.conf.hybrid | Routes select endpoints to Python (9380/9381) and Go (9383/9384) |
All three variants share these traits :
- Serve static assets from
/ragflow/web/dist(nginxroot) - SPA routing:
try_files $uri $uri/ /index.htmlfalls back toindex.htmlfor client-side routing - Gzip compression enabled for JS, CSS, HTML, images
- Long-lived caching:
expires 10yfor/static/(css|js|media)/paths - Proxy API traffic (
/v1,/api) to the backend with shared settings fromproxy.conf(3600s timeouts, buffering disabled for streaming)
The top-level nginx.conf sets client_max_body_size 1024M to allow large file uploads and includes /etc/nginx/conf.d/ragflow.conf.
Key Files#
| File | Purpose |
|---|---|
Dockerfile | Three-stage build; frontend compiled in builder, copied to production |
web/package.json | npm scripts (dev, build, test, etc.) and dependency manifest |
web/.npmrc | Node engine requirement + npmmirror registry |
web/CLAUDE.md | Developer conventions: coding patterns, state management, network layers |
web/README.md | Quick-start: install, run dev server, access at :9222 |
docker/nginx/ragflow.conf.python | Default nginx config (Python backend) |
docker/nginx/ragflow.conf.golang | Nginx config for Go backend |
docker/nginx/ragflow.conf.hybrid | Nginx config for mixed Python+Go backends |
docker/entrypoint.sh | Selects nginx config at startup based on API_PROXY_SCHEME |