Elixir Guidelines Skill
Use this skill when:
- Designing Elixir module structure
- Naming modules, functions, and variables
- Publishing Elixir libraries
- Following Elixir community standards
- Writing documentation for public APIs
When to Use
- Creating new Elixir projects
- Designing library APIs
- Choosing between idiomatic Elixir patterns
- Publishing packages to Hex.pm
- Ensuring code follows community conventions
Naming Conventions
Project Names
# GOOD - snake_case
my_app
my_project
user_auth_system
# BAD - camelCase or mixed
myApp
myProject
userAuthSystem
Module Names
# GOOD - PascalCase
defmodule MyApp.Accounts
defmodule MyApp.Accounts.User
# BAD - snake_case
defmodule my_app.accounts
defmodule my_app.accounts.user
Function Names
# GOOD - snake_case
def create_user(attrs)
def list_users(filter)
def calculate_total(items)
def get_user_by_email(email)
# BAD - camelCase
def createUser(attrs)
def listUsers(filter)
def calculateTotal(items)
def getUserByEmail(email)
Variable Names
# GOOD - snake_case
def process(user_data)
user_name = "John"
total_count = Enum.sum(items)
error_message = "Invalid input"
# BAD - camelCase
def process(userData)
userName = "John"
totalCount = Enum.sum(items)
errorMessage = "Invalid input"
Atoms
# GOOD - snake_case
:get_user_status
:handle_request
:timeout
:account_created
:network_error
:process_complete
:ready_to_send
:error_handling
:validation_failed
:retry_exhausted
:shutdown_requested
# BAD - camelCase
:getUserStatus
:handleRequest
:timeOut
:accountCreated
:networkError
Code Style
Function Parentheses
# GOOD - Single line, no parentheses
def func_name, do: result
# BAD - Unnecessary parentheses
def func_name, do: (result)
Pipe Operator
# GOOD - Transform data with pipes
result
|> step_one()
|> step_two()
|> step_three()
# BAD - Nested function calls
result = step_two(step_one())
final = step_three(result)
Pattern Matching
# GOOD - Match instead of conditionals
case result do
{:ok, value} -> value
{:error, reason} -> handle_error(reason)
:timeout -> retry()
:success -> process_value()
:failure -> log_error()
end
# BAD - Conditionals with if/else
if elem(result, 0) == :ok do
value = elem(result, 1)
else
reason = elem(result, 1)
handle_error(reason)
end
Library Publishing
Versioning
# Use semantic versioning
def project do
[
version: "1.0.0",
elixir: "~> 1.14"
]
end
Documentation
@moduledoc """
MyApp provides user authentication and management.
This module implements JWT-based authentication with role-based access control.
Supports user registration, login, password recovery, and profile management.
"""
@doc """
Authenticates a user with email and password.
## Parameters
- `email`: User's email address (string)
- `password`: User's password (string)
## Returns
- `{:ok, %User{}}`: User object on success
- `{:error, :invalid_credentials}`: Invalid email or password
- `{:error, :account_locked}`: Account is locked
## Examples
iex> MyApp.authenticate("user@example.com", "password")
{:ok, %User{id: 123, email: "user@example.com"}}
iex> MyApp.authenticate("user@example.com", "wrong")
{:error, :invalid_credentials}
"""
def authenticate(email, password) do
# implementation
end
Code Formatting
# Format all code
mix format
# Check formatting
mix format --check-formatted
# Format specific file
mix format lib/my_app.ex
Project Structure
# Standard Elixir project
my_app/
├── lib/ # Source code
│ └── my_app/
│ ├── application.ex
│ ├── accounts/
│ │ ├── user.ex
│ │ └── profile.ex
│ └── api.ex
├── test/ # Test files
│ ├── support/
│ └── my_app/
│ └── accounts_test.exs
├── mix.exs # Build configuration
├── README.md # Documentation
└── LICENSE # License file
Integration with ai-rules
Roles to Reference
- Architect: Use naming conventions when designing module structure
- Orchestrator: Follow naming conventions for all new code
- Backend Specialist: Reference style guide for code formatting
- Reviewer: Verify official standards compliance
- QA: Use official testing practices
- Frontend Specialist: Follow naming conventions in web modules
Skills to Reference
- api-design: Use naming conventions for API design
- test-generation: Use official testing practices (ExUnit)
- otp-patterns: Follow official naming conventions for OTP behaviors
- git-workflow: Follow community conventions for documentation
Documentation Links
- Elixir Library Guidelines: https://hexdocs.pm/elixir/library-guidelines.html
- Elixir Naming Conventions: https://hexdocs.pm/elixir/naming-conventions.html
- Community Style Guide: https://github.com/christopheradams/elixir_style_guide
- Writing Documentation: https://hexdocs.pm/elixir/writing-documentation.html
Best Practices
DO:
- ✅ Use snake_case for projects, functions, and variables
- ✅ Use PascalCase for modules
- ✅ Use snake_case for atoms
- ✅ Add @moduledoc and @doc to public modules/functions
- ✅ Run mix format to match community style
- ✅ Use pipe operator for transformations
- ✅ Use pattern matching instead of conditionals
- ✅ Use semantic versioning for packages
- ✅ Write comprehensive documentation with examples
DON'T:
- ❌ Use camelCase for projects, functions, or variables
- ❌ Use snake_case for module names
- ❌ Skip documentation for public APIs
- ❌ Ignore formatting (run mix format)
- ❌ Use nested function calls instead of pipes
- ❌ Use if/else when pattern matching is clearer
- ❌ Ignore semantic versioning
- ❌ Write code without type specs
- ❌ Create APIs without documentation
Summary
Follow official Elixir community standards to ensure:
- ✅ Consistent naming conventions
- ✅ Clean, readable code
- ✅ Well-documented public APIs
- ✅ Proper library structure
- ✅ Community-accepted patterns