diff --git a/CLAUDE.md b/CLAUDE.md
index f5c49f8..3918f6b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -340,6 +340,9 @@ This allows `applyTheme()` to switch themes at runtime.
- Example: `formatTimestamp(event.created_at, "long")` instead of manual `toLocaleDateString()`
- **File Organization**: By domain (`nostr/`, `ui/`, `services/`, `hooks/`, `lib/`)
- **State Logic**: All UI state mutations go through `src/core/logic.ts` pure functions
+- **Shared Components**:
+ - **`RelayLink`** (`src/components/nostr/RelayLink.tsx`): Always use this when displaying relay URLs. It shows the relay favicon, handles insecure `ws://` warnings, and opens the relay detail window on click. Never render raw relay URL strings — use `` instead.
+ - **`UserName`** (`src/components/nostr/UserName.tsx`): Always use this for displaying user pubkeys. Accepts optional `relayHints` prop for fetching profiles from specific relays.
## Important Patterns
diff --git a/src/components/nostr/UserName.tsx b/src/components/nostr/UserName.tsx
index a3d301e..52bfc4e 100644
--- a/src/components/nostr/UserName.tsx
+++ b/src/components/nostr/UserName.tsx
@@ -10,6 +10,7 @@ interface UserNameProps {
pubkey: string;
isMention?: boolean;
className?: string;
+ relayHints?: string[];
}
/**
@@ -25,9 +26,14 @@ interface UserNameProps {
* - Premium supporters (2.1k+ sats/month): Flame badge in their username color
* - Regular supporters: Yellow flame badge (no username color change)
*/
-export function UserName({ pubkey, isMention, className }: UserNameProps) {
+export function UserName({
+ pubkey,
+ isMention,
+ className,
+ relayHints,
+}: UserNameProps) {
const { addWindow, state } = useGrimoire();
- const profile = useProfile(pubkey);
+ const profile = useProfile(pubkey, relayHints);
const isGrimoire = isGrimoireMember(pubkey);
const { isSupporter, isPremiumSupporter } = useIsSupporter(pubkey);
const displayName = getDisplayName(pubkey, profile);
diff --git a/src/components/nostr/kinds/TrustedProviderListDetailRenderer.tsx b/src/components/nostr/kinds/TrustedProviderListDetailRenderer.tsx
index 3285d3e..7383c7f 100644
--- a/src/components/nostr/kinds/TrustedProviderListDetailRenderer.tsx
+++ b/src/components/nostr/kinds/TrustedProviderListDetailRenderer.tsx
@@ -1,12 +1,11 @@
import { NostrEvent } from "@/types/nostr";
import { UserName } from "../UserName";
+import { RelayLink } from "../RelayLink";
import {
getTrustedProviders,
hasEncryptedProviders,
- formatKindTag,
} from "@/lib/nip85-helpers";
-import { Shield, Lock, Radio } from "lucide-react";
-import { Badge } from "@/components/ui/badge";
+import { Shield, Lock } from "lucide-react";
/**
* Trusted Provider List Detail Renderer (Kind 10040)
@@ -50,28 +49,18 @@ export function TrustedProviderListDetailRenderer({
{providers.map((p, i) => (
- {/* Metric badge */}
-
- {formatKindTag(p.kindTag)}
-
-
- {/* Provider */}
-
- Provider:
-
-
+ {/* Provider name */}
+
{/* Relay */}
-
-
- {p.relay}
-
+
))}
diff --git a/src/components/nostr/kinds/TrustedProviderListRenderer.tsx b/src/components/nostr/kinds/TrustedProviderListRenderer.tsx
index 30de9cb..1f5ca50 100644
--- a/src/components/nostr/kinds/TrustedProviderListRenderer.tsx
+++ b/src/components/nostr/kinds/TrustedProviderListRenderer.tsx
@@ -5,6 +5,7 @@ import {
} from "./BaseEventRenderer";
import { Badge } from "@/components/ui/badge";
import { UserName } from "../UserName";
+import { RelayLink } from "../RelayLink";
import {
getTrustedProviders,
hasEncryptedProviders,
@@ -33,7 +34,7 @@ export function TrustedProviderListRenderer({ event }: BaseEventProps) {
{/* Compact summary */}
- {providers.length} mapping{providers.length !== 1 ? "s" : ""}
+ {providers.length} provider{providers.length !== 1 ? "s" : ""}
{hasEncrypted && (
- {/* Provider preview: show unique service keys */}
+ {/* Provider preview */}
{previewProviders.length > 0 && (
-
+
{previewProviders.map((p, i) => (
-
- {p.kindTag}
-
-
+
+ on
+
))}
{providers.length > 3 && (