diff --git a/frontend/src/lib/network.ts b/frontend/src/lib/network.ts
index 5976109..e8b43ab 100644
--- a/frontend/src/lib/network.ts
+++ b/frontend/src/lib/network.ts
@@ -10,3 +10,19 @@ export const USDX_ISSUER = import.meta.env.VITE_USDX_ISSUER ?? "";
export const POOL_ID = import.meta.env.VITE_POOL_ID ?? "";
export const isConfigured = Boolean(CBRL_ISSUER && USDX_ISSUER);
+
+/**
+ * A hard guard, mirroring the backend's `assertTestnet` (src/lib/network.ts): this dApp is
+ * testnet-only. It signs and submits destructive, irreversible ops (freeze, clawback, lock),
+ * so it must never operate against the public network. Returns an error message when the
+ * configured passphrase is PUBLIC so the caller can fail visibly instead of silently signing.
+ */
+export function testnetGuardError(): string | null {
+ if (NETWORK_PASSPHRASE === Networks.PUBLIC) {
+ return (
+ "Stellar Mint is a testnet teaching dApp. It refuses to run against the PUBLIC network. " +
+ "Set VITE_NETWORK_PASSPHRASE to the testnet passphrase."
+ );
+ }
+ return null;
+}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 5662951..0861fb0 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -3,15 +3,31 @@ import { createRoot } from "react-dom/client";
import { Buffer } from "buffer";
import { StoreProvider } from "./store.js";
import App from "./App.js";
+import { testnetGuardError } from "./lib/network.js";
import "./index.css";
// stellar-sdk expects Node's Buffer in the browser.
globalThis.Buffer = globalThis.Buffer ?? Buffer;
-createRoot(document.getElementById("root")!).render(
-