Working feed: NDK + relay connection + live notes from Nostr

- Tailwind CSS + Zustand + NDK installed and configured
- Sidebar with feed/relays/settings navigation
- Global feed view with live notes from relays
- Profile fetching with caching and deduplication
- Relay connection with timeout handling
- Note cards with avatar, name, timestamp, content
- Dark theme, monospace, no-slop UI
- Devtools enabled for debugging
This commit is contained in:
Jure
2026-03-08 14:54:04 +01:00
parent 43e14f9f04
commit b75ccb7f46
22 changed files with 2066 additions and 246 deletions

View File

@@ -0,0 +1,52 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
import { useProfile } from "../../hooks/useProfile";
import { timeAgo, shortenPubkey } from "../../lib/utils";
interface NoteCardProps {
event: NDKEvent;
}
export function NoteCard({ event }: NoteCardProps) {
const profile = useProfile(event.pubkey);
const name = profile?.displayName || profile?.name || shortenPubkey(event.pubkey);
const avatar = profile?.picture;
const time = event.created_at ? timeAgo(event.created_at) : "";
return (
<article className="border-b border-border px-4 py-3 hover:bg-bg-hover transition-colors duration-100">
<div className="flex gap-3">
{/* Avatar */}
<div className="shrink-0">
{avatar ? (
<img
src={avatar}
alt=""
className="w-9 h-9 rounded-sm object-cover bg-bg-raised"
loading="lazy"
onError={(e) => {
(e.target as HTMLImageElement).style.display = "none";
}}
/>
) : (
<div className="w-9 h-9 rounded-sm bg-bg-raised border border-border flex items-center justify-center text-text-dim text-xs">
{name.charAt(0).toUpperCase()}
</div>
)}
</div>
{/* Content */}
<div className="min-w-0 flex-1">
<div className="flex items-baseline gap-2 mb-0.5">
<span className="text-text font-medium truncate text-[13px]">
{name}
</span>
<span className="text-text-dim text-[11px] shrink-0">{time}</span>
</div>
<div className="note-content text-text text-[13px] break-words whitespace-pre-wrap">
{event.content}
</div>
</div>
</div>
</article>
);
}