Skip to content

feat: add subpath route support#60

Open
Airamhh wants to merge 4 commits into
ClickHouse:mainfrom
Airamhh:feat/subpath-routing-support
Open

feat: add subpath route support#60
Airamhh wants to merge 4 commits into
ClickHouse:mainfrom
Airamhh:feat/subpath-routing-support

Conversation

@Airamhh
Copy link
Copy Markdown

@Airamhh Airamhh commented May 20, 2026

Summary

Hello there!

Hope you're doing great, this PR focuses on adding supath support to the application, I didn't know how you exactly wanted to implement it, hope you like it!

Closes #54

Change Type

  • New feature (non-breaking change which adds functionality)

Testing

  1. Build the Docker image with --build-arg VITE_BASE_PATH=/adminpanel
  2. Run the container with -e VITE_BASE_PATH=/adminpanel
  3. Verify /health returns 200
  4. Verify /adminpanel/ loads the app (assets, routes, login all work)
  5. Verify without the variable (default /) the app works as before at root

Test Configuration:

  • nginx reverse proxy forwarding /adminpanelhttp://localhost:4082

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • I have made pertinent documentation changes
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes
  • Any changes dependent on mine have been merged and published in downstream modules.
  • A pull request for updating the documentation has been submitted.

Note

Medium Risk
Introduces path-prefixing across build, routing, and session cookie configuration; misconfiguration of VITE_BASE_PATH could break asset loading, navigation, or auth/session behavior when deployed behind a reverse proxy.

Overview
Adds support for serving the admin panel under a configurable subpath via VITE_BASE_PATH, wiring it through Vite’s build base, TanStack Router basepath, static asset routing, favicon URLs, and session cookie path.

Updates the Bun server to prefix static routes with the base path, redirect ${BASE_PATH}${BASE_PATH}/, adjust Prometheus metrics path normalization to ignore the prefix, and adds a dedicated /health endpoint (also used by the Docker HEALTHCHECK). Documentation and .env.example are updated to describe the new variable and Docker build/run usage.

Reviewed by Cursor Bugbot for commit 143d976. Bugbot is set up for automated code reviews on this repo. Configure here.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 20, 2026

CLA assistant check
All committers have signed the CLA.

Airamhh added 3 commits May 21, 2026 12:17
Add support for deploying the admin panel under a configurable URL subpath
(e.g., /adminpanel) via the VITE_BASE_PATH environment variable. The app
defaults to serving from root (/) when unset, preserving backward compatibility.

Changes:
- vite.config.ts: set Vite 'base' from VITE_BASE_PATH for correct asset prefixing
- src/router.tsx: configure TanStack Router basepath from VITE_BASE_PATH
- src/routes/__root.tsx: prefix favicon href with base path
- server.ts: prefix static file routes with BASE_PATH, add /health endpoint,
  add redirect from BASE_PATH (no slash) to BASE_PATH/
- Dockerfile: accept VITE_BASE_PATH as build ARG, fix healthcheck to use /health
- src/server/session.ts: scope session cookie path to VITE_BASE_PATH to prevent
  cookie conflicts with other apps on the same domain
- .env.example: document VITE_BASE_PATH variable
openid-client v6 uses currentUrl.searchParams.size === 0 to distinguish
initiation from callback. The redirect_uri param was not stripped by
LibreChat's storeAndStripChallenge (only code_challenge is), causing
Passport to misclassify the request as a callback and return 401.

LibreChat already knows the admin panel callback URL via ADMIN_PANEL_URL
env var, so the redirect_uri param was unnecessary.
@Airamhh Airamhh force-pushed the feat/subpath-routing-support branch from cbe5f83 to 64694cd Compare May 21, 2026 14:37
@Airamhh
Copy link
Copy Markdown
Author

Airamhh commented May 21, 2026

Hello!

Sorry, I initially tested everything with a local account rather than using SSO

