Plebeian Market Development Skill
Overview
This skill provides comprehensive guidance for developing features in the Plebeian Market application, a decentralized e-commerce marketplace built on the Nostr protocol. It ensures consistency with the established architecture, coding patterns, styling conventions, and Nostr integration approaches used throughout the codebase.
Use this skill when:
- Implementing new marketplace features (products, checkout, orders)
- Creating or modifying UI components
- Adding new routes or pages
- Working with Nostr events and NDK
- Fixing bugs or refactoring existing code
- Styling components with Tailwind CSS
- Managing state with TanStack Store or React Query
Technology Stack
Core Technologies
- Runtime: Bun (JavaScript runtime and bundler)
- Frontend: React 19 with TypeScript
- Routing: TanStack Router v1 (file-based routing)
- State Management: TanStack Store (client state) + React Query (server/async state)
- Styling: Tailwind CSS v4 with shadcn/ui components
- Nostr Protocol: NDK (Nostr Dev Kit) v2.15.2
- Backend: Bun WebSocket server
Refer to references/libraries.md for complete dependency list and versions.
Core Development Guidelines
1. Architecture Understanding
Before implementing features, understand the project structure:
/src/routes/ - File-based routing (use $param for dynamic segments, _layout prefix for layouts)
/src/components/ - React components (organized by feature or in ui/ for base components)
/src/lib/stores/ - TanStack Store state management
/src/queries/ - React Query hooks and query key factories
/src/hooks/ - Custom React hooks for reusable logic
Read references/architecture.md for detailed project structure and architectural patterns.
2. React Patterns
Follow these established patterns:
- Functional components only - No class components
- Custom hooks for reusable logic - Extract complex behavior into hooks
- Query key factory pattern - Organize React Query keys for cache invalidation
- Store + action creator pattern - Separate state from mutations
- Data transformation utilities - Use utility functions to extract data from Nostr events
For detailed patterns and code examples, read references/patterns.md.
3. Routing Implementation
TanStack Router uses file-based routing:
// Example: routes/products.$productId.tsx
export const Route = createFileRoute('/products/$productId')({
component: ProductDetailComponent,
})
function ProductDetailComponent() {
const { productId } = Route.useParams()
const productQuery = useSuspenseQuery(productQueryOptions(productId))
return <div>{/* render product */}</div>
}
Key conventions:
- Dynamic routes:
products.$productId.tsx
- Index routes:
products.index.tsx
- Layout routes:
_dashboard-layout.tsx
- Always run
bun run generate-routes after modifying route files
4. State Management Strategy
Use TanStack Store for:
- Client-side state (auth, cart, UI state)
- State that needs persistence (localStorage/IndexedDB)
- Simple reactive state updates
Use React Query for:
- Fetching data from Nostr relays
- Server/async state with caching
- Background synchronization
Example store implementation:
// lib/stores/example.ts
export const exampleStore = new Store<ExampleState>({
data: [],
isLoading: false,
})
export const exampleActions = {
updateData: (newData) => {
exampleStore.setState({ data: newData })
},
}
// Component usage
const state = useStore(exampleStore)
5. Styling with Tailwind CSS
Follow utility-first approach with Tailwind CSS v4:
- Use utility classes exclusively (no CSS modules or styled-components)
- Use
cn() helper for conditional classes
- Leverage shadcn/ui components from
components/ui/
- Follow established color palette (zinc scale for neutrals)
- Mobile-first responsive design
Example component styling:
import { cn } from '@/lib/utils'
<div className={cn(
"flex flex-col gap-4 p-4",
"border border-zinc-800 rounded-lg",
"hover:shadow-lg transition-shadow"
)}>
{children}
</div>
Read references/styling.md for comprehensive styling patterns, color schemes, and component examples.
6. Nostr Integration
All data flows through NDK (Nostr Dev Kit):
Fetching data:
export const fetchProducts = async (limit: number = 500) => {
const ndk = ndkActions.getNDK()
const events = await ndk.fetchEvents({
kinds: [30402], // Product listing kind
limit,
})
return Array.from(events).sort((a, b) => (b.created_at || 0) - (a.created_at || 0))
}
Publishing events:
export const publishProduct = async (productData) => {
const ndk = ndkActions.getNDK()
const event = new NDKEvent(ndk)
event.kind = 30402
event.tags = [
['d', productData.id],
['title', productData.title],
['price', productData.price.toString(), 'sats'],
]
await event.publish()
return event
}
Data transformation: Use utility functions to extract data from Nostr events:
const title = getProductTitle(product)
const price = getProductPrice(product)
const images = getProductImages(product)
Read references/nostr-integration.md for complete Nostr patterns, event kinds, authentication, and NDK usage.
Development Workflow
Adding a New Feature
- Plan the implementation:
- Identify if the feature needs new routes, components, stores, or queries - Review existing similar features for consistency - Check if shadcn/ui components can be reused
- Implement routes (if needed):
- Create route files in /src/routes/ following naming conventions - Use appropriate route types (index, dynamic, layout) - Run bun run generate-routes to update route tree
- Create components:
- Use functional components with TypeScript - Follow established styling patterns with Tailwind - Reuse shadcn/ui components where possible - Extract reusable logic into custom hooks
- Implement state management:
- Use TanStack Store for client state - Use React Query for Nostr data fetching - Follow query key factory pattern - Implement action creators for mutations
- Integrate with Nostr:
- Use NDK for all Nostr operations - Follow established event kinds and patterns - Implement proper error handling - Use data transformation utilities
- Test the implementation:
- Test in development mode (bun run dev) - Verify responsive design on mobile/desktop - Check dark mode compatibility - Test with Nostr relays
Modifying Existing Features
- Locate relevant files:
- Routes in /src/routes/ - Components in /src/components/ - Stores in /src/lib/stores/ - Queries in /src/queries/
- Understand existing patterns:
- Read through related code to understand current implementation - Check how similar features are implemented - Maintain consistency with existing patterns
- Make changes:
- Preserve existing patterns and conventions - Use established utilities and helpers - Update TypeScript types as needed - Keep changes focused and minimal
- Verify integration:
- Ensure changes don't break existing functionality - Test with real Nostr relays - Verify UI consistency
Common Tasks
Creating a New Route
- Create file in
/src/routes/ (e.g., newpage.tsx)
- Define route with
createFileRoute
- Implement component
- Run
bun run generate-routes
Adding a New UI Component
- Check if shadcn/ui has a suitable base component
- Create component in appropriate directory
- Use Tailwind utility classes for styling
- Follow established naming conventions (PascalCase)
- Export from component file
Fetching Data from Nostr
- Create query function in
/src/queries/
- Use query key factory pattern
- Create query options with
queryOptions()
- Use
useSuspenseQuery() or useQuery() in components
- Handle loading and error states
Managing Client State
- Create store in
/src/lib/stores/
- Define state interface
- Create action creators
- Use
useStore() hook in components
- Consider persistence (localStorage/IndexedDB)
Reference Documentation
For detailed information, read the reference files:
references/architecture.md - Project structure, architectural patterns, data flow
references/libraries.md - Complete list of libraries, versions, and usage notes
references/patterns.md - React patterns, hooks, routing, state management, and Nostr integration patterns
references/styling.md - Tailwind CSS usage, component styling, responsive design, theming
references/nostr-integration.md - NDK usage, event kinds, data fetching/publishing, authentication
Best Practices
- Consistency first - Follow established patterns throughout the codebase
- Use existing utilities - Leverage helper functions and custom hooks
- Type safety - Use TypeScript types and Zod schemas for validation
- Mobile-first - Design for mobile, enhance for desktop
- Error handling - Handle Nostr relay failures gracefully
- Performance - Use React Query caching, code splitting via routes
- Accessibility - Use semantic HTML and Radix UI accessible primitives
- Dark mode - Always consider dark mode variants in styling
Commands
Run these commands during development:
bun run dev # Start development server
bun run generate-routes # Generate route tree
bun run build # Build for production
bun run format # Format code with Prettier
Getting Help
When implementing features:
- Read relevant reference documentation for detailed patterns
- Search codebase for similar implementations
- Check existing components for reusable patterns
- Refer to library documentation for TanStack Router, React Query, NDK