| name | phoenix-generator |
| description | Generate Phoenix resources (contexts, schemas, LiveViews, controllers) using mix phx.gen.* commands with best practices. Use when creating new Phoenix resources, contexts, or LiveView components. |
| allowed-tools | Bash, Read, Edit, Write |
Phoenix Generator
This skill helps generate Phoenix resources using built-in generators with proper patterns and best practices.
When to Use
- Creating new Phoenix contexts
- Adding schemas to existing contexts
- Generating LiveView CRUD interfaces
- Creating JSON/HTML resources
- Scaffolding authentication
Available Generators
Context and Schema Generation
mix phx.gen.context - Generate a context with schema and migration
mix phx.gen.context Accounts User users name:string email:string:unique age:integer
Generates:
- Context module:
lib/my_app/accounts.ex - Schema:
lib/my_app/accounts/user.ex - Migration:
priv/repo/migrations/*_create_users.exs - Test files
mix phx.gen.schema - Schema and migration only (no context)
mix phx.gen.schema Accounts.User users name:string email:string:unique
LiveView Generators
mix phx.gen.live - Full LiveView CRUD with context
mix phx.gen.live Catalog Product products \
name:string \
description:text \
price:decimal \
sku:string:unique \
in_stock:boolean
Generates:
- Context and schema
- LiveView modules (Index, Show, Form Component)
- Routes
- Tests
mix phx.gen.live.component - Standalone LiveView component
mix phx.gen.live.component Components.Modal
Traditional Web Generators
mix phx.gen.html - HTML resource with controllers
mix phx.gen.html Blog Post posts title:string body:text published:boolean
mix phx.gen.json - JSON API resource
mix phx.gen.json Shop Product products name:string price:decimal
Field Types and Modifiers
Common Field Types
string- varchar(255)text- unlimited textinteger- whole numbersdecimal- precise decimals (for money)float- floating pointboolean- true/falsedate- date onlytime- time onlydatetime- timestampuuid- UUIDbinary- binary data
Field Modifiers
:unique- adds unique index:redact- marks for redaction in logsname:string:unique:redact- chain modifiers
References (Associations)
# belongs_to
mix phx.gen.context Blog Post posts \
title:string \
body:text \
user_id:references:users
# Specify custom reference
mix phx.gen.context Comments Comment comments \
body:text \
post_id:references:posts \
author_id:references:users
Best Practices
1. Context Naming
- Use plural for context:
Accounts,Catalog,Blog - Use singular for schema:
User,Product,Post - Table name matches schema plural:
users,products,posts
2. Field Selection
# Good: Specific types
price:decimal # For money
published_at:datetime # For timestamps
active:boolean # For flags
# Avoid: Wrong types
price:float # Loses precision for money
published:string # Use datetime or boolean
3. Associations
# Always specify references explicitly
user_id:references:users
# Don't use bare integer for foreign keys
user_id:integer # Missing association metadata
4. Decimal Precision
For money fields, update migration:
# Generated
add :price, :decimal
# Best Practice - specify precision
add :price, :decimal, precision: 10, scale: 2
5. String Length Limits
Update schema for validation:
# Add to changeset
|> validate_length(:name, max: 100)
|> validate_length(:email, max: 160)
Generator Workflow
Step 1: Plan Schema
# List fields with types
name:string
email:string:unique
age:integer
bio:text
admin:boolean
inserted_at:datetime
updated_at:datetime # automatic with timestamps()
Step 2: Generate Resource
# Choose appropriate generator
mix phx.gen.live Accounts User users \
name:string \
email:string:unique \
age:integer \
bio:text \
admin:boolean
Step 3: Review Generated Files
- Check migration for proper indexes and constraints
- Review schema for additional validations needed
- Update context functions as needed
- Review tests and add edge cases
Step 4: Customize Migration
# Before running migration, edit it
vim priv/repo/migrations/*_create_users.exs
Add:
- Check constraints
- Default values
- Additional indexes
- Precision for decimals
Step 5: Add Routes (if needed)
# lib/my_app_web/router.ex
scope "/", MyAppWeb do
pipe_through :browser
live "/users", UserLive.Index, :index
live "/users/new", UserLive.Index, :new
live "/users/:id/edit", UserLive.Index, :edit
live "/users/:id", UserLive.Show, :show
live "/users/:id/show/edit", UserLive.Show, :edit
end
Step 6: Run Migration
mix ecto.migrate
Step 7: Update Tests
- Add validation tests
- Add association tests
- Test edge cases
Common Patterns
Money Fields
mix phx.gen.live Shop Product products \
name:string \
price:decimal \
sale_price:decimal
Then update migration:
add :price, :decimal, precision: 10, scale: 2, null: false
add :sale_price, :decimal, precision: 10, scale: 2
Soft Deletes
Add to schema:
deleted_at:datetime
Update migration:
add :deleted_at, :utc_datetime
create index(:products, [:deleted_at])
Polymorphic Associations
mix phx.gen.schema Comments.Comment comments \
body:text \
commentable_type:string \
commentable_id:integer
Multi-tenant (Tenant ID)
mix phx.gen.live Accounts User users \
organization_id:references:organizations \
name:string \
email:string
Add unique constraint on tenant + field:
create unique_index(:users, [:organization_id, :email])
Undoing Generators
If you need to rollback:
# Rollback migration
mix ecto.rollback
# Delete generated files manually or use:
mix phx.gen.context --undo Accounts User users
Troubleshooting
Module already exists:
- Generator won't overwrite existing files
- Use
--merge-with-existing-contextto add to existing context - Or manually integrate generated code
Routes not working:
- Check router.ex was updated
- Verify pipe_through matches (:browser or :api)
- Restart server after adding routes
Migration fails:
- Check for duplicate table names
- Verify referenced tables exist
- Ensure field types are valid
Generator Flags
# Skip migration
mix phx.gen.context Accounts User users name:string --no-migration
# Binary ID (UUID)
mix phx.gen.schema Accounts User users name:string --binary-id
# Merge with existing context
mix phx.gen.context Accounts Profile profiles bio:text --merge-with-existing-context
# Specify table name
mix phx.gen.schema Accounts User my_users name:string --table my_users