developing-elixir
Developing Elixir
Expert guidance for building robust, scalable Elixir/Phoenix applications.
Quick Start
For immediate help, identify your task type and consult the relevant reference:
| Working On | Reference File | Key Topics |
|---|---|---|
| Controllers, routing, plugs, channels | phoenix-framework | MVC patterns, authentication, WebSockets |
| LiveView components, forms | liveview | Real-time UI, hooks, streams |
| Schemas, queries, migrations | ecto-database | Associations, changesets, transactions |
| Safe migrations, schema changes | safe-ecto-migrations | Concurrent indexes, zero-downtime DDL |
| GenServer, Supervisor, processes | otp-patterns | Fault tolerance, state management |
| Domain modeling, value objects | functional-modeling | Parse-don't-validate, DDD |
| GraphQL schemas, resolvers | graphql-absinthe | Subscriptions, dataloader |
| ExUnit tests, TDD workflow | testing-exunit | Test organization, assertions |
TDD Phase Awareness
All guidance in this skill is phase-aware. Identify your current phase:
RED Phase (Writing Failing Tests)
- Write the smallest test that captures intent
- Use hard-coded values directly in tests
- Skip edge cases and parameterization initially
- Focus on what behavior the test demands
GREEN Phase (Making Tests Pass)
- RESIST over-engineering at all costs
- Start with pure functions and simple data structures
- Recommend primitives and maps before structs
- Defer abstractions, smart constructors, and validations
- Focus only on making the current test pass
REFACTOR Phase (Improving Design)
- NOW apply proper patterns and abstractions
- Extract value objects from primitives
- Add comprehensive error handling
- Introduce OTP patterns if genuinely needed
- Improve test structure and coverage
Cross-Cutting Principles
These principles apply across all Elixir development:
Functional-First Approach
- Prefer pure functions over stateful processes
- Use explicit state passing through function parameters
- Only introduce OTP patterns when tests require them
- Push side effects to system boundaries
Progressive Abstraction
- Start with primitives and maps
- Introduce structs when structure is genuinely needed
- Add type specs when interfaces stabilize
- Extract domain modules when concepts are proven
Parse, Don't Validate
- Transform unstructured data into guaranteed-valid types at boundaries
- Once data is parsed, it's always valid throughout the system
- Prefer constructors that return
{:ok, value} | {:error, reason}
Error Handling Philosophy
- Use tagged tuples consistently:
{:ok, result}or{:error, reason} - Implement proper error types for domain-specific errors
- Never expose internal implementation details in errors
Examples
Creating a Phoenix context with Ecto:
User: "I need to add a checkout feature for orders"
→ Consult ecto-database.md for schema design, phoenix-framework.md for controller
Implementing real-time updates:
User: "Show live order status updates to the customer"
→ Consult liveview.md for socket state and PubSub patterns
Refactoring to proper domain model:
User: "This order calculation has grown complex with many edge cases"
→ Identify TDD phase (likely REFACTOR), consult functional-modeling.md
Adding background job processing:
User: "Process order confirmations asynchronously"
→ Consult otp-patterns.md for process decisions, phoenix-framework.md for Oban
Writing a database migration:
User: "I need to add an index to the posts table"
→ Consult safe-ecto-migrations.md for concurrent index creation
Anti-Patterns to Avoid
Premature OTP
- GenServer for data that could be function arguments
- Supervisors for processes that don't need restart strategies
- ETS tables for small, static datasets
- Message passing when direct function calls suffice
Premature Abstraction
- Creating types for single-use values
- Building generic solutions for specific problems
- Introducing abstractions without duplication
- Modeling future requirements
Testing Anti-Patterns
- Writing multiple assertions before any pass
- Creating elaborate test fixtures prematurely
- Testing implementation details
- Adding error case tests too early
Reference File IDs
For programmatic access (e.g., parallel reviews), use these identifiers:
phoenix-framework · liveview · ecto-database · safe-ecto-migrations · otp-patterns · functional-modeling · graphql-absinthe · testing-exunit
More from bnadlerjr/dotfiles
slicing-elephant-carpaccio
Breaks features into ultra-thin vertical slices using Elephant Carpaccio methodology. Use when planning new features, breaking down epics, slicing work across layers, or when a task spans multiple components. Produces an ordered backlog of thin slices, each independently working, testable, and demoable. Handles single-repo, monorepo, and multi-repo architectures.
14receiving-code-review
Guides technical evaluation of code review feedback before implementation. Use when receiving PR comments, review suggestions, GitHub feedback, or when asked to address reviewer feedback. Emphasizes verification and reasoned pushback over blind agreement.
13breaking-down-stories
Breaks down user stories into small, actionable tasks. Use when decomposing user stories, planning sprint work, creating task lists from tickets, or when the user mentions story breakdown, task decomposition, or sprint planning.
12mui
Material-UI component library patterns including sx prop styling, theme integration, responsive design, and MUI-specific hooks. Use when working with MUI components (@mui/material), styling with sx prop, theme customization, or MUI utilities. Supports v5, v6, and v7.
1applying-swiss-design
Applies Swiss/International Typographic Style principles to create clear, functional output. Use when designing interfaces, data visualizations, documentation, CLI output, or any output where clarity matters. Recognizes requests like "make it cleaner", "reduce clutter", "too busy", "improve readability", "visual hierarchy", "simplify the layout".
1coding-workflow
Use when user asks to build a feature, implement something new, or make significant code changes. Recognizes requests like "build", "implement", "create a new feature", "add functionality", "develop", "I need to build X", "let's implement", "new feature request", "make these changes". Orchestrates a four-stage workflow (Research → Brainstorm → Plan → Implement) using the appropriate thought pattern skill at each stage.
1