From 2555570ac590a470c5e08fc7f5e305741593548f Mon Sep 17 00:00:00 2001 From: Sean Olszewski Date: Wed, 13 May 2026 14:56:23 -0700 Subject: [PATCH 1/4] fix(examples): show connector URL section for invite code mode The generate() method already sets connectorURL for both connect URL and invite code modes, but the UI guard restricted the Connector URL section to connect URL mode only. Remove the mode check so the "Open Connector URL" and copy buttons appear whenever a connector URL is available. Co-Authored-By: Claude Opus 4.6 (1M context) --- swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift index 34400382..4cf609e7 100644 --- a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift +++ b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift @@ -121,7 +121,7 @@ struct ContentView: View { .disabled(model.isLoading) } - if model.mode == .connectUrl, let connectorURL = model.connectorURL { + if let connectorURL = model.connectorURL { Section("Connector URL") { HStack { Button("Open Connector URL", systemImage: "link") { From 092a9bd3ccc245356b52310d4f838895cb882fc8 Mon Sep 17 00:00:00 2001 From: Sean Olszewski Date: Wed, 13 May 2026 15:07:53 -0700 Subject: [PATCH 2/4] feat(react): add mobile deep-link button to invite code flow The InviteCodeState component only showed a QR code and invite code text, with no way to open the connector URL directly on mobile. Add the same mobile/desktop split used by QRState: on mobile, show an "Open World App" deep-link button; on desktop, show the QR code. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/States/InviteCodeState.tsx | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/js/packages/react/src/components/States/InviteCodeState.tsx b/js/packages/react/src/components/States/InviteCodeState.tsx index acb359e1..568abe9b 100644 --- a/js/packages/react/src/components/States/InviteCodeState.tsx +++ b/js/packages/react/src/components/States/InviteCodeState.tsx @@ -1,5 +1,6 @@ import { useEffect, useMemo, useState, type ReactElement } from "react"; import { __ } from "../../lang"; +import { useMedia } from "../../hooks/useMedia"; import { WorldcoinIcon } from "../Icons/WorldIcon"; import { LoadingIcon } from "../Icons/LoadingIcon"; import { QRCode } from "../../widget/QRCode"; @@ -35,6 +36,7 @@ export function InviteCodeState({ codeExpiresAt, isAwaitingUserConfirmation, }: InviteCodeStateProps): ReactElement { + const media = useMedia(); const now = useNowInSeconds(); const secondsRemaining = codeExpiresAt !== null ? Math.max(0, codeExpiresAt - now) : null; @@ -59,28 +61,43 @@ export function InviteCodeState({

{__("Connect your World ID")}

- {__("Scan with your phone to continue verifying")} + {media === "mobile" + ? __( + "You will be redirected to the app, please return to this page once you're done", + ) + : __("Scan with your phone to continue verifying")}

-
- {isAwaitingUserConfirmation && ( -
-
- -
-
-

{__("Connecting...")}

-

{__("Please continue in app")}

+ {/* Mobile: deep-link button */} + + + {/* Desktop: QR code */} +
+
+ {isAwaitingUserConfirmation && ( +
+
+ +
+
+

{__("Connecting...")}

+

{__("Please continue in app")}

+
-
- )} + )} -
-
-
- {connectorURI ? : null} +
+
+
+ {connectorURI ? : null} +
From 1c4bfbedd38e5cebab622f97c0d2c24c417fcf41 Mon Sep 17 00:00:00 2001 From: Sean Olszewski Date: Wed, 13 May 2026 15:14:20 -0700 Subject: [PATCH 3/4] feat(react): add always-visible "Open Connector URL" link to invite code widget The previous commit only added a mobile-only deep-link button. Add a visible link on all viewports so users can open the connector URL directly from the invite code widget. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/States/InviteCodeState.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/js/packages/react/src/components/States/InviteCodeState.tsx b/js/packages/react/src/components/States/InviteCodeState.tsx index 568abe9b..17c56e3b 100644 --- a/js/packages/react/src/components/States/InviteCodeState.tsx +++ b/js/packages/react/src/components/States/InviteCodeState.tsx @@ -103,6 +103,27 @@ export function InviteCodeState({
+ {connectorURI && ( + + {__("Open Connector URL")} + + )} + {inviteCode && (
Date: Wed, 13 May 2026 16:35:06 -0700 Subject: [PATCH 4/4] feat(examples): display invite code in iOS sample app Extract and display the invite code from the connector URL's `c` query parameter so developers can see the code alongside the connector URL. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../IDKitSampleApp/ContentView.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift index 4cf609e7..9e851773 100644 --- a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift +++ b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift @@ -138,6 +138,20 @@ struct ContentView: View { }.buttonStyle(.borderless) // This is necessary to prevent the entire section from forwarding tap gestures to the first button in the Section. } + if model.mode == .inviteCode, let code = model.inviteCode { + Section("Invite Code") { + HStack { + Text(code) + .font(.title.monospaced()) + .textSelection(.enabled) + Spacer() + Button("", systemImage: "clipboard") { + UIPasteboard.general.string = code + } + } + }.buttonStyle(.borderless) + } + if model.mode == .inviteCode, let expiresAt = model.codeExpiresAt { Section("Code Expiry") { HStack { @@ -178,6 +192,7 @@ final class SampleModel: ObservableObject { @Published var legacyPreset: SampleLegacyPreset = .orb @Published var mode: SampleMode = .connectUrl @Published var connectorURL: URL? + @Published var inviteCode: String? @Published var codeExpiresAt: Date? @Published var logs = "" @Published var isLoading = false @@ -241,6 +256,7 @@ final class SampleModel: ObservableObject { completionTask?.cancel() connectorURL = request.connectorURL + inviteCode = nil codeExpiresAt = nil pendingRequest = request pendingInviteCodeRequest = nil @@ -265,6 +281,8 @@ final class SampleModel: ObservableObject { // renders the landing page rather than redirecting into World // App. The shared "Connector URL" Section displays it. connectorURL = request.connectorURL + inviteCode = URLComponents(url: request.connectorURL, resolvingAgainstBaseURL: false)? + .queryItems?.first(where: { $0.name == "c" })?.value codeExpiresAt = request.expiresAt pendingRequest = nil pendingInviteCodeRequest = request