# Project Overview This project is a Nostr client application built with React 19.x, TailwindCSS 3.x, Vite, shadcn/ui, and Nostrify. ## Technology Stack - **React 19**: Latest version of React with improved performance and features - **TailwindCSS 3.x**: Utility-first CSS framework for styling - **Vite**: Fast build tool and development server - **shadcn/ui**: Unstyled, accessible UI components built with Radix UI and Tailwind - **Nostrify**: Nostr protocol framework for Deno and web - **React Router**: For client-side routing - **TanStack Query**: For data fetching, caching, and state management - **TypeScript**: For type-safe JavaScript development ## Project Structure - `/src/components/`: UI components including NostrProvider for Nostr integration - `/src/hooks/`: Custom hooks including `useNostr` and `useNostrQuery` - `/src/pages/`: Page components used by React Router - `/src/lib/`: Utility functions and shared logic - `/public/`: Static assets ## Nostr Protocol Integration This project comes with custom hooks for querying and publishing events on the Nostr network. ### The `useNostr` Hook The `useNostr` hook returns an object containing a `nostr` property, with `.query()` and `.event()` methods for querying and publishing Nostr events respectively. ```typescript import { useNostr } from '@nostrify/react'; function useCustomHook() { const { nostr } = useNostr(); // ... } ``` ### Query Nostr Data with `useNostr` and Tanstack Query When querying Nostr, the best practice is to create custom hooks that combine `useNostr` and `useQuery` to get the required data. ```typescript import { useNostr } from '@nostrify/react'; import { useQuery } from '@tanstack/query'; function usePosts() { const { nostr } = useNostr(); return useQuery({ queryKey: ['posts'], queryFn: async () => { const events = await nostr.query([{ kinds: [1], limit: 20 }]); return events; // these events could be transformed into another format }, }); } ``` The data may be transformed into a more appropriate format if needed, and multiple calls to `nostr.query()` may be made in a single queryFn. ### The `useNostrPublish` Hook To publish events, use the `useNostrPublish` hook in this project. ```tsx import { useState } from 'react'; import { useCurrentUser } from "@/hooks/useCurrentUser"; import { useNostrPublish } from '@/hooks/useNostrPublish'; export function MyComponent() { const [ data, setData] = useState>({}); const { user } = useCurrentUser(); const { mutate: createEvent } = useNostrPublish(); const handleSubmit = () => { createEvent({ kind: 1, content: data.content }); }; if (!user) { return You must be logged in to use this form.; } return (
{/* ...some input fields */}
); } ``` The `useCurrentUser` hook should be used to ensure that the user is logged in before they are able to publish Nostr events. ## Development Practices - Uses React Query for data fetching and caching - Follows shadcn/ui component patterns - Implements Path Aliases with `@/` prefix for cleaner imports - Uses Vite for fast development and production builds - Component-based architecture with React hooks - Default connection to multiple Nostr relays for network redundancy ## Build & Deployment - Build for production: `npm run build` - Development build: `npm run build:dev` ## Testing Your Changes Use `npm run build` to check for build errors.