Gulliver

Gulliver

How can I change the default directory structure for templates in Phoenix app?

I just tried to create a new project and added some authentication to it by doing the “mix phx.gen.auth Accounts User users”. The result worked as expected but the directory/file structure it generated was quite a mess in my opinion. All the generated templates were directly under the “templates” directory, as user_registration, user_session and so on.

So I wanted to fix this by creating a “user” subdirectory and moving all the user related templates there but I couldn’t find a place where to tell phoenix where these templates files are. The generated view files were quite empty and they all just seem to call this “view” function. So where can I tell which templates this view actually renders and where they are?

Showing Posts 1 to 5

APB9785

APB9785

Creator of ECSx

The view function is in lib/my_app_web.ex:

def view do
  quote do
    use Phoenix.View,
      root: "lib/my_app_web/templates",
      namespace: MyAppWeb

    # Import convenience functions from controllers
    import Phoenix.Controller,
      only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]

    # Include shared imports and aliases for views
    unquote(view_helpers())
  end
end

You can define other alternatives to view here and use them instead when needed.

tadasajon

tadasajon

I just refactored a project I’m working on to address precisely this issue. I added a new function to myapp_web.ex, so now I have both view and accounts_view:

def view do
    quote do
      use Phoenix.View,
        root: "lib/quizdrill_web/templates",
        namespace: QuizdrillWeb

      # Import convenience functions from controllers
      import Phoenix.Controller,
        only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]

      # Include shared imports and aliases for views
      unquote(view_helpers())
    end
  end

  def accounts_view do
    quote do
      use Phoenix.View,
        root: "lib/quizdrill_web/accounts/templates",
        namespace: QuizdrillWeb

      # Import convenience functions from controllers
      import Phoenix.Controller,
        only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]

      # Include shared imports and aliases for views
      unquote(view_helpers())
    end
  end

Then, I created a new accounts/ folder at lib/myapp_web/accounts/ and I created three directories inside it: controllers/, views/, templates/. So my directory structure inside myapp_web looks like this:

myapp_web/
├── accounts/
│   ├── controllers/
│   │   ├── user_auth.ex
│   │   ├── user_confirmation_controller.ex
│   │   ├── user_registration_controller.ex
│   │   ├── user_reset_password_controller.ex
│   │   ├── user_session_controller.ex
│   │   └── user_settings_controller.ex
│   ├── templates/
│   │   ├── user_confirmation/
│   │   ├── user_registration/
│   │   ├── user_reset_password/
│   │   ├── user_session/
│   │   └── user_settings/
│   └── views/
│       ├── user_confirmation_view.ex
│       ├── user_registration_view.ex
│       ├── user_reset_password_view.ex
│       ├── user_session_view.ex
│       └── user_settings_view.ex
├── controllers/
│   └── page_controller.ex
├── templates/
│   ├── dashboard/
│   │   └── index.html.heex
│   ├── layout/
│   │   ├── live.html.heex
│   │   ├── _user_menu.html.heex
│   │   ├── root.html.heex
│   │   ├── admin.html.heex
│   │   └── app.html.heex
│   └── page/
│       ├── index.html.heex
│       └── dashboard.html.heex
├── views/
│   ├── error_helpers.ex
│   ├── error_view.ex
│   ├── layout_view.ex
│   ├── page_view.ex
│   └── dashboard_view.ex
├── endpoint.ex
├── gettext.ex
├── telemetry.ex
└── router.ex

The controllers and the views can be moved into the new directories without affecting anything, but if the templates are moved then they will be in the wrong location – so I have edited each of the view files so it is an :accounts_view rather than a :view, following the adjustment I made to lib/myapp_web.ex. For example:

defmodule QuizdrillWeb.UserConfirmationView do
  use QuizdrillWeb, :accounts_view
end

Now I have everything having to do with user accounts under the accounts/ directory and out of the way.

I’d appreciate any feedback, incidentally – the one thing I don’t like about this approach is the code-duplication between the view and accounts_view functions in lib/myapp_web.ex – I’d prefer to only change the root directory for the templates rather than copy-paste the whole function in the way that I did.

stefanchrobot

stefanchrobot

Since I have both a server-side rendered app and an API for a mobile app in my app, I took it one step further and created separate MyAppWeb modules, something along the lines of:

defmodule MyAppWeb.App do
  # ...

  def view do
    # import HTML helpers
  end 
end

defmodule MyAppWeb.MobileApi do
  # ...

  def view do
    # import API-related helpers
  end 
end

and then:

defmodule MyAppWeb.App.SessionView do
  use MyAppWeb.App, :view

  # ...
end

defmodule MyAppWeb.MobileApi.MessageView do
  use MyAppWeb.MobileApi, :view

  # ...
end
Gulliver

Gulliver OP

Thanks, this does solve the issue. However, it seems like such an overkill to to change my whole code structure just to get some sanity in the directory sorting that I decided to get rid of the whole frontend part of Phoenix and only use it for the api and use React for the frontend. There’s seems to be bit too much magic happening with all of the rendering/templates part to my liking. Anyways, thanks for the help!

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews