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

40
src/stores/feed.ts Normal file
View File

@@ -0,0 +1,40 @@
import { create } from "zustand";
import { NDKEvent } from "@nostr-dev-kit/ndk";
import { connectToRelays, fetchGlobalFeed } from "../lib/nostr";
interface FeedState {
notes: NDKEvent[];
loading: boolean;
connected: boolean;
error: string | null;
connect: () => Promise<void>;
loadFeed: () => Promise<void>;
}
export const useFeedStore = create<FeedState>((set, get) => ({
notes: [],
loading: false,
connected: false,
error: null,
connect: async () => {
try {
set({ error: null });
await connectToRelays();
set({ connected: true });
} catch (err) {
set({ error: `Connection failed: ${err}` });
}
},
loadFeed: async () => {
if (get().loading) return;
set({ loading: true, error: null });
try {
const notes = await fetchGlobalFeed(80);
set({ notes, loading: false });
} catch (err) {
set({ error: `Feed failed: ${err}`, loading: false });
}
},
}));

17
src/stores/ui.ts Normal file
View File

@@ -0,0 +1,17 @@
import { create } from "zustand";
type View = "feed" | "relays" | "settings";
interface UIState {
currentView: View;
sidebarCollapsed: boolean;
setView: (view: View) => void;
toggleSidebar: () => void;
}
export const useUIStore = create<UIState>((set) => ({
currentView: "feed",
sidebarCollapsed: false,
setView: (currentView) => set({ currentView }),
toggleSidebar: () => set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),
}));