Skip to content

feat(dashboard): same-origin /api proxy for local dev against any API env#799

Merged
law-chain-hot merged 2 commits into
mainfrom
feat/dashboard-local-dev-api-proxy
Jun 16, 2026
Merged

feat(dashboard): same-origin /api proxy for local dev against any API env#799
law-chain-hot merged 2 commits into
mainfrom
feat/dashboard-local-dev-api-proxy

Conversation

@law-chain-hot

@law-chain-hot law-chain-hot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

Local dashboard dev reaches any API environment through a same-origin Vite /api proxy, instead of calling the API cross-origin.

Why

Serving the dashboard on localhost:3000 and calling https://dev.boxlite.ai directly is cross-origin. The browser requires the dev API to return a CORS Access-Control-Allow-Origin for localhost, which it does not — so requests failed with TypeError: Failed to fetch.

Fix is the standard React/Vite approach: the dashboard calls a same-origin /api path, and the Vite dev server proxies it to the selected backend server-to-server (no same-origin policy between servers). No backend has to allow-list localhost, and no dev/prod infra changes.

How

  • start-dashboard.mjs: single API_TARGETS map (local, dev, prod placeholder). --api=<url> proxies to any URL; --yes-prod guards prod (real data + prod Auth0 would have to allow localhost).
  • vite.config.mts: /api proxy target read from DASHBOARD_API_PROXY_TARGET (defaults to local API; nx serve dashboard unchanged).
  • package.json: start:prod (replaces a throwaway start:dev-proxy).
  • apps/CLAUDE.md: corrects "from the repository root" (scripts live in apps/) and documents the proxy model.

Commands

command API
npm run start / start:dev dev (default)
npm run start:local local API (:3001)
npm run start:prod prod (guarded, --yes-prod)
npm run start -- --api=<url> any URL
npm run start:mock MSW mocks

Test

npm run start:dev → browser fetch /api/config returns 200 with real dev config (oidc.issuer = auth.dev.boxlite.ai), no CORS error. Logged in to the dev dashboard locally and saw real boxes + the image picker.

Summary by CodeRabbit

  • New Features

    • Added configurable same-origin dashboard /api proxy routing via DASHBOARD_API_PROXY_TARGET (with --api override support) and improved PROD gating for production runs.
  • Documentation

    • Updated dashboard/E2E instructions to run commands from the apps/ workspace root and clarified proxy/auth behavior and required local/test setup.
  • Chores

    • Added start:prod for production dashboard startup.
    • Refined dashboard startup/proxy configuration and environment handling for more predictable behavior.

… env

Local dashboard dev calls a same-origin /api path; Vite proxies it to the selected backend, so the browser never makes a cross-origin (CORS-gated) request and no backend has to allow-list localhost. Replaces the prior VITE_BASE_API_URL=dev direct-call approach, which the browser blocked with CORS.

- start-dashboard.mjs: API_TARGETS map (local/dev + prod placeholder), --api=<url> for any env, --yes-prod guard for prod
- vite.config.mts: /api proxy target read from DASHBOARD_API_PROXY_TARGET
- package.json: start:prod (replaces throwaway start:dev-proxy)
- apps/CLAUDE.md: fix 'from repository root' -> apps/, document the proxy model
@law-chain-hot law-chain-hot requested a review from a team as a code owner June 16, 2026 06:30
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3733a2ba-2303-4c40-bb5e-5bd9e5fd9263

📥 Commits

Reviewing files that changed from the base of the PR and between 56bf2c5 and 68f3e35.

📒 Files selected for processing (1)
  • apps/scripts/start-dashboard.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/scripts/start-dashboard.mjs

📝 Walkthrough

Walkthrough

The dashboard startup script is refactored around a centralized API_TARGETS map. A Vite proxy for /api now reads its target from DASHBOARD_API_PROXY_TARGET (set by the script at runtime). A --yes-prod guard blocks accidental prod startup. A new start:prod npm script is added, and CLAUDE.md is updated to document the proxy-based workflow.

Dashboard API Proxy Refactor

Layer / File(s) Summary
API_TARGETS map, proxy resolution, and Vite config
apps/scripts/start-dashboard.mjs, apps/dashboard/vite.config.mts
Replaces per-target env blocks with a centralized API_TARGETS constant and proxyTarget/extraEnv structure. Adds --yes-prod to arg parsing and CLI help. At runtime, resolves and normalizes the proxy destination from --api or the selected target's proxyTarget, enforces a prod guard, sets env.DASHBOARD_API_PROXY_TARGET while clearing VITE_BASE_API_URL, and logs the resolved proxy. Vite reads DASHBOARD_API_PROXY_TARGET (fallback http://localhost:3001) as the /api proxy target.
start:prod script and updated docs
apps/package.json, apps/CLAUDE.md
Adds the start:prod npm script (node scripts/start-dashboard.mjs --target=prod). Updates CLAUDE.md to document running from the apps/ workspace root, the same-origin /api proxy mechanism, all start variants, the --yes-prod requirement, and local Dex test account and Docker Desktop prerequisites.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 Hoppity-hop through the proxy lane,
No hardcoded URLs shall remain!
API_TARGETS now leads the way,
Prod needs a flag before you may play.
The dashboard proxies /api with care —
A tidy warren, beyond compare! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main technical change: implementing a same-origin /api proxy for local dashboard development.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dashboard-local-dev-api-proxy

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Copy link
Copy Markdown

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: 56bf2c5e30

