3.5 KiB
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 includinguseNostr
anduseNostrQuery
/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.
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.
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.
import { useState } from 'react';
import { useCurrentUser } from "@/hooks/useCurrentUser";
import { useNostrPublish } from '@/hooks/useNostrPublish';
export function MyComponent() {
const [ data, setData] = useState<Record<string, string>>({});
const { user } = useCurrentUser();
const { mutate: createEvent } = useNostrPublish();
const handleSubmit = () => {
createEvent({ kind: 1, content: data.content });
};
if (!user) {
return <span>You must be logged in to use this form.</span>;
}
return (
<form onSubmit={handleSubmit} disabled={!user}>
{/* ...some input fields */}
</form>
);
}
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.