mkstack/CONTEXT.md
2025-04-17 11:29:22 -05:00

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 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.

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.