When I tried it with SSO, I found an issue where the redirect_uri returns an unauthorized error, the latest push is somewhat a workaround, but of course it's neccessary to change

There’s also another fix needed in LibreChat, specifically in the isAdminPanelRedirect function, to properly allow cross-origin redirects that include subroutes to allow the login

https://github.com/danny-avila/LibreChat/blob/8310e9a8402c1712e9cc9d19ef2eadb2187d8e7c/packages/api/src/auth/exchange.ts#L286-L302

@dustinhealy
Copy link
Copy Markdown
Contributor

Thank you for your contribution @Airamhh ! Will be able to take a look at this next week and give a proper review.

@Airamhh
Copy link
Copy Markdown
Author

Airamhh commented May 23, 2026

Thanks!

This was thought based on the actual implementation of the admin panel, so it can be a bit rough since you have to pass an argument to specify the subpath when building the image, which doesn’t allow for much customization on the image itself...

I didn’t want to change the whole thing, rather just implement some kind of workaround so people can still use it under a subpath if they needed it

But yeah, it depends on how you want to implement this feature and of course whether this could impact LibreChat App as well when implementing SSO logins

See you and of course take all the time you need!

@danny-avila
Copy link
Copy Markdown
Contributor

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64694cd5dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/routes/__root.tsx Outdated
{
rel: 'icon',
href: '/favicon.ico',
href: `${import.meta.env.VITE_BASE_PATH || ''}/favicon.ico`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Normalize base path before building favicon URL

When VITE_BASE_PATH is set to '/' (which is the default build arg in this change), this expression produces //favicon.ico instead of /favicon.ico. Browsers interpret //... as a scheme-relative absolute URL (host favicon.ico), so root deployments can request the icon from the wrong host and fail to load it. This regression is introduced by concatenating the raw env value without trimming the root-slash case.

Useful? React with 👍 / 👎.

Comment thread server.ts Outdated
...(BASE_PATH ? { [`${BASE_PATH}`]: () => Response.redirect(`${BASE_PATH}/`, 302) } : {}),
'/*': async (req) => {
const url = new URL(req.url);
const res = await withHttpMetrics(req, url.pathname, () => handler.fetch(req));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Strip base path before recording route metrics

In subpath deployments (for example VITE_BASE_PATH=/adminpanel), this passes /adminpanel/... into withHttpMetrics, but normalizeMetricsPath only maps unprefixed app routes like /login and /configuration. As a result, most application page hits are relabeled as unknown, which regresses per-route observability introduced by this feature. Strip BASE_PATH from url.pathname (or normalize it) before recording metrics.

Useful? React with 👍 / 👎.

- Normalize VITE_BASE_PATH before building favicon URL to avoid //favicon.ico
- Strip BASE_PATH prefix from pathname before recording route metrics
- Add required search prop to Link component to fix TS2741
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 143d976. Configure here.

Comment thread src/server/auth.ts
const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('hex');
authUrl.searchParams.set('code_challenge', codeChallenge);
if (requestOrigin)
authUrl.searchParams.set('redirect_uri', `${requestOrigin}/auth/openid/callback`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SSO redirect_uri removed instead of made subpath-aware

Medium Severity

The openidLoginFn previously sent a redirect_uri parameter to LibreChat's OAuth endpoint so it knew where to redirect after authentication. This was removed entirely instead of being updated to include the base path. Without redirect_uri, LibreChat must determine the callback URL from its own config — which won't include the subpath (e.g., /adminpanel/auth/openid/callback). This means SSO is likely broken for subpath deployments, which is the core purpose of this PR. Even for non-subpath users, this is a behavioral regression since the callback URL is no longer explicitly communicated to the OAuth flow.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 143d976. Configure here.

@Airamhh
Copy link
Copy Markdown
Author

Airamhh commented May 23, 2026

Hello!

I adressed the issues! Well, expect the one related to the redirect_uri one, depends on how you would prefer to deal with this approach since I think it's related to LibreChat as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admin panel does not support sub-path deployments

4 participants