ℹ️ 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 apps/scripts/start-dashboard.mjs Outdated
Comment thread apps/scripts/start-dashboard.mjs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/scripts/start-dashboard.mjs (1)

68-87: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate required option values for --target/--env/--api before consuming next argv item.

--api / --target currently accept the next token blindly. If the next token is another flag (or missing), parsing becomes inconsistent (e.g., --api --yes-prod sets api="--yes-prod" and skips the real flag handling). Fail fast with a clear error when the value is absent/invalid.

Suggested fix
 function parseArgs(argv) {
   let target = 'dev'
   let api
   let yesProd = false
   const forward = []
+  const readValue = (flag, index) => {
+    const value = argv[index + 1]
+    if (!value || value.startsWith('--')) {
+      throw new Error(`Missing value for ${flag}`)
+    }
+    return value
+  }

   for (let i = 0; i < argv.length; i += 1) {
     const arg = argv[i]
@@
     if (arg === '--target' || arg === '--env') {
-      target = argv[i + 1] || target
+      target = readValue(arg, i)
       i += 1
       continue
     }
@@
     if (arg === '--api') {
-      api = argv[i + 1]
+      api = readValue(arg, i)
       i += 1
       continue
     }
@@
   }

   return { help: false, target, api, yesProd, forward }
 }

Also applies to: 90-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/scripts/start-dashboard.mjs` around lines 68 - 87, The argument parser
in start-dashboard.mjs does not validate that required option values exist
before consuming them from argv. When handling flags like --target, --env, and
--api that expect a value (via both --flag value and --flag=value syntax), you
must check that argv[i + 1] exists and is not another flag (starting with --)
before assigning it to the target or api variable. Add validation logic that
checks if the next argv item is present and does not start with -- ; if the
check fails, throw or log a clear error message indicating which option is
missing its required value, then exit early. Apply this validation consistently
across all three flag handlers (--target/--env around line 68-75 and --api
around line 86-103) to prevent inconsistent parsing behavior when users
accidentally omit values or provide flags out of order.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/scripts/start-dashboard.mjs`:
- Around line 143-156: The prod confirmation guard can be bypassed by providing
both --target=prod and --api together because the entire guard only runs when
!api is true. This means a user can skip the --yes-prod confirmation check by
supplying an API target. Restructure the condition so that the yesProd check
runs whenever selected.prod is true, regardless of whether the api parameter is
provided. Move the yesProd validation outside or separate from the !api
condition so that any prod target invocation requires --yes-prod confirmation to
be explicitly provided, closing this security gap.

---

Outside diff comments:
In `@apps/scripts/start-dashboard.mjs`:
- Around line 68-87: The argument parser in start-dashboard.mjs does not
validate that required option values exist before consuming them from argv. When
handling flags like --target, --env, and --api that expect a value (via both
--flag value and --flag=value syntax), you must check that argv[i + 1] exists
and is not another flag (starting with --) before assigning it to the target or
api variable. Add validation logic that checks if the next argv item is present
and does not start with -- ; if the check fails, throw or log a clear error
message indicating which option is missing its required value, then exit early.
Apply this validation consistently across all three flag handlers
(--target/--env around line 68-75 and --api around line 86-103) to prevent
inconsistent parsing behavior when users accidentally omit values or provide
flags out of order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 854f433d-ecdb-450c-b14f-c641815787e9

📥 Commits

Reviewing files that changed from the base of the PR and between f394033 and 56bf2c5.

📒 Files selected for processing (4)
  • apps/CLAUDE.md
  • apps/dashboard/vite.config.mts
  • apps/package.json
  • apps/scripts/start-dashboard.mjs

Comment thread apps/scripts/start-dashboard.mjs
Comment thread apps/scripts/start-dashboard.mjs
DorianZheng
DorianZheng previously approved these changes Jun 16, 2026
@law-chain-hot law-chain-hot enabled auto-merge June 16, 2026 07:57
… /api

Review fixes (CodeRabbit / codex):
- prod guard ran only when !api, so --target=prod --api=<url> bypassed the --yes-prod confirmation. Now any prod target requires it; only the 'unconfigured' check depends on the built-in API_TARGETS map.
- proxied targets clear VITE_BASE_API_URL so an inherited/exported value can't build a cross-origin apiUrl and bypass the proxy (re-introducing CORS).
@law-chain-hot law-chain-hot added this pull request to the merge queue Jun 16, 2026
Merged via the queue into main with commit 075f6a6 Jun 16, 2026
31 checks passed
@law-chain-hot law-chain-hot deleted the feat/dashboard-local-dev-api-proxy branch June 16, 2026 10:34
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.

2 participants