The same frontend can run inside Sage and in an ordinary browser. Use the SDK to detect the Sage runtime before creating a client, then call only methods backed by capabilities declared in the app manifest.

01

Detect Sage before creating a client

Import isSageRuntimeAvailable from sage-app-sdk and call it in the browser. It returns true when the frontend is running in Sage and false in an ordinary browser.

Do not use isSageBridgeInitialized for the initial environment check. That function tells you whether a Sage client has already been initialized, so it can still be false during normal Sage startup.

Detect the runtimets
import { isSageRuntimeAvailable } from "sage-app-sdk";

const runsInSage = isSageRuntimeAvailable();
02

Declare the method capability

Every Sage method your app uses must be backed by its capability in sage-manifest.json. The SDK method environment.getNetwork() uses the manifest capability environment.get_network.

Declare it as required for this example. Reading the active network does not require a user approval prompt, but Sage will still reject the method call if the capability was not declared and granted to the installed app.

Add to sage-manifest.jsonjson
{
  "permissions": {
    "capabilities": {
      "required": ["environment.get_network"]
    }
  }
}
03

Create the client and call Sage

Only call getSageClient() after runtime detection succeeds. The SDK initializes the Bridge client and returns its typed interfaces. environment.getNetwork() then returns the active network name, network ID, kind, ticker, address prefix, and precision.

This method has no per-request approval screen. The promise resolves directly when the capability is available, so the result can immediately drive network-aware labels, addresses, and API choices.

Read the active networkts
import {
  getSageClient,
  isSageRuntimeAvailable,
} from "sage-app-sdk";

export async function getAppEnvironment() {
  if (!isSageRuntimeAvailable()) {
    return { kind: "browser" } as const;
  }

  const sage = await getSageClient();
  const network = await sage.environment.getNetwork();

  return { kind: "sage", network } as const;
}
04

Try the live detector

The panel below runs the same detection and network call in this page. In a normal browser it reports Browser. When this guide is opened as an installed Sage app, it reports Sage and reads the active network through environment.getNetwork().

If Sage is detected but the network call fails, the panel shows the Bridge error separately. That commonly means the installed app still has an older manifest or does not have environment.get_network.

Live environment detectorOpen this page in a browser to run it
05

Keep the browser path useful

Treat the returned kind as an application capability boundary. Render the normal web experience for browser, and add Sage-specific behavior only for sage. Do not call getSageClient() and use a thrown error as routine browser detection.

When Sage unlocks functionality, make the browser fallback actionable. Show the exact public app URL to install into Sage and say what the user can do there instead of only reporting that Sage was not detected.

Handle Bridge failures separately from environment detection. Sage can be present while a call still fails because the installed manifest is stale, the capability is missing, or the wallet is unavailable. Show a retryable Sage error without breaking the browser version.

  • Build and finalize again after changing the manifest
  • Update the installed app so Sage receives the new capability declaration
  • Test the same production bundle in Sage and in a normal browser
Builder's note

Bridge APIs and client behavior can evolve. Verify implementation details against the Sage version you support, then test in both Sage and a normal browser.