diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 208379ef9..8cfba4090 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -36,7 +36,7 @@ jobs:
- name: Build canary
run: bun run build:canary
env:
- VITE_PORTAL_GATEWAY_BASE_URL: 'https://m.longbridge.xyz'
+ VITE_PORTAL_GATEWAY_BASE_URL: 'https://mr.longbridge.xyz'
NODE_OPTIONS: --max-old-space-size=12288 --expose-gc
- name: Upload to Aliyun OSS
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 97b3577b2..1fe68db51 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -40,7 +40,7 @@ jobs:
- name: Build release
run: bun run build:release
env:
- VITE_PORTAL_GATEWAY_BASE_URL: 'https://m.lbkrs.com'
+ VITE_PORTAL_GATEWAY_BASE_URL: 'https://mr.lbkrs.com'
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index b305e26a5..7df44a3c5 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -28,11 +28,17 @@ const oneTapProxy = process.env.PROXY === 'canary' ? 'canary' : 'production'
const isReleaseBuild = process.env.PROXY !== 'canary' && process.env.NODE_ENV === 'production'
const heloraScriptSrc = 'https://assets.lbkrs.com/h5hub/helora-embed/helora-embed-1.0.1.iife.js'
+// Resolve `window.__API_PROXY_URL__` at runtime based on cookie `app_id` (US tenants),
+// falling back to the build-time env value. Must run before longport-internal.iife.js loads.
+// Aligns with docs/.vitepress/theme/utils/app-id.ts (US_APPID_API_HOST).
+const apiProxyDefault = JSON.stringify(process.env.VITE_PORTAL_GATEWAY_BASE_URL)
+const apiProxyBootstrap = `(function(){var d=document;function c(n){var m=('; '+d.cookie).split('; '+n+'=');return m.length===2?decodeURIComponent(m.pop().split(';').shift()):undefined;}var a=c('app_id')||c('x-original-app-id');var US={longbridge_us:'https://mr.longbridge.com',longbridge_us_uat:'https://mr.longbridge-staging.com'};window.__API_PROXY_URL__=(a&&US[a])||${apiProxyDefault};})();`
+
const insertScript = (html: string) => {
const $ = cheerio.load(html)
$('head').prepend(
- ``,
- ``
+ ``,
+ ``
)
return $.html()
}
@@ -211,7 +217,7 @@ export default defineConfig(
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/lb-api': {
- target: process.env.VITE_PORTAL_API_BASE_URL || 'https://m.longbridge.xyz',
+ target: process.env.VITE_PORTAL_API_BASE_URL || 'https://mr.longbridge.xyz',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/lb-api/, '/api'),
},
diff --git a/docs/.vitepress/theme/utils/app-id.ts b/docs/.vitepress/theme/utils/app-id.ts
new file mode 100644
index 000000000..5cf41c796
--- /dev/null
+++ b/docs/.vitepress/theme/utils/app-id.ts
@@ -0,0 +1,51 @@
+/**
+ * Runtime tenant detection via cookie `app_id`.
+ * Aligns with openapi-website-private:
+ * - packages/utils/src/normalize.ts:11-17 (US_APP_IDS)
+ * - packages/services/utils.ts:14-17 (APPID_PROXY_OVERRIDE)
+ */
+
+/**
+ * API host per US tenant environment.
+ * Values match openapi-website-private/packages/utils/src/constant.ts DomainsMap:
+ * us-prod.api = 'https://mr.longbridge.com'
+ * us-staging.api = 'https://mr.longbridge-staging.com'
+ */
+export const US_APPID_API_HOST: Record = {
+ longbridge_us: 'https://mr.longbridge.com',
+ longbridge_us_uat: 'https://mr.longbridge-staging.com',
+}
+
+/** Read a cookie value on the client. Returns undefined on SSR or missing. */
+function readCookie(name: string): string | undefined {
+ if (typeof document === 'undefined') return undefined
+ const target = `${name}=`
+ for (const part of document.cookie.split(';')) {
+ const trimmed = part.trim()
+ if (trimmed.startsWith(target)) {
+ return decodeURIComponent(trimmed.slice(target.length))
+ }
+ }
+ return undefined
+}
+
+/** Current tenant app_id from cookie (falls back to `x-original-app-id`). */
+export function getAppIdFromCookie(): string | undefined {
+ return readCookie('app_id') || readCookie('x-original-app-id')
+}
+
+/** Whether the current user is on a US tenant (either prod or UAT). */
+export function isUsAppId(): boolean {
+ const appId = getAppIdFromCookie()
+ return !!appId && appId in US_APPID_API_HOST
+}
+
+/**
+ * Resolve the API host for the current US tenant.
+ * Returns the matching host for `longbridge_us` (prod) / `longbridge_us_uat` (staging),
+ * or undefined when the cookie is not a US app_id.
+ */
+export function resolveUsApiHost(): string | undefined {
+ const appId = getAppIdFromCookie()
+ return appId ? US_APPID_API_HOST[appId] : undefined
+}
diff --git a/docs/.vitepress/theme/utils/navigate.ts b/docs/.vitepress/theme/utils/navigate.ts
index 7079a6922..a1b0e871d 100644
--- a/docs/.vitepress/theme/utils/navigate.ts
+++ b/docs/.vitepress/theme/utils/navigate.ts
@@ -15,5 +15,6 @@ export function createLoginRedirectPath(ssoParams?: Record>
) {
- const API_BASE_URL = endsWith(location.hostname, '.xyz')
- ? 'https://openapi.longbridge.xyz'
- : endsWith(location.hostname, '.cn')
- ? 'https://openapi.longbridge.com'
- : 'https://openapi.longbridge.com'
+ // Prefer runtime cookie `app_id`:
+ // - longbridge_us → https://mr.longbridge.com (US prod)
+ // - longbridge_us_uat → https://mr.longbridge-staging.com (US staging)
+ // Fallback to hostname suffix detection.
+ const usHost = resolveUsApiHost()
+ const API_BASE_URL =
+ usHost ||
+ (endsWith(location.hostname, '.xyz')
+ ? 'https://openapi.longbridge.xyz'
+ : endsWith(location.hostname, '.cn')
+ ? 'https://openapi.longbridge.com'
+ : 'https://openapi.longbridge.com')
const config: ApiConfig = {
appKey: authConfig.appKey,
diff --git a/package.json b/package.json
index 5af03f1f2..aee8f6201 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"dev:cn": "cross-env VITE_REGION=cn VITE_API_BASE_URL=https://openapi.longbridge.cn VITE_SITE_HOSTNAME=https://open.longbridge.cn npx vitepress dev docs",
"build:canary": "cross-env \"NODE_OPTIONS=--max-old-space-size=12288 --expose-gc\" PROXY=canary VITE_API_BASE_URL=https://openapi.longbridge.xyz npx vitepress build docs && bun run build:llms && bun run build:copy-routes",
"build:release": "cross-env \"NODE_OPTIONS=--max-old-space-size=12288 --expose-gc\" VITE_API_BASE_URL=https://openapi.longbridge.com npx vitepress build docs && bun run build:llms && bun run build:copy-routes",
- "build:cn": "cross-env \"NODE_OPTIONS=--max-old-space-size=12288 --expose-gc\" VITE_REGION=cn VITE_API_BASE_URL=https://openapi.longbridge.cn VITE_PORTAL_GATEWAY_BASE_URL=https://m.lbkrs.com VITE_SITE_HOSTNAME=https://open.longbridge.cn npx vitepress build docs && cross-env VITE_REGION=cn bun run build:llms && bun run build:copy-routes",
+ "build:cn": "cross-env \"NODE_OPTIONS=--max-old-space-size=12288 --expose-gc\" VITE_REGION=cn VITE_API_BASE_URL=https://openapi.longbridge.cn VITE_PORTAL_GATEWAY_BASE_URL=https://mr.lbkrs.com VITE_SITE_HOSTNAME=https://open.longbridge.cn npx vitepress build docs && cross-env VITE_REGION=cn bun run build:llms && bun run build:copy-routes",
"build:llms": "bun run scripts/normalize_md.ts && bun run scripts/generate-llms.ts",
"build:copy-routes": "bun run scripts/copy-routes.ts",
"preview": "vitepress preview docs",
diff --git a/region.config.ts b/region.config.ts
index 3b19c1207..6b461e0e8 100644
--- a/region.config.ts
+++ b/region.config.ts
@@ -29,7 +29,7 @@ export interface RegionConfig {
export const regionConfig: Record = {
cn: {
apiBaseUrl: 'https://openapi.longbridge.cn',
- portalGatewayBaseUrl: 'https://m.lbkrs.com',
+ portalGatewayBaseUrl: 'https://mr.lbkrs.com',
siteHostname: 'https://open.longbridge.cn',
mcpHostname: 'https://mcp.longbridge.cn',