Skip to content

Latest commit

 

History

History
122 lines (101 loc) · 7.31 KB

File metadata and controls

122 lines (101 loc) · 7.31 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Stash-box is an open-source video indexing and metadata API server for adult content, developed by Stash App. It serves as a community-driven database of metadata, similar to MusicBrainz for music. The application uses Go for the backend API with GraphQL, and React/TypeScript for the frontend.

Development Commands

Backend Development

  • make build - Build the Go binary with embedded frontend
  • make test - Run unit tests
  • make it - Run integration tests
  • make lint - Run golangci-lint on Go code
  • make fmt - Format Go code with gofmt
  • make generate - Regenerate GraphQL files, sqlc queries, and UI types
  • make generate-backend - Generate Go GraphQL files only
  • make generate-ui - Generate frontend GraphQL types only
  • make generate-sqlc - Generate sqlc query code only
  • make generate-goverter - Generate goverter type conversion code
  • make generate-dataloaders - Generate dataloader files

Frontend Development

  • make pre-ui - Install frontend dependencies via pnpm
  • make ui - Build the frontend for production
  • make ui-start - Start frontend development server
  • make ui-fmt - Format frontend code with prettier
  • make ui-validate - Run linting, format checking, and TypeScript validation

Complete Build Process

  • make stash-box - Full build: dependencies, generation, UI, linting, and binary

Database Setup

The application uses PostgreSQL extensions, created automatically by migrations (superuser required):

  • CREATE EXTENSION IF NOT EXISTS bktree; — pHash distance search (optional, only if installed on system)
  • CREATE EXTENSION IF NOT EXISTS pg_search; — ParadeDB full-text search (optional, only if installed on system)
  • Database schema migrations run automatically on startup
  • Migrations: Located in internal/database/migrations/postgres/ and executed sequentially by filename
  • Default connection string: postgres@localhost/stash-box?sslmode=disable
  • Query Code Generation: Uses sqlc (configured in sqlc.yaml) to generate type-safe Go code from SQL queries

Architecture

Backend (internal/ directory)

  • internal/api/ - GraphQL resolvers, HTTP handlers, and server setup
  • internal/auth/ - Authentication and authorization logic
  • internal/models/ - Data models, database entity definitions, and generated GraphQL types
  • internal/database/ - Database connection, migrations, and PostgreSQL-specific code
  • internal/queries/ - Type-safe database query code generated by sqlc from SQL files
  • internal/service/ - Business logic layer organized by entity (draft, edit, image, performer, scene, site, studio, tag, user, etc.)
  • internal/email/ - Email handling and templates
  • internal/image/ - Image processing, storage (local/S3), caching, and resizing
  • internal/storage/ - Storage abstraction layer for local/S3 backends
  • internal/config/ - Configuration management and parsing
  • internal/converter/ - Generated type conversion code via goverter
  • internal/dataloader/ - Generated DataLoader implementations for efficient GraphQL N+1 query resolution
  • internal/cron/ - Scheduled task management

Frontend (frontend/ directory)

  • frontend/src/pages/ - Page components organized by entity type (performers, scenes, studios, tags, users)
  • frontend/src/components/ - Reusable UI components and form elements
  • frontend/src/graphql/ - GraphQL queries, mutations, fragments, and generated TypeScript types
  • frontend/src/hooks/ - Custom React hooks for authentication, pagination, and state management
  • frontend/src/utils/ - Utility functions for data transformation, routing, and validation

Key Concepts

  • Entities: Performers, Scenes, Studios, Tags, Sites - the main data types in the system
  • Edits: All changes go through an edit/voting system before being applied to entities
  • Drafts: Temporary submissions that can be converted to edits
  • Roles: User permission system (READ, VOTE, EDIT, MODIFY, ADMIN) controlling access to operations
  • Images: Stored locally or on S3, with automatic resizing and caching capabilities
  • Fingerprints: Used for scene matching and duplicate detection via three algorithms:
    • MD5: Hash of entire video file for exact matching
    • OSHASH: OpenSubtitles Hash implementation - hash of leading and trailing 64kb of video file
    • PHASH: Perceptual hash based on a 5x5 grid of frames at regular intervals for content-based matching

GraphQL Schema

  • Schema files in graphql/schema/ define the API structure
  • Code generation via gqlgen creates Go resolvers and TypeScript types
  • Uses dataloader pattern to prevent N+1 queries when fetching related data
  • Authorization Directives: @hasRole(role: ROLE) implemented in internal/api/directives.go for field-level access control

Configuration

  • YAML configuration file (stash-box-config.yml) controls server behavior
  • Support for PostgreSQL connection settings, image storage, email, and security options
  • Environment variables can override configuration values

Testing

Backend Tests

  • Integration tests preferred: All tests should be integration tests utilizing the GraphQL API as much as possible
  • Unit tests: make test - Fast tests that don't require database (use sparingly)
  • Integration tests: make it - Full tests against PostgreSQL test database
  • Integration tests use PostgreSQL with default connection string postgres@localhost/stash-box-test?sslmode=disable
  • Can override test database via POSTGRES_DB environment variable
  • Warning: Integration tests drop all tables, never run against production database
  • Test files follow pattern internal/api/*_integration_test.go with GraphQL client helper in graphql_client_test.go
  • Test Data Setup: Tests use the service layer to create test data (see internal/api/integration_test.go for user setup example)

Frontend Tests

  • cd frontend && pnpm run validate - Runs ESLint, stylelint, prettier check, and TypeScript compilation
  • No unit tests currently implemented in frontend

Development Workflow

  1. Setup: Ensure PostgreSQL is running with required extensions
  2. Dependencies: Run make pre-ui to install frontend packages
  3. Development: Use make ui-start for frontend development server
  4. API Development: Modify GraphQL schema, run make generate to update code
  5. Database Changes: Add migration files to internal/database/migrations/postgres/ (executed sequentially by filename)
  6. Query Changes: Modify SQL files in internal/queries/sql/, run make generate-sqlc to regenerate Go code
  7. Testing: Run make lint test it before committing changes
  8. Build: Use make stash-box for complete production build

Important Notes

  • The application requires libvips for image processing on Linux systems
  • Default admin user (root) is created on first run with random password printed to stdout
  • Frontend development can use API key in .env.development.local to bypass login
  • Integration tests require PostgreSQL (default: postgres@localhost/stash-box-test?sslmode=disable)
  • pHash distance matching requires the bktree extension (built from the pg-spgist_hamming repo), installed via the production Dockerfile