piclets / CLAUDE.md
Fraser's picture
RESET TO MONSTER DISCOVERY SYSTEM
565e57b
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Svelte 5 + TypeScript + Vite single-page application for a discovery-based creature collection game called "Pictuary". It uses the latest Svelte 5 with runes syntax (`$state()`, `$derived()`, etc.).
### Main Features
- **Monster Discovery**: Upload images β†’ AI identifies objects and generates/retrieves canonical "Piclets"
- **Canonical System**: Each real-world object has ONE canonical Piclet, with variations tracked
- **Collection Management**: Track discovered Piclets with metadata (discoverer, rarity, variations)
- **Activity Feed**: Leaderboard showing top discoverers and recent finds
- **Server Integration**: Connects to `../piclets-server/` for canonical Piclet database
## Essential Commands
```bash
# Install dependencies
npm install
# Development server with HMR
npm run dev
# Type checking
npm run check
# Production build (outputs to dist/)
npm run build
# Preview production build
npm run preview
# Run tests
npm test
# Run tests with UI
npm run test:ui
```
## Architecture
### Component Structure
- Components use `.svelte` files with TypeScript support via `lang="ts"` in script tags
- Main entry: `src/main.ts` β†’ mounts `src/App.svelte`
- Reusable components go in `src/lib/`
- Uses Svelte 5 runes syntax (not Svelte 4 syntax)
### Key Components
- **Pages**: `Scanner.svelte` (discovery), `Pictuary.svelte` (collection), `Activity.svelte` (leaderboard/feed)
- **Monster Discovery**: `PicletGenerator.svelte`, `PicletResult.svelte` with canonical/variation detection
- **Server Integration**: Services for canonical Piclet lookup and creation
- **Piclet Management**: `PicletCard.svelte`, `PicletDetail.svelte` with discovery metadata
- **Database**: IndexedDB with `schema.ts` for local caching + server sync for canonical data
### Key Patterns
1. **State Management**: Use `$state()` rune for reactive state
2. **TypeScript**: All components should use `<script lang="ts">`
3. **Imports**: Use ES module imports, components are default exports
4. **Styling**: Component styles are scoped by default, global styles in `src/app.css`
5. **Database**: Hybrid approach - IndexedDB for local state, server API for canonical Piclets
6. **Discovery Flow**: Caption β†’ Extract object β†’ Server lookup β†’ Return canonical/variation/new
### Build Configuration
- Vite handles bundling with `vite.config.ts`
- TypeScript config uses project references (tsconfig.json + tsconfig.app.json)
- Production builds go to `dist/` directory
## External Dependencies
### Gradio Client Integration
This project uses Gradio Client for connecting to Hugging Face Spaces. **Important**: Use the CDN-based approach, not npm packages.
**Setup in App.svelte:**
```javascript
// CDN imports are loaded dynamically
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
window.gradioClient = { Client };
```
**Usage in other files:**
```typescript
// Access via window.gradioClient (types are declared in vite-env.d.ts)
const client = await window.gradioClient.Client.connect("space-name");
```
**Current Gradio Connections:**
- **Flux Image Generation**: `Fraser/flux`
- **Joy Caption**: `fancyfeast/joy-caption-alpha-two` (configured for object identification)
- **Qwen Text Generation**: For generating Piclet concepts from object captions
### Server Integration
- **Endpoint**: `../piclets-server/` (local development)
- **Canonical Lookup**: POST `/api/piclets/search` with object keywords
- **Create Canonical**: POST `/api/piclets/canonical` for new discoveries
- **Create Variation**: POST `/api/piclets/variation` with canonicalId
- **Activity Feed**: GET `/api/activity/recent` for global discoveries
**Build Notes:**
- DO NOT install Gradio Client via npm (`npm install @gradio/client`) - it causes build failures
- The CDN approach ensures compatibility with Vite bundling
- All Gradio connections should use the established pattern from App.svelte
### Discovery Architecture
#### Object Identification Flow
1. **Image Caption**: Joy Caption extracts object type and visual attributes
2. **Object Extraction**: Parse caption for primary object ("pillow", "pyramid", etc.)
3. **Server Lookup**: Search for exact match or close variations
4. **Response Types**:
- **Exact Match**: Return existing canonical Piclet + increment scan count
- **Close Match**: Create variation of canonical + link to parent
- **No Match**: Create new canonical Piclet + register discoverer
#### Rarity Calculation
- Track `scanCount` per canonical Piclet
- Rarity score = 1 / scanCount (lower scan count = higher rarity)
- Display rarity tiers: Common, Uncommon, Rare, Epic, Legendary
## Troubleshooting
### Common Build Issues
- **Gradio Client build failures**: Ensure you're NOT using `npm install @gradio/client`. Use CDN imports only.
- **Type errors**: Run `npm run check` to identify TypeScript issues before building
- **Missing dependencies**: Run `npm install` if packages are missing
### Discovery System Issues
- **Object extraction**: Ensure Joy Caption is set to "Descriptive" mode with focus on object type
- **Server connection**: Verify `../piclets-server/` is running on expected port
- **Variation detection**: Check keyword matching algorithm for false positives
- **Rarity calculation**: Ensure scanCount is properly incremented on each discovery
### Performance
- **Large image files**: Consider image compression before upload
- **Server latency**: Cache canonical Piclets locally after first fetch
- **Search optimization**: Use keyword indexing for O(1) lookups
- **Activity feed**: Paginate results, cache recent discoveries
## Implementation Strategy
### Caption Processing
```typescript
// Example caption processing for object extraction
const caption = "A velvet blue pillow with golden tassels on a couch";
const primaryObject = extractObject(caption); // "pillow"
const attributes = extractAttributes(caption); // ["velvet", "blue"]
```
### Server Communication
```typescript
// Canonical lookup
const result = await fetch('/api/piclets/search', {
method: 'POST',
body: JSON.stringify({
object: 'pillow',
attributes: ['velvet', 'blue']
})
});
// Response types
interface CanonicalMatch {
type: 'exact' | 'variation' | 'new';
piclet: PicletInstance;
canonicalId?: string;
discoveredBy?: string;
scanCount: number;
}
```
### Database Schema Updates
- Remove: level, xp, hp, attack, defense, speed, moves, battleStats
- Add: canonicalId, isCanonical, discoveredBy, discoveredAt, scanCount, variations[]
- Keep: typeId, primaryType, tier, imageUrl, description, concept
## Important Notes
- This is NOT SvelteKit - no routing, SSR, or API routes
- HMR preserves component state (can be toggled in vite.config.ts)
- All paths in imports should be relative or use `$lib` alias for src/lib
- Hybrid storage: IndexedDB for local cache, server for canonical truth
- Object abstraction level is critical - "pillow" not "decorative cushion"
- Variations limited to 2-3 meaningful attributes (material, style, color)