diff --git a/packages/app/lib/envVars.native.ts b/packages/app/lib/envVars.native.ts
index 38ea8d2b32..8ed1aaf5ab 100644
--- a/packages/app/lib/envVars.native.ts
+++ b/packages/app/lib/envVars.native.ts
@@ -6,6 +6,7 @@ const envVars = (Constants.expoConfig?.extra ?? {}) as Record<
   string | undefined
 >;
 
+export const DEV_SHIP_URL = '';
 export const NOTIFY_PROVIDER = envVars.notifyProvider ?? 'rivfur-livmet';
 export const NOTIFY_SERVICE = envVars.notifyService ?? 'groups-native';
 export const POST_HOG_API_KEY = envVars.postHogApiKey ?? '';
@@ -46,6 +47,7 @@ export const INVITE_SERVICE_IS_DEV =
   envVars.inviteServiceIsDev === 'true' ? true : undefined;
 
 export const ENV_VARS = {
+  DEV_SHIP_URL,
   NOTIFY_PROVIDER,
   NOTIFY_SERVICE,
   POST_HOG_API_KEY,
diff --git a/packages/app/lib/envVars.ts b/packages/app/lib/envVars.ts
index caf0572c52..b7b6f11f14 100644
--- a/packages/app/lib/envVars.ts
+++ b/packages/app/lib/envVars.ts
@@ -2,6 +2,7 @@
 // @ts-ignore – only valid on web
 const env = import.meta.env;
 const envVars = {
+  devShipUrl: env.VITE_SHIP_URL,
   notifyProvider: env.VITE_NOTIFY_PROVIDER,
   notifyService: env.VITE_NOTIFY_SERVICE,
   postHogApiKey: env.VITE_POST_HOG_API_KEY,
@@ -30,6 +31,7 @@ const envVars = {
   inviteServiceIsDev: env.VITE_INVITE_SERVICE_IS_DEV,
 } as Record<string, string | undefined>;
 
+export const DEV_SHIP_URL = envVars.devShipUrl ?? '';
 export const NOTIFY_PROVIDER = envVars.notifyProvider ?? 'rivfur-livmet';
 export const NOTIFY_SERVICE = envVars.notifyService ?? 'groups-native';
 export const POST_HOG_API_KEY = envVars.postHogApiKey ?? '';
@@ -67,6 +69,7 @@ export const INVITE_SERVICE_IS_DEV =
   envVars.inviteServiceIsDev === 'true' ? true : undefined;
 
 export const ENV_VARS = {
+  DEV_SHIP_URL,
   NOTIFY_PROVIDER,
   NOTIFY_SERVICE,
   POST_HOG_API_KEY,
diff --git a/packages/shared/src/api/urbit.ts b/packages/shared/src/api/urbit.ts
index 015751ce12..8bc8a67f58 100644
--- a/packages/shared/src/api/urbit.ts
+++ b/packages/shared/src/api/urbit.ts
@@ -2,7 +2,8 @@ import { Noun } from '@urbit/nockjs';
 import _ from 'lodash';
 
 import { createDevLogger, escapeLog, runIfDev } from '../debug';
-import { AnalyticsEvent } from '../domain';
+import { AnalyticsEvent, getConstants } from '../domain';
+import * as Hosting from '../domain/hosting';
 import {
   AuthError,
   ChannelStatus,
@@ -106,7 +107,19 @@ export const getCurrentUserIsHosted = () => {
     throw new Error('Client not initialized');
   }
 
-  return client.url.endsWith('tlon.network');
+  // prefer referencing client URL if available
+  if (client.url) {
+    return Hosting.nodeUrlIsHosted(client.url);
+  }
+
+  /*
+    On web, client URL is implicit based on location
+    Note: during development, the true URL is supplied via the environment. Localhost is
+    set up to redirect there
+  */
+  const env = getConstants();
+  const implicitUrl = __DEV__ ? env.DEV_SHIP_URL : window.location.hostname;
+  return Hosting.nodeUrlIsHosted(implicitUrl);
 };
 
 export function internalConfigureClient({
@@ -119,7 +132,6 @@ export function internalConfigureClient({
   onQuitOrReset,
   onChannelStatusChange,
 }: ClientParams) {
-  logger.log('configuring client', shipName, shipUrl);
   config.client = config.client || new Urbit(shipUrl, '', '', fetchFn);
   config.client.verbose = verbose;
   config.client.nodeId = preSig(shipName);
diff --git a/packages/shared/src/domain/constants.ts b/packages/shared/src/domain/constants.ts
index 64b22ade64..dee9efa7bc 100644
--- a/packages/shared/src/domain/constants.ts
+++ b/packages/shared/src/domain/constants.ts
@@ -1,6 +1,7 @@
 const TLON_NAMESPACE = 'tlonEnv';
 
 interface Constants {
+  DEV_SHIP_URL: string;
   NOTIFY_PROVIDER: string;
   NOTIFY_SERVICE: string;
   POST_HOG_API_KEY: string;
diff --git a/packages/shared/src/domain/hosting.ts b/packages/shared/src/domain/hosting.ts
index 692fd961c6..1accc95621 100644
--- a/packages/shared/src/domain/hosting.ts
+++ b/packages/shared/src/domain/hosting.ts
@@ -50,3 +50,7 @@ export enum HostedNodeStatus {
   UnderMaintenance = 'UnderMaintenance',
   Unknown = 'Unknown',
 }
+
+export function nodeUrlIsHosted(url: string) {
+  return url.endsWith('tlon.network') || url.endsWith('.test.tlon.systems');
+}