Skip to content

FEAT: Switch default frontend to Next.js app - #5111

Merged
qinxuye merged 7 commits into
xorbitsai:mainfrom
OliverBryant:codex/use-new-frontend
Jul 8, 2026
Merged

FEAT: Switch default frontend to Next.js app#5111
qinxuye merged 7 commits into
xorbitsai:mainfrom
OliverBryant:codex/use-new-frontend

Conversation

@OliverBryant

@OliverBryant OliverBryant commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

What & why

Switch the default web UI to the Next.js app under frontend/, shipped as a static export bundled into the xinference package and served by the backend itself — single process, no Node runtime needed at runtime. pip install xinference gives the full product again, same as the old CRA UI. This follows the approach used in xagent#732.

How it works

Frontend (static export)

  • next.config.ts: output mode is env-driven — builds default to export; NEXT_OUTPUT=standalone keeps the Node server; next dev sets none (export would break dynamic routes in dev). Rewrites (the dev API proxy) only apply outside export mode; in production the UI is same-origin with the API.
  • Dynamic routes (launch-model/[modelType], register-model/[modelType], register-model/[modelType]/[modelName], running-model/[modelUid]) are split into a server wrapper (generateStaticParams emits a __shell__ placeholder page) + a client page that reads real params from the URL (useParams/useSearchParams in Suspense).
  • layout.tsx drops request-time cookies()/headers() and the server-side cluster-auth fetch; AppInit now resolves /v1/cluster/auth client-side, and I18nProvider falls back to the browser language on first visit.
  • Root / redirects to /launch-model client-side (server redirect()/config redirects are unsupported in export).

Backend (xinference/api/frontend_static.py)

  • mount_frontend() serves /_next assets plus a SPA catch-all that reconstructs the route table from the export's __shell__ files, serves RSC .txt prefetch payloads, guards path traversal, returns JSON 404 for unmatched API prefixes (derived from the live route table), and redirects legacy /ui/ to /. No-op when the export is absent (API-only).
  • ensure_spa_fallback_last() keeps the catch-all at the end of the route table so runtime Gradio mounts at /{model_uid} are not shadowed.
  • Replaces the previous XINFERENCE_FRONTEND_ENDPOINT redirect; override the export location with XINFERENCE_FRONTEND_DIST_DIR if needed.

Packaging

  • npm run build stages the export at xinference/ui/web/dist via a postbuild hook; setup.py build_web (hooked on install/develop/sdist, as before) runs npm and asserts the staged output. MANIFEST grafts the staged dist, so wheels/sdists are self-contained. Docker flows are unchanged (python setup.py build_web still works; the staged dist is untracked so git restore . keeps it).

CI & tests

  • Lint job: ESLint → next build (static export) → verify out/ shape (index.html, 404.html, __shell__ pages) → serve the real export through FastAPI and run the routing tests.
  • xinference/api/tests/test_frontend_static.py: unit tests on a synthetic export (no Node needed) — shell pattern building, backend-prefix 404s, RSC payloads, traversal rejection, Gradio-mount reordering.
  • xinference/api/tests/test_frontend_static_real_export.py: integration tests against the real frontend/out (skipped when not built).

Verification

  • Static export build: 19/19 routes, all 4 dynamic routes emit __shell__ shells; postbuild staging works.
  • 37/37 backend tests pass (also with --noconftest, as the CI lint job runs them).
  • Built a wheel locally: all 90 export files included under xinference/ui/web/dist.
  • pre-commit (black/flake8/isort/mypy/codespell) passes; ESLint 0 errors.

Notes

  • The old CRA app under xinference/ui/web/ui is untouched here; it can be removed in a follow-up.
  • next@15.2.3 has a published advisory (CVE-2025-66478); worth bumping in a follow-up.

@XprobeBot XprobeBot added this to the v2.x milestone Jul 1, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the Xinference Web UI to a separate Next.js application in the frontend/ directory, updating the build process, Dockerfiles, and documentation accordingly. Feedback points out a critical bug where the Switch component's state handler was incorrectly changed to onChange, and suggests several improvements: defaulting the backend redirect to the local frontend port, removing the web build step from standard Python installations to save time, excluding Next.js build artifacts from MANIFEST.in, and stripping trailing slashes from API URLs to prevent routing issues.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread xinference/api/restful_api.py Outdated
Comment thread setup.py
Comment thread MANIFEST.in Outdated
Comment thread frontend/next.config.ts Outdated
Comment thread frontend/src/lib/utils.ts Outdated
OliverBryant and others added 6 commits July 8, 2026 15:58
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Rework the frontend switch to a single-process deployment, following the
approach used in xagent#732:

- next.config: env-driven output (default static export; NEXT_OUTPUT=standalone
  keeps the Node server; dev mode sets none). Rewrites are dev/standalone only.
- Dynamic routes split into server wrappers (generateStaticParams __shell__
  placeholder) + client pages reading params from the URL.
- layout drops request-time cookies()/headers() and server-side cluster auth
  fetch; AppInit resolves cluster auth client-side, I18nProvider falls back to
  the browser language.
- New xinference/api/frontend_static.py serves the export from FastAPI:
  /_next assets, SPA catch-all with __shell__ route table, RSC .txt payloads,
  JSON 404 for unmatched API prefixes, /ui legacy redirect, and
  ensure_spa_fallback_last() so runtime Gradio mounts are not shadowed.
- Packaging: npm postbuild stages the export at xinference/ui/web/dist, which
  ships in the wheel/sdist; build_web hooks restored for install/develop/sdist.
- Tests: synthetic-export unit tests plus real-export integration tests; CI
  lint job builds the export, verifies its shape, and serves it through the
  backend.
@OliverBryant
OliverBryant force-pushed the codex/use-new-frontend branch from ecd0c23 to 88bd676 Compare July 8, 2026 08:01
@OliverBryant

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@OliverBryant

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request transitions the web UI to a Next.js static export served directly by the FastAPI backend, moving the source code to the frontend/ directory and updating build scripts, Dockerfiles, and documentation. It introduces a backend module to handle SPA routing, dynamic route shells, and static assets. The review feedback identifies three key issues: a bug in launch-dialog.tsx where using onChange instead of onCheckedChange on the Switch component breaks state updates, a routing issue in frontend_static.py where trailing slashes can cause 404 errors, and a potential build-time exception in i18n-context.tsx from accessing navigator during static pre-rendering.

Comment thread xinference/api/frontend_static.py
Comment thread frontend/src/contexts/i18n-context.tsx Outdated
- frontend_static: strip trailing slash before route lookup so
  /running-model/<uid>/ and /launch-model/ resolve like their
  no-slash form instead of 404ing.
- i18n-context: guard the browser-language fallback with a
  typeof navigator check instead of relying on the try/catch.

The other gemini comments (Switch onChange, frontend_endpoint default,
CustomInstall/CustomDevelop build_web hooks, MANIFEST.in artifacts,
trailing-slash stripping in next.config/getApiUrl) target the
pre-rework code and no longer apply.
@OliverBryant

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request restructures the Xinference web UI into a Next.js static export under the frontend/ directory, which is staged at xinference/ui/web/dist and served directly by the FastAPI backend, removing the Node.js runtime dependency in production. It adds SPA routing fallback logic in the backend, updates Dockerfiles to Node.js 20.19.0, and transitions server-side layout logic to client-side initialization. The review feedback correctly identifies a bug in launch-dialog.tsx where changing onCheckedChange to onChange on a Radix UI Switch component will cause TypeScript compilation errors and break functionality.

@qinxuye qinxuye left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@qinxuye
qinxuye merged commit 9db0e32 into xorbitsai:main Jul 8, 2026
11 of 12 checks passed
OliverBryant added a commit to OliverBryant/inference that referenced this pull request Jul 8, 2026
…fault

The old xinference/ui/web/ui frontend was fully superseded by the
Next.js app under frontend/ (xorbitsai#5111), which is already wired into the
build, packaging, and serving pipeline. Removing the unused directory
and updating AGENTS.md to point at the current frontend.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants