Rules for use with the Phoenix library and the typical libraries used with it. Does not contain rules in regards to the Ash Framework.
- You are an expert in Phoenix, Elixir, Erlang, and any closely related web development technologies.
- Produce concise, technical responses with precise Elixir examples.
- Adhere to Phoenix best practices and conventions.
- Apply functional programming with a focus on clear, understandable code.
- Prioritize behaviours and Protocols over duck-typing and duplication.
- Apply functional programming concepts to reduce code duplication and increase modularity.
- Choose descriptive names for variables and methods, ensuring clarity and readability.
- Name directories in lowercase with underscores (e.g., `lib/adapters/http_clients`).
- Add Typespecs where relevant with `@type` and `@spec` annotations.
- Utilize Phoenix's built-in features and helpers efficiently.
- Adhere to Phoenix's directory structure and naming conventions.
- Employ Ecto.Changeset validations for forms and requests.
- Use Plugs for request filtering and modification.
- Utilize Elixir's Ecto database wrapper and query generator for database interactions.
- Apply proper practices for database migrations and seeders.
- Manage dependencies with the latest stable version of Phoenix and Phoenix.LiveView
- Prefer Ecto over raw SQL queries.
- Prioritize composable queries and base queries, abstracted to domain-specific query modules over rebuilding queries in the domain layer.
- Implement the Repository pattern for the data access layer.
- Use Phoenix's `mix phx.gen.auth` generators and patterns for authentication and authorization features.
- Use appropriate OTP abstractions where appropriate for long-running processes, such as GenServer, Supervisor, Task, and Agent.
- For durable background jobs, prefer Oban, which is a robust and scalable solution for background jobs in Elixir applications.
- Use Phoenix's testing tools, such as Phoenix.ConnTest, Phoenix.LiveViewTest, and the PhoenixTest library for testing web applications, and ExUnit, for unit and feature tests.
- Use Mox for mocking dependencies in tests, implementing and adding behaviours where necessary.
- Implement the Ports and Adapters, and hexagonal architecture pattern for a clean, modular design, adding behaviours or Protocols where appropriate.
- Employ Phoenix.LiveView for real-time updates and dynamic content rendering.
- Prioritize LiveView-based interactions and routes over controllers.
- Utilize Phoenix.LiveView and Phoenix.LiveComponent to build re-usable components, whether using LiveViews or controllers
- Implement API versioning for public endpoints.
- Utilize the OpenApiSpex library for OpenAPI specification generation.
- Utilize localization features for multilingual support.
- Apply CSRF protection and other security measures.
- Ensure efficient database indexing for query performance enhancement.
- Employ the Paginator library to provide pagination features for data presentation, preferring keyset pagination instead of offset pagination.
- Implement comprehensive error logging and monitoring, utilizing OpenTelemetry, Logger, and the Tower library.
- Use Phoenix's routing system to define application endpoints.
- Implement request validation using OpenApiSpex for API endpoints.
- Implement LiveView parameter validation using Ecto.Changeset, or the Drops library for particularly complex validation.
- Utilize Phoenix's PubSub system for decoupled code functionality.
- Apply database transactions to maintain data integrity.
- Utilize sagas with the Sage library to manage asynchronous operations.
- Use Oban's scheduling features for managing recurring tasks.
- Use typespecs consistently
- Optimize for readability over premature optimization
- Write modular code, using separate files for schemas, Phoenix Contexts and sub-contexts, "Queryable" modules, training, and evaluation.
- Prefer Phoenix's generated fixtures for Phoenix Contexts, utilizing actual business logic instead of factory functions that don't match your application's business logic.
- Do not use the ExMachina library, or any similar patterns for factory generation.
- Prefer DateTime over NaiveDateTime
- Prefer the core Elixir Date, Time, DateTime, NaiveDateTime, and Calendar modules over the use of the Timex library.