<!-- LLM_VERSION_INFO
FORMAT: text/markdown
CONTENT_TYPE: article
ORIGINAL_URL: https://fly.io/phoenix-files/customizing-phoenix-generators
ALTERNATE_VERSION: phoenix-files/customizing-phoenix-generators/index.html (text/html)
EXTRACTION_DATE: 2026-04-18T22:26:15.452Z

This is the markdown version with text-only content (images converted to alt-text).
For rich formatting with images, request the HTML version at: phoenix-files/customizing-phoenix-generators/index.html
-->

# Author 
   
 Name  
 Mark Ericksen  
 @brainlid [@brainlid](https://twitter.com/brainlid)  
   
 Image by [Annie Ruygt](https://annieruygtillustration.com/)

We’re Fly.io. We run apps for our users on hardware we host around the world. Fly.io happens to be a great place to run Phoenix applications. Check out how to [get started](/content/docs/elixir/ ""/index.html)!

During my [interview with Victor Björklund](https://podcast.thinkingelixir.com/167 ""), I learned how easily the Phoenix generators can be customized for our projects. I was shocked I that I never knew about it and I don’t recall ever seeing it documented. This post is to document this invisible feature that is super easy to use and can be really powerful for teams with either new or mature projects.

## Problem  
You have an established project and over time, patterns and styles were developed for LiveViews, Controllers, etc. Now, every time you add a new Context, LiveView, Controller or some other standard thing, rather than use the built-in generators, you’ve been copying an existing file and changing it to be what you want.

The process of copying and tweaking files this way is tedious and error prone. We frequently end up with left-overs in our resulting code that points back to where it was copied from.

Is there a way to make creating new standard parts of our application smoother? Can we customize an existing Phoenix generator to make it match our application and our patterns?

## Solution  
Yes, it’s actually easy to do!

First, let’s be clear about which Phoenix generators we’re talking about.

For your Phoenix project, type `mix phx.gen` to list the available Phoenix generators. This is what mine looks like:

```  
mix phx.gen  
```

```  
mix phx.gen.auth     # Generates authentication logic for a resource  
mix phx.gen.cert     # Generates a self-signed certificate for HTTPS testing  
mix phx.gen.channel  # Generates a Phoenix channel  
mix phx.gen.context  # Generates a context with functions around an Ecto schema  
mix phx.gen.embedded # Generates an embedded Ecto schema file  
mix phx.gen.html     # Generates context and controller for an HTML resource  
mix phx.gen.json     # Generates context and controller for a JSON resource  
mix phx.gen.live     # Generates LiveView, templates, and context for a resource  
mix phx.gen.notifier # Generates a notifier that delivers emails by default  
mix phx.gen.presence # Generates a Presence tracker  
mix phx.gen.release  # Generates release files and optional Dockerfile for release-based deployments  
mix phx.gen.schema   # Generates an Ecto schema and migration file  
mix phx.gen.secret   # Generates a secret  
mix phx.gen.socket   # Generates a Phoenix socket handler  
```

Every one of these can easily be customized to generate something more appropriate for our project! Let’s see how!

### Choosing a Generator  
To get started, let’s pick a generator to customize. It makes sense to choose one that we’ll continue to use as our project evolves. For this example, we’ll use the LiveView generator for a resource. In our case, it’s the `mix phx.gen.live` task.

With our generator selected, let’s go!

### Step 1: Locate the current template  
Luckily, we don’t have to start from scratch! Here’s how we can find the current generator that is used for our project.

Our project’s mix tasks come from our mix dependencies. Specifically, this mix task comes from our Phoenix dependency and lives in `deps/phoenix`. The generator templates are found in `deps/phoenix/priv/templates`.

Alternatively, we can find the templates online. Here’s a link to the templates on the [Phoenix Framework’s main branch](https://github.com/phoenixframework/phoenix/tree/main/priv/templates ""). We can use the Github tags to find specific versions of the templates as well.

### Step 2: Copy the files we want to customize  
Now that we’ve found the existing files to start from, we can copy the templates into our project.

This brings up the next question, “Where should these go?”

To answer this, let’s explore a bit about how the mix task templates work.

#### How does this work?  
The template files are in the Phoenix project’s `priv/templates` folder. It turns out that the Phoenix generators first look in _our_ project’s `priv/templates` folder for the template files. When the templates aren’t found in our project, and they usually aren’t, it falls back to use the Phoenix project’s templates.

**Take-away**  
If we put one or more customized template files in `priv/templates/MIX-TASK-NAME/` then the mix task will look for the file in our project first. Any files we don’t include there will fall back to the Phoenix generator.

The `phx.gen.live` directory name is used because that’s the mix task we’re running and where the original templates are located.

This example is using the `phx.gen.live` generator. In this case, our files will end up in our project’s `priv/templates/phx.gen.live/` directory.

Let’s create that directory in our project.

### Step 3: Customize the generated LiveView `index.ex` file  
Let’s walk through what we need to do:

- copy the file(s) to customize into this directory. For this example, [we’ll copy the `index.ex` file](https://github.com/phoenixframework/phoenix/blob/main/priv/templates/phx.gen.live/index.ex "") which generates the LiveView’s code for the index page.

- make a change to `index.ex`. For our example, well just add the comment `# CHECK IT OUT! Custom change right here!!!`.

Here’s the first part of our modified `priv/templates/phx.gen.live/index.ex` template file. Notice the “CHECK IT OUT!” comment was added.

```  
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.Index do  
  use <%= inspect context.web_module %>, :live_view

alias <%= inspect context.module %>  
  alias <%= inspect schema.module %>

# CHECK IT OUT! Custom change right here!!!

@impl true  
  def mount(_params, _session, socket) do  
    {:ok, stream(socket, :<%= schema.collection %>, <%= inspect context.alias %>.list_<%= schema.plural %>())}  
  end  
```

Let’s run it and see what happens.

### Step 4: Run the generator  
Let’s run the mix task using the following command:

To see all the options available for executing this generator, use the `help` command like this: `mix help phx.gen.live`

```  
mix phx.gen.live Foos Foo foos name:string age:integer  
```

The mix task generated a bunch of files. Let’s see the generated `index.ex` file:

```  
defmodule Web.FooLive.Index do  
  use Web, :live_view

alias Web.Foos  
  alias Web.Foos.Foo

# CHECK IT OUT! Custom change right here!!!

@impl true  
  def mount(_params, _session, socket) do  
    {:ok, stream(socket, :foos, Foos.list_foos())}  
  end  
```

Notice our change (the comment) is included in the newly generated module. The other thing to note is that all the other files were generated without customization.

Perfect! It worked! We customized a Phoenix generator template file and it was used by our project.

## Discussion  
It turns out that the Phoenix team created an excellent escape hatch for the Phoenix generators!

What I love about this is approach is our customizations are checked-in with the project. Our team members get access to the generators too. As we define new patterns for our project, we now have a good place to put them!

We saw here that we can customize just one, or many of the template files for a generator. It’s totally open for us to decide.

### Keeping templates out of our deploy  
By default, any templates in our `priv/templates` directory will be included in our deploy. There’s nothing inherently dangerous about that, but still, why include dev-focused files in our production build? Luckily, it’s easy to prevent those files from being included.

Assuming we’re using a `Dockerfile` to deploy, then adding the following line to our [`.dockerignore` file](https://docs.docker.com/engine/reference/builder/#dockerignore-file "") excludes any and all templates from the build.

```  
priv/templates/  
```

Nice and easy.

### What can we do with this?  
With this, we can customize how new LiveViews are generated. We can tailor them for our application, to use our components, our styles, our helper modules, our markup, all the things we used to copying over but often ended up copying too much.

Is it just LiveViews? No! We could customize Contexts with all the functions you end up adding anyway. We could customize migrations, schemas, controllers, or whatever our application uses frequently.

If you’re happy with your established patterns, you can copy them to a brand new project and use it from the beginning.

Cool trick!

# Fly.io ❤️ Elixir

Fly.io is a great way to run your Phoenix LiveView apps. It’s really easy to get started. You can be running in minutes.
