From 12293366fdf4a7d2f1d6fa6d0575e92e862c0b7f Mon Sep 17 00:00:00 2001 From: Bradley Axen Date: Wed, 22 Jul 2026 12:14:37 -0700 Subject: [PATCH] Auto-connect configured production relay --- .../features/communities/communityStorage.test.mjs | 11 +++++++++++ .../src/features/communities/communityStorage.ts | 9 +++++++++ .../src/features/communities/useCommunityInit.ts | 14 ++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/desktop/src/features/communities/communityStorage.test.mjs b/desktop/src/features/communities/communityStorage.test.mjs index 4187d55d54..e55c1d7b7c 100644 --- a/desktop/src/features/communities/communityStorage.test.mjs +++ b/desktop/src/features/communities/communityStorage.test.mjs @@ -4,6 +4,7 @@ import test from "node:test"; import { clearCommunityStorage, migrateLegacyCommunityStorage, + shouldAutoConnectDefaultRelay, } from "./communityStorage.ts"; function createMemoryStorage(initial = {}) { @@ -46,6 +47,16 @@ test("migrateLegacyCommunityStorage does not overwrite new community state", () assert.equal(storage.getItem("buzz-active-community-id"), "new"); }); +test("signed-build relay defaults auto-connect during first-run onboarding", () => { + assert.equal( + shouldAutoConnectDefaultRelay("wss://buzz.block.builderlab.xyz"), + true, + ); + assert.equal(shouldAutoConnectDefaultRelay("ws://localhost:3000"), false); + assert.equal(shouldAutoConnectDefaultRelay("ws://127.0.0.1:3000"), false); + assert.equal(shouldAutoConnectDefaultRelay("not a valid relay"), false); +}); + test("clearCommunityStorage removes new and legacy state", () => { const storage = createMemoryStorage({ "buzz-communities": "new", diff --git a/desktop/src/features/communities/communityStorage.ts b/desktop/src/features/communities/communityStorage.ts index e406d9087f..3dc43bddd8 100644 --- a/desktop/src/features/communities/communityStorage.ts +++ b/desktop/src/features/communities/communityStorage.ts @@ -108,6 +108,15 @@ export function normalizeRelayUrl(url: string): string { return url; } +export function shouldAutoConnectDefaultRelay(relayUrl: string): boolean { + try { + const parsed = new URL(normalizeRelayUrl(relayUrl)); + return parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1"; + } catch { + return false; + } +} + export function deriveCommunityName(relayUrl: string): string { try { const url = new URL( diff --git a/desktop/src/features/communities/useCommunityInit.ts b/desktop/src/features/communities/useCommunityInit.ts index a50a8665c7..b44a56cc19 100644 --- a/desktop/src/features/communities/useCommunityInit.ts +++ b/desktop/src/features/communities/useCommunityInit.ts @@ -23,7 +23,10 @@ import { resetSidebarRelayConnectionCardState } from "@/features/sidebar/ui/useS import { clearMarkdownNodeCache } from "@/shared/ui/markdown/nodeCache"; import { resetVideoPlayerState } from "@/shared/ui/videoPlayerState"; -import { initFirstCommunity } from "./communityStorage"; +import { + initFirstCommunity, + shouldAutoConnectDefaultRelay, +} from "./communityStorage"; import type { Community } from "./types"; /** @@ -94,7 +97,14 @@ export function useCommunityInit( try { const defaultRelayUrl = await getDefaultRelayUrl(); - if (isSharedIdentity) { + // Signed builds carry a reviewed production relay. Treat that as the + // user's first community so first-run onboarding proceeds directly + // from machine setup into profile/team setup. Local development keeps + // the explicit add-a-community flow for ws://localhost defaults. + if ( + isSharedIdentity || + shouldAutoConnectDefaultRelay(defaultRelayUrl) + ) { const identity = await getIdentity(); if (cancelled) return; initFirstCommunity(defaultRelayUrl, identity.pubkey);