+ {/* Header */}
+
+
+ {/* Tabs (only when we have both note and people results) */}
+ {searched && !isHashtag && noteResults.length > 0 && userResults.length > 0 && (
+
+ {(["notes", "people"] as const).map((tab) => (
+ setActiveTab(tab)}
+ className={`px-4 py-2 text-[11px] border-b-2 transition-colors ${
+ activeTab === tab
+ ? "border-accent text-accent"
+ : "border-transparent text-text-dim hover:text-text"
+ }`}
+ >
+ {tab === "notes" ? `notes (${noteResults.length})` : `people (${userResults.length})`}
+
+ ))}
+
+ )}
+
+ {/* Results */}
+
+ {/* Empty / idle state */}
+ {!searched && !loading && (
+
+
Search notes with NIP-50 full-text, or use #hashtag to browse topics.
+
NIP-50 requires relay support — results vary by relay.
+
+ )}
+
+ {searched && totalResults === 0 && (
+
+ No results for
{query} .
+ {!isHashtag &&
Your relays may not support NIP-50 full-text search.
}
+
+ )}
+
+ {/* People tab */}
+ {activeTab === "people" && userResults.map((user) => (
+
+ ))}
+
+ {/* Notes tab (or all notes for hashtag search) */}
+ {(activeTab === "notes" || isHashtag) && noteResults.map((event) => (
+
+ ))}
+
+ {/* People inline when only people results */}
+ {searched && noteResults.length === 0 && userResults.length > 0 && activeTab === "notes" && (
+ userResults.map((user) =>
)
+ )}
+
+
+ );
+}
diff --git a/src/components/sidebar/Sidebar.tsx b/src/components/sidebar/Sidebar.tsx
index 7e82aa9..9ccee53 100644
--- a/src/components/sidebar/Sidebar.tsx
+++ b/src/components/sidebar/Sidebar.tsx
@@ -7,6 +7,7 @@ import { shortenPubkey } from "../../lib/utils";
const NAV_ITEMS = [
{ id: "feed" as const, label: "feed", icon: "◈" },
+ { id: "search" as const, label: "search", icon: "⌕" },
{ id: "relays" as const, label: "relays", icon: "⟐" },
{ id: "settings" as const, label: "settings", icon: "⚙" },
] as const;
diff --git a/src/lib/nostr/client.ts b/src/lib/nostr/client.ts
index 5071c61..f55a00d 100644
--- a/src/lib/nostr/client.ts
+++ b/src/lib/nostr/client.ts
@@ -226,6 +226,31 @@ export async function fetchUserNotes(pubkey: string, limit = 30): Promise