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

# 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:

// 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:

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

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

// 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)