From 019c9e8cb44a866bc88eab51aa9666385b5f6264 Mon Sep 17 00:00:00 2001
From: silent-cipher
Date: Mon, 29 Jun 2026 23:40:17 +0530
Subject: [PATCH 1/3] feat(web): add per-network betterstack url configuration
---
apps/web/.env.example | 13 ++++++++--
apps/web/docker-entrypoint.sh | 14 ++++++++++-
apps/web/src/pages/Landing.tsx | 45 +++++++++++++++++++++++++++++++---
apps/web/src/vite-env.d.ts | 8 ++++++
4 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/apps/web/.env.example b/apps/web/.env.example
index 71d59fb5..abb3819b 100644
--- a/apps/web/.env.example
+++ b/apps/web/.env.example
@@ -6,9 +6,15 @@ VITE_API_BASE_URL=http://localhost:8080
# Example values: dealbot.filoz.org or staging.dealbot.filoz.org
VITE_PLAUSIBLE_DATA_DOMAIN=
-# Dashboard URL linked from the landing page
+# Metrics dashboard URL linked from the per-SP rows on the landing page.
+# BetterStack keeps a separate dashboard per network, so set the per-network
+# vars below for deployments that monitor more than one network. VITE_DASHBOARD_URL
+# is the fallback used when the selected network's var is unset, so existing
+# single-network deployments keep working until infra sets the per-network vars.
# Example: https://your-team.betteruptime.com
VITE_DASHBOARD_URL=
+VITE_DASHBOARD_URL_MAINNET=
+VITE_DASHBOARD_URL_CALIBRATION=
# Dashboard URL to embed as an iframe on the landing page (optional)
# Example: https://your-team.betteruptime.com/embed/...
@@ -21,5 +27,8 @@ VITE_DASHBOARD_EMBED_URL=
VITE_APPROVED_SP_DASHBOARD_URL_MAINNET=
VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION=
-# Logs URL linked from the landing page (optional)
+# Logs URL linked from the per-SP rows on the landing page (optional).
+# Per-network vars take precedence; VITE_LOGS_URL is the fallback when unset.
VITE_LOGS_URL=
+VITE_LOGS_URL_MAINNET=
+VITE_LOGS_URL_CALIBRATION=
diff --git a/apps/web/docker-entrypoint.sh b/apps/web/docker-entrypoint.sh
index 06b88235..a7a367ea 100644
--- a/apps/web/docker-entrypoint.sh
+++ b/apps/web/docker-entrypoint.sh
@@ -10,28 +10,40 @@ escape_js() {
API_BASE_URL="${DEALBOT_API_BASE_URL:-${VITE_API_BASE_URL:-}}"
PLAUSIBLE_DATA_DOMAIN="${VITE_PLAUSIBLE_DATA_DOMAIN:-}"
DASHBOARD_URL="${DASHBOARD_URL:-${VITE_DASHBOARD_URL:-}}"
+DASHBOARD_URL_MAINNET="${DASHBOARD_URL_MAINNET:-${VITE_DASHBOARD_URL_MAINNET:-}}"
+DASHBOARD_URL_CALIBRATION="${DASHBOARD_URL_CALIBRATION:-${VITE_DASHBOARD_URL_CALIBRATION:-}}"
DASHBOARD_EMBED_URL="${DASHBOARD_EMBED_URL:-${VITE_DASHBOARD_EMBED_URL:-}}"
APPROVED_SP_DASHBOARD_URL_MAINNET="${APPROVED_SP_DASHBOARD_URL_MAINNET:-${VITE_APPROVED_SP_DASHBOARD_URL_MAINNET:-}}"
APPROVED_SP_DASHBOARD_URL_CALIBRATION="${APPROVED_SP_DASHBOARD_URL_CALIBRATION:-${VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION:-}}"
LOGS_URL="${LOGS_URL:-${VITE_LOGS_URL:-}}"
+LOGS_URL_MAINNET="${LOGS_URL_MAINNET:-${VITE_LOGS_URL_MAINNET:-}}"
+LOGS_URL_CALIBRATION="${LOGS_URL_CALIBRATION:-${VITE_LOGS_URL_CALIBRATION:-}}"
API_BASE_URL_ESCAPED="$(escape_js "$API_BASE_URL")"
PLAUSIBLE_DATA_DOMAIN_ESCAPED="$(escape_js "$PLAUSIBLE_DATA_DOMAIN")"
DASHBOARD_URL_ESCAPED="$(escape_js "$DASHBOARD_URL")"
+DASHBOARD_URL_MAINNET_ESCAPED="$(escape_js "$DASHBOARD_URL_MAINNET")"
+DASHBOARD_URL_CALIBRATION_ESCAPED="$(escape_js "$DASHBOARD_URL_CALIBRATION")"
DASHBOARD_EMBED_URL_ESCAPED="$(escape_js "$DASHBOARD_EMBED_URL")"
APPROVED_SP_DASHBOARD_URL_MAINNET_ESCAPED="$(escape_js "$APPROVED_SP_DASHBOARD_URL_MAINNET")"
APPROVED_SP_DASHBOARD_URL_CALIBRATION_ESCAPED="$(escape_js "$APPROVED_SP_DASHBOARD_URL_CALIBRATION")"
LOGS_URL_ESCAPED="$(escape_js "$LOGS_URL")"
+LOGS_URL_MAINNET_ESCAPED="$(escape_js "$LOGS_URL_MAINNET")"
+LOGS_URL_CALIBRATION_ESCAPED="$(escape_js "$LOGS_URL_CALIBRATION")"
cat > "$RUNTIME_CONFIG_PATH" < {
return { safe, isInvalid: Boolean(raw) && !safe };
};
+type NetworkUrlSource = { runtime?: string; build?: string };
+
+/**
+ * Resolves a URL that may be configured per network, falling back to a bare
+ * global value so single-network deployments keep working before infra sets the
+ * per-network vars. Precedence within each tier (runtime, build) is
+ * per-network → global; runtime still wins over build (see getConfigUrl).
+ */
+const getNetworkConfigUrl = (
+ network: Network | null,
+ perNetwork: Record,
+ global: NetworkUrlSource,
+) => {
+ const scoped = network ? perNetwork[network] : undefined;
+ return getConfigUrl(scoped?.runtime ?? global.runtime, scoped?.build ?? global.build);
+};
+
const getConfig = (network: Network | null) => {
const runtimeConfig = typeof window === "undefined" ? undefined : window.__DEALBOT_CONFIG__;
- const dashboardUrl = getConfigUrl(runtimeConfig?.DASHBOARD_URL, import.meta.env.VITE_DASHBOARD_URL);
- const approvedSpSources: Record = {
+ // Metrics dashboard and SP logs live in a distinct BetterStack dashboard per
+ // network, so prefer a per-network URL and fall back to the bare global var so
+ // single-network deployments keep working until infra sets the per-network vars.
+ const dashboardUrl = getNetworkConfigUrl(
+ network,
+ {
+ mainnet: { runtime: runtimeConfig?.DASHBOARD_URL_MAINNET, build: import.meta.env.VITE_DASHBOARD_URL_MAINNET },
+ calibration: {
+ runtime: runtimeConfig?.DASHBOARD_URL_CALIBRATION,
+ build: import.meta.env.VITE_DASHBOARD_URL_CALIBRATION,
+ },
+ },
+ { runtime: runtimeConfig?.DASHBOARD_URL, build: import.meta.env.VITE_DASHBOARD_URL },
+ );
+ const logsUrl = getNetworkConfigUrl(
+ network,
+ {
+ mainnet: { runtime: runtimeConfig?.LOGS_URL_MAINNET, build: import.meta.env.VITE_LOGS_URL_MAINNET },
+ calibration: { runtime: runtimeConfig?.LOGS_URL_CALIBRATION, build: import.meta.env.VITE_LOGS_URL_CALIBRATION },
+ },
+ { runtime: runtimeConfig?.LOGS_URL, build: import.meta.env.VITE_LOGS_URL },
+ );
+
+ // Approved-SP dashboard: per-network only (two separate curated dashboards; no global fallback).
+ const approvedSpSources: Record = {
mainnet: {
runtime: runtimeConfig?.APPROVED_SP_DASHBOARD_URL_MAINNET,
build: import.meta.env.VITE_APPROVED_SP_DASHBOARD_URL_MAINNET,
@@ -68,7 +108,6 @@ const getConfig = (network: Network | null) => {
const approvedSpDashboardUrl = network
? getConfigUrl(approvedSpSources[network].runtime, approvedSpSources[network].build)
: { safe: "", isInvalid: false };
- const logsUrl = getConfigUrl(runtimeConfig?.LOGS_URL, import.meta.env.VITE_LOGS_URL);
return {
dashboardUrl: dashboardUrl.safe,
diff --git a/apps/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts
index e2df724c..1b62de2b 100644
--- a/apps/web/src/vite-env.d.ts
+++ b/apps/web/src/vite-env.d.ts
@@ -7,10 +7,14 @@ interface ImportMeta {
readonly VITE_API_BASE_URL: string;
readonly VITE_PLAUSIBLE_DATA_DOMAIN?: string;
readonly VITE_DASHBOARD_URL?: string;
+ readonly VITE_DASHBOARD_URL_MAINNET?: string;
+ readonly VITE_DASHBOARD_URL_CALIBRATION?: string;
readonly VITE_DASHBOARD_EMBED_URL?: string;
readonly VITE_APPROVED_SP_DASHBOARD_URL_MAINNET?: string;
readonly VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION?: string;
readonly VITE_LOGS_URL?: string;
+ readonly VITE_LOGS_URL_MAINNET?: string;
+ readonly VITE_LOGS_URL_CALIBRATION?: string;
};
}
@@ -19,9 +23,13 @@ interface Window {
API_BASE_URL?: string;
PLAUSIBLE_DATA_DOMAIN?: string;
DASHBOARD_URL?: string;
+ DASHBOARD_URL_MAINNET?: string;
+ DASHBOARD_URL_CALIBRATION?: string;
DASHBOARD_EMBED_URL?: string;
APPROVED_SP_DASHBOARD_URL_MAINNET?: string;
APPROVED_SP_DASHBOARD_URL_CALIBRATION?: string;
LOGS_URL?: string;
+ LOGS_URL_MAINNET?: string;
+ LOGS_URL_CALIBRATION?: string;
};
}
From f2a32217d04c2916bc34d7549eb69ceab2fbc4b3 Mon Sep 17 00:00:00 2001
From: silent-cipher
Date: Thu, 2 Jul 2026 01:10:18 +0530
Subject: [PATCH 2/3] feat: rescope url configuration
---
apps/web/.env.example | 24 ++++----
apps/web/docker-entrypoint.sh | 17 ++----
apps/web/src/pages/Landing.test.tsx | 42 +++++++++++++-
apps/web/src/pages/Landing.tsx | 90 +++++++++++++++--------------
apps/web/src/vite-env.d.ts | 10 +---
5 files changed, 105 insertions(+), 78 deletions(-)
diff --git a/apps/web/.env.example b/apps/web/.env.example
index abb3819b..4fe9c2dd 100644
--- a/apps/web/.env.example
+++ b/apps/web/.env.example
@@ -7,28 +7,26 @@ VITE_API_BASE_URL=http://localhost:8080
VITE_PLAUSIBLE_DATA_DOMAIN=
# Metrics dashboard URL linked from the per-SP rows on the landing page.
-# BetterStack keeps a separate dashboard per network, so set the per-network
-# vars below for deployments that monitor more than one network. VITE_DASHBOARD_URL
-# is the fallback used when the selected network's var is unset, so existing
-# single-network deployments keep working until infra sets the per-network vars.
+# One dashboard per environment; the app adds a vs[network] filter per row so it
+# serves every network the deployment monitors (a no-op until the dashboard
+# defines a {{network}} variable).
# Example: https://your-team.betteruptime.com
VITE_DASHBOARD_URL=
-VITE_DASHBOARD_URL_MAINNET=
-VITE_DASHBOARD_URL_CALIBRATION=
# Dashboard URL to embed as an iframe on the landing page (optional)
# Example: https://your-team.betteruptime.com/embed/...
VITE_DASHBOARD_EMBED_URL=
-# Combined approved-SP dashboard URL linked from the landing page, per network (optional)
-# The frontend picks the URL matching the backend's network (mainnet vs calibration).
-# Example mainnet: https://telemetry.betterstack.com/dashboards/Zz8k7L?rf=now-72h&rt=now
-# Example calibration: https://telemetry.betterstack.com/dashboards/wt6QCw?rf=now-3d&rt=now
+# Combined approved-SP dashboard URL linked from the landing page (optional).
+# Preferred: one per-environment dashboard; the app adds a vs[network] filter.
+# When set, it wins over the legacy per-network vars below.
+# Example: https://telemetry.betterstack.com/dashboards/Zz8k7L?rf=now-72h&rt=now
+VITE_APPROVED_SP_DASHBOARD_URL=
+# Legacy per-network approved-SP dashboards (fallback used when the combined var
+# above is unset). Each deployment sets the one matching its network.
VITE_APPROVED_SP_DASHBOARD_URL_MAINNET=
VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION=
# Logs URL linked from the per-SP rows on the landing page (optional).
-# Per-network vars take precedence; VITE_LOGS_URL is the fallback when unset.
+# One dashboard per environment; the app adds a vs[network] filter per row.
VITE_LOGS_URL=
-VITE_LOGS_URL_MAINNET=
-VITE_LOGS_URL_CALIBRATION=
diff --git a/apps/web/docker-entrypoint.sh b/apps/web/docker-entrypoint.sh
index a7a367ea..893dd17f 100644
--- a/apps/web/docker-entrypoint.sh
+++ b/apps/web/docker-entrypoint.sh
@@ -10,40 +10,31 @@ escape_js() {
API_BASE_URL="${DEALBOT_API_BASE_URL:-${VITE_API_BASE_URL:-}}"
PLAUSIBLE_DATA_DOMAIN="${VITE_PLAUSIBLE_DATA_DOMAIN:-}"
DASHBOARD_URL="${DASHBOARD_URL:-${VITE_DASHBOARD_URL:-}}"
-DASHBOARD_URL_MAINNET="${DASHBOARD_URL_MAINNET:-${VITE_DASHBOARD_URL_MAINNET:-}}"
-DASHBOARD_URL_CALIBRATION="${DASHBOARD_URL_CALIBRATION:-${VITE_DASHBOARD_URL_CALIBRATION:-}}"
DASHBOARD_EMBED_URL="${DASHBOARD_EMBED_URL:-${VITE_DASHBOARD_EMBED_URL:-}}"
+APPROVED_SP_DASHBOARD_URL="${APPROVED_SP_DASHBOARD_URL:-${VITE_APPROVED_SP_DASHBOARD_URL:-}}"
APPROVED_SP_DASHBOARD_URL_MAINNET="${APPROVED_SP_DASHBOARD_URL_MAINNET:-${VITE_APPROVED_SP_DASHBOARD_URL_MAINNET:-}}"
APPROVED_SP_DASHBOARD_URL_CALIBRATION="${APPROVED_SP_DASHBOARD_URL_CALIBRATION:-${VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION:-}}"
LOGS_URL="${LOGS_URL:-${VITE_LOGS_URL:-}}"
-LOGS_URL_MAINNET="${LOGS_URL_MAINNET:-${VITE_LOGS_URL_MAINNET:-}}"
-LOGS_URL_CALIBRATION="${LOGS_URL_CALIBRATION:-${VITE_LOGS_URL_CALIBRATION:-}}"
API_BASE_URL_ESCAPED="$(escape_js "$API_BASE_URL")"
PLAUSIBLE_DATA_DOMAIN_ESCAPED="$(escape_js "$PLAUSIBLE_DATA_DOMAIN")"
DASHBOARD_URL_ESCAPED="$(escape_js "$DASHBOARD_URL")"
-DASHBOARD_URL_MAINNET_ESCAPED="$(escape_js "$DASHBOARD_URL_MAINNET")"
-DASHBOARD_URL_CALIBRATION_ESCAPED="$(escape_js "$DASHBOARD_URL_CALIBRATION")"
DASHBOARD_EMBED_URL_ESCAPED="$(escape_js "$DASHBOARD_EMBED_URL")"
+APPROVED_SP_DASHBOARD_URL_ESCAPED="$(escape_js "$APPROVED_SP_DASHBOARD_URL")"
APPROVED_SP_DASHBOARD_URL_MAINNET_ESCAPED="$(escape_js "$APPROVED_SP_DASHBOARD_URL_MAINNET")"
APPROVED_SP_DASHBOARD_URL_CALIBRATION_ESCAPED="$(escape_js "$APPROVED_SP_DASHBOARD_URL_CALIBRATION")"
LOGS_URL_ESCAPED="$(escape_js "$LOGS_URL")"
-LOGS_URL_MAINNET_ESCAPED="$(escape_js "$LOGS_URL_MAINNET")"
-LOGS_URL_CALIBRATION_ESCAPED="$(escape_js "$LOGS_URL_CALIBRATION")"
cat > "$RUNTIME_CONFIG_PATH" < {
+ afterEach(() => {
+ window.__DEALBOT_CONFIG__ = undefined;
+ });
+
it("renders string providerId in the table", () => {
setupMock([makeProvider({ providerId: "42" })]);
renderLanding();
@@ -81,4 +85,40 @@ describe("Landing", () => {
const cells = row.querySelectorAll("td");
expect(cells[1].textContent).toBe("—");
});
+
+ it("scopes per-SP metrics and logs links with vs[network]", () => {
+ window.__DEALBOT_CONFIG__ = {
+ DASHBOARD_URL: "https://telemetry.betterstack.com/dashboards/metrics",
+ LOGS_URL: "https://telemetry.betterstack.com/dashboards/logs",
+ };
+ setupMock([makeProvider({ providerId: "42" })]);
+ renderLanding();
+ const metrics = screen.getByRole("link", { name: /Metrics/ });
+ const logs = screen.getByRole("link", { name: /Logs/ });
+ expect(metrics.getAttribute("href")).toContain("vs%5Bnetwork%5D=mainnet");
+ expect(logs.getAttribute("href")).toContain("vs%5Bnetwork%5D=mainnet");
+ });
+
+ it("prefers the combined approved-SP dashboard and scopes it with vs[network]", () => {
+ window.__DEALBOT_CONFIG__ = {
+ APPROVED_SP_DASHBOARD_URL: "https://telemetry.betterstack.com/dashboards/combined",
+ APPROVED_SP_DASHBOARD_URL_MAINNET: "https://telemetry.betterstack.com/dashboards/legacy-mainnet",
+ };
+ setupMock();
+ renderLanding();
+ const href = screen.getByRole("link", { name: /View dashboard/ }).getAttribute("href") ?? "";
+ expect(href).toContain("/dashboards/combined");
+ expect(href).toContain("vs%5Bnetwork%5D=mainnet");
+ });
+
+ it("falls back to the legacy per-network approved-SP dashboard when the combined var is unset", () => {
+ window.__DEALBOT_CONFIG__ = {
+ APPROVED_SP_DASHBOARD_URL_MAINNET: "https://telemetry.betterstack.com/dashboards/legacy-mainnet",
+ };
+ setupMock();
+ renderLanding();
+ const href = screen.getByRole("link", { name: /View dashboard/ }).getAttribute("href") ?? "";
+ expect(href).toContain("/dashboards/legacy-mainnet");
+ expect(href).not.toContain("vs%5Bnetwork%5D");
+ });
});
diff --git a/apps/web/src/pages/Landing.tsx b/apps/web/src/pages/Landing.tsx
index 143d5a6e..35f9057d 100644
--- a/apps/web/src/pages/Landing.tsx
+++ b/apps/web/src/pages/Landing.tsx
@@ -10,8 +10,9 @@ import type { Network } from "@/types/config";
/**
* Builds a BetterStack dashboard or logs URL scoped to a single provider.
- * Appends time range (now-24h to now) and provider filter.
- * Metrics dashboard uses vs[provider_id]; logs dashboard uses vs[providerId].
+ * Appends time range and provider filter. Metrics dashboard uses vs[provider_id];
+ * logs dashboard uses vs[providerId]. Network scoping is layered on separately
+ * via withNetworkParam.
*/
function buildBetterStackUrlWithProvider(
baseUrl: string,
@@ -54,48 +55,39 @@ const getConfigUrl = (runtimeValue?: string, buildValue?: string) => {
type NetworkUrlSource = { runtime?: string; build?: string };
/**
- * Resolves a URL that may be configured per network, falling back to a bare
- * global value so single-network deployments keep working before infra sets the
- * per-network vars. Precedence within each tier (runtime, build) is
- * per-network → global; runtime still wins over build (see getConfigUrl).
+ * Adds the vs[network] dashboard filter to a URL, preserving existing params.
+ * Empty/invalid input yields "", and a null network returns the URL unchanged.
+ * A no-op until the BetterStack dashboard defines a {{network}} variable, so it
+ * is safe to emit ahead of that dashboard change.
*/
-const getNetworkConfigUrl = (
- network: Network | null,
- perNetwork: Record,
- global: NetworkUrlSource,
-) => {
- const scoped = network ? perNetwork[network] : undefined;
- return getConfigUrl(scoped?.runtime ?? global.runtime, scoped?.build ?? global.build);
+const withNetworkParam = (baseUrl: string, network: Network | null): string => {
+ if (!baseUrl || !network) return baseUrl;
+ try {
+ const url = new URL(baseUrl);
+ url.searchParams.set("vs[network]", network);
+ return url.toString();
+ } catch {
+ return "";
+ }
};
const getConfig = (network: Network | null) => {
const runtimeConfig = typeof window === "undefined" ? undefined : window.__DEALBOT_CONFIG__;
- // Metrics dashboard and SP logs live in a distinct BetterStack dashboard per
- // network, so prefer a per-network URL and fall back to the bare global var so
- // single-network deployments keep working until infra sets the per-network vars.
- const dashboardUrl = getNetworkConfigUrl(
- network,
- {
- mainnet: { runtime: runtimeConfig?.DASHBOARD_URL_MAINNET, build: import.meta.env.VITE_DASHBOARD_URL_MAINNET },
- calibration: {
- runtime: runtimeConfig?.DASHBOARD_URL_CALIBRATION,
- build: import.meta.env.VITE_DASHBOARD_URL_CALIBRATION,
- },
- },
- { runtime: runtimeConfig?.DASHBOARD_URL, build: import.meta.env.VITE_DASHBOARD_URL },
- );
- const logsUrl = getNetworkConfigUrl(
- network,
- {
- mainnet: { runtime: runtimeConfig?.LOGS_URL_MAINNET, build: import.meta.env.VITE_LOGS_URL_MAINNET },
- calibration: { runtime: runtimeConfig?.LOGS_URL_CALIBRATION, build: import.meta.env.VITE_LOGS_URL_CALIBRATION },
- },
- { runtime: runtimeConfig?.LOGS_URL, build: import.meta.env.VITE_LOGS_URL },
- );
+ // Metrics dashboard and SP logs are a single per-environment dashboard; the
+ // per-SP rows add a vs[network] filter (see withNetworkParam) so one dashboard
+ // serves every network the deployment monitors.
+ const dashboardUrl = getConfigUrl(runtimeConfig?.DASHBOARD_URL, import.meta.env.VITE_DASHBOARD_URL);
+ const logsUrl = getConfigUrl(runtimeConfig?.LOGS_URL, import.meta.env.VITE_LOGS_URL);
- // Approved-SP dashboard: per-network only (two separate curated dashboards; no global fallback).
- const approvedSpSources: Record = {
+ // Approved-SP dashboard: prefer the combined per-environment dashboard scoped
+ // with vs[network]; fall back to the legacy per-network dashboards so existing
+ // deployments keep working until infra sets APPROVED_SP_DASHBOARD_URL.
+ const approvedSpGlobal = getConfigUrl(
+ runtimeConfig?.APPROVED_SP_DASHBOARD_URL,
+ import.meta.env.VITE_APPROVED_SP_DASHBOARD_URL,
+ );
+ const approvedSpPerNetworkSources: Record = {
mainnet: {
runtime: runtimeConfig?.APPROVED_SP_DASHBOARD_URL_MAINNET,
build: import.meta.env.VITE_APPROVED_SP_DASHBOARD_URL_MAINNET,
@@ -105,9 +97,15 @@ const getConfig = (network: Network | null) => {
build: import.meta.env.VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION,
},
};
- const approvedSpDashboardUrl = network
- ? getConfigUrl(approvedSpSources[network].runtime, approvedSpSources[network].build)
+ const approvedSpPerNetwork = network
+ ? getConfigUrl(approvedSpPerNetworkSources[network].runtime, approvedSpPerNetworkSources[network].build)
: { safe: "", isInvalid: false };
+ let approvedSpDashboardUrl = approvedSpPerNetwork;
+ if (approvedSpGlobal.safe) {
+ approvedSpDashboardUrl = { safe: withNetworkParam(approvedSpGlobal.safe, network), isInvalid: false };
+ } else if (approvedSpGlobal.isInvalid) {
+ approvedSpDashboardUrl = approvedSpGlobal;
+ }
return {
dashboardUrl: dashboardUrl.safe,
@@ -180,8 +178,8 @@ export default function Landing() {
{approvedSpDashboardUrlInvalid && selectedNetwork && (
- Warning: APPROVED_SP_DASHBOARD_URL_{selectedNetwork.toUpperCase()} (or{" "}
- VITE_APPROVED_SP_DASHBOARD_URL_{selectedNetwork.toUpperCase()}) configured but invalid. Link
+ Warning: approved-SP dashboard URL (APPROVED_SP_DASHBOARD_URL or{" "}
+ APPROVED_SP_DASHBOARD_URL_{selectedNetwork.toUpperCase()}) configured but invalid. Link
unavailable.
)}
@@ -283,11 +281,17 @@ export default function Landing() {
const providerId = provider.providerId;
const metricsHref =
dashboardUrl && providerId != null
- ? buildBetterStackUrlWithProvider(dashboardUrl, providerId, "vs[provider_id]")
+ ? withNetworkParam(
+ buildBetterStackUrlWithProvider(dashboardUrl, providerId, "vs[provider_id]"),
+ selectedNetwork,
+ )
: "";
const logsHref =
logsUrl && providerId != null
- ? buildBetterStackUrlWithProvider(logsUrl, providerId, "vs[providerId]")
+ ? withNetworkParam(
+ buildBetterStackUrlWithProvider(logsUrl, providerId, "vs[providerId]"),
+ selectedNetwork,
+ )
: "";
return (
diff --git a/apps/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts
index 1b62de2b..9eda4711 100644
--- a/apps/web/src/vite-env.d.ts
+++ b/apps/web/src/vite-env.d.ts
@@ -7,14 +7,11 @@ interface ImportMeta {
readonly VITE_API_BASE_URL: string;
readonly VITE_PLAUSIBLE_DATA_DOMAIN?: string;
readonly VITE_DASHBOARD_URL?: string;
- readonly VITE_DASHBOARD_URL_MAINNET?: string;
- readonly VITE_DASHBOARD_URL_CALIBRATION?: string;
readonly VITE_DASHBOARD_EMBED_URL?: string;
+ readonly VITE_APPROVED_SP_DASHBOARD_URL?: string;
readonly VITE_APPROVED_SP_DASHBOARD_URL_MAINNET?: string;
readonly VITE_APPROVED_SP_DASHBOARD_URL_CALIBRATION?: string;
readonly VITE_LOGS_URL?: string;
- readonly VITE_LOGS_URL_MAINNET?: string;
- readonly VITE_LOGS_URL_CALIBRATION?: string;
};
}
@@ -23,13 +20,10 @@ interface Window {
API_BASE_URL?: string;
PLAUSIBLE_DATA_DOMAIN?: string;
DASHBOARD_URL?: string;
- DASHBOARD_URL_MAINNET?: string;
- DASHBOARD_URL_CALIBRATION?: string;
DASHBOARD_EMBED_URL?: string;
+ APPROVED_SP_DASHBOARD_URL?: string;
APPROVED_SP_DASHBOARD_URL_MAINNET?: string;
APPROVED_SP_DASHBOARD_URL_CALIBRATION?: string;
LOGS_URL?: string;
- LOGS_URL_MAINNET?: string;
- LOGS_URL_CALIBRATION?: string;
};
}
From 3951c768b7e2a389cebb67470162a70942bff950 Mon Sep 17 00:00:00 2001
From: silent-cipher
Date: Thu, 2 Jul 2026 01:33:46 +0530
Subject: [PATCH 3/3] chore: address copilot comments
---
apps/web/src/pages/Landing.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/pages/Landing.tsx b/apps/web/src/pages/Landing.tsx
index 35f9057d..5d4a74b9 100644
--- a/apps/web/src/pages/Landing.tsx
+++ b/apps/web/src/pages/Landing.tsx
@@ -179,8 +179,8 @@ export default function Landing() {
{approvedSpDashboardUrlInvalid && selectedNetwork && (
Warning: approved-SP dashboard URL (APPROVED_SP_DASHBOARD_URL or{" "}
- APPROVED_SP_DASHBOARD_URL_{selectedNetwork.toUpperCase()}) configured but invalid. Link
- unavailable.
+ APPROVED_SP_DASHBOARD_URL_{selectedNetwork.toUpperCase()}, or their VITE_-prefixed
+ build-time equivalents) configured but invalid. Link unavailable.
)}