This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Pathfinder API - A REST API for Pathfinder 1st Edition rules reference data (spells, classes). Built with ASP.NET Core Web API targeting .NET 10 and C# 14.
Live API: https://pfapi.whizkid.dev/
Uses mise as the task runner (defined in mise.toml):
mise run build # Build the project
mise run serve # Run development server
mise run clean # Clean build artifacts
mise run migratedb <name> # Create and run EF migration
mise run tools:install # Install/restore dotnet tools
mise run upgrade-deps # Update dependencies
mise run docker-build # Build container imageDirect dotnet commands:
dotnet build api/api.csproj
dotnet run --project api/api.csproj
dotnet ef migrations add <Name> --project api/api.csproj
dotnet ef database update --project api/api.csprojapi/- Main ASP.NET Core Web API projectData Helper/- Utility for importing spell data (not part of main API)
Controllers/- API endpoints (SpellController, ClassController, AdminController)Models/Database/- EF Core entities (Spell, Class, Descriptor, ClassLevel, SourceMaterial)Models/Request/- DTOs for incoming dataModels/Response/- DTOs for outgoing dataData/- DbContext, AutoMapper profiles, seed data helpersUtils/- Extension methods and configuration helpersMigrations/- EF Core migrations
Database type selected via Database:Type setting (env var: Database_Type):
postgres(default) - Uses connection details fromDatabase_*env varssqlite- Uses connection string from appsettings
Configuration priority: environment variables > appsettings.json (uses _ instead of : for env var names)
Primary Constructor DI (C# 12+):
public class SpellController(ApiContext context, IMapper mapper, ILogger<SpellController> logger) : ControllerBaseConditional Query Building - Use WhereIf<T>() extension for optional filters:
context.Spell
.WhereIf(school is not null, s => s.School == school.ToTitleCase())
.WhereIf(level.HasValue, s => s.ClassLevels.Any(cl => cl.Level == level))String Normalization - Use ToTitleCase() extension for case-insensitive lookups against stored data
Entity-DTO Mapping - AutoMapper profiles in Data/Mapper.cs handle all transformations
Spell.ClassLevels- Owned collection storing spell level per class (not a separate table)Class.SpellsPerDay- JSON-serializedIDictionary<int, IDictionary<int, int>>for spells-per-day tables- Seed data for Classes and Descriptors loaded from JSON in
Data/Seed/
Swagger UI available at root path (/) in all environments. API version: v1alpha1