# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **Mila** is a self-hostable membership management system for small to mid-sized clubs, built with Elixir/Phoenix and the Ash Framework. **Tech Stack:** - Elixir 1.18.3 / Erlang/OTP 27.3.4 - Phoenix 1.8 with LiveView 1.1 - Ash Framework 3.0 with AshPostgres, AshAuthentication, AshPhoenix - PostgreSQL 17 (dev) / 16 (prod) - Tailwind CSS 4 + DaisyUI - Just (task runner) ## Essential Commands ```bash # Development just run # Start full dev environment (DB + app) just test # Run test suite just test path/to/test.exs # Run single test file just test path/to/test.exs:42 # Run single test at line just lint # Format check + compile warnings + credo + gettext just audit # Security audit (sobelow + deps.audit + hex.audit) just format # Auto-format code just ci-dev # Run lint + audit + test (pre-commit check) # Database just reset-database # Reset dev and test databases just migrate-database # Run migrations (mix ash.setup) # Migrations just regen-migrations name # Rollback untracked migrations and regenerate mix ash.codegen --name description # Generate new migration # Gettext (i18n) just gettext # Extract and merge translations ``` ## Architecture ### Ash Domains (lib/) The codebase follows domain-driven design using Ash Framework: - **`lib/accounts/`** - User authentication domain (AshAuthentication) - `User` - Authenticated users with OIDC/password strategies - `Token` - Auth tokens - **`lib/membership/`** - Core membership domain - `Member` - Club members with personal information - `CustomField` - Admin-defined custom fields - `CustomFieldValue` - Values for custom fields per member - `Setting` - Application settings - **`lib/membership_fees/`** - Fee management domain - `MembershipFeeType` - Fee type definitions - `MembershipFeeCycle` - Fee cycles - **`lib/mv/authorization/`** - Authorization domain (in development) - `Role` - User roles referencing permission sets - `PermissionSets` - Permission definitions - **`lib/mv/`** - Core application modules - `email_sync/` - Email synchronization between User and Member - `repo.ex`, `application.ex`, `secrets.ex` - **`lib/mv_web/`** - Phoenix web layer - `live/` - LiveView modules - `components/` - Reusable UI components - `controllers/` - HTTP controllers ### Key Patterns **Ash Resources:** Each resource defines its own actions, validations, policies, and code interface. Use the domain's code interface for all operations: ```elixir Mv.Membership.create_member(attrs) # Not Ash.create(Member, attrs) ``` **Email Sync:** User and Member emails are synchronized - User email is the source of truth. **LiveView:** Primary UI pattern. Controllers are thin; delegate to Ash domains. ## Testing Tests mirror lib/ structure in `test/`. Use: - `Mv.DataCase` for database tests - `MvWeb.ConnCase` for controller/LiveView tests - `async: true` when possible for parallel execution ## Important Notes - Run `just ci-dev` before each commit to catch issues - All modules require `@moduledoc` documentation (enforced by Credo) - Follow existing Ash DSL section ordering (see `.formatter.exs` Spark config) - Commit messages use conventional format: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:` - Refer to `CODE_GUIDELINES.md` for detailed coding standards - Refer to `docs/` for feature-specific documentation