Hi Phoenix community!
First off, huge thanks for an amazing framework - Phoenix has been a joy to work with. I have a small UX suggestion that I think could improve developer experience around code clarity.
The Current Confusion
Right now when I write:
defmodule MyApp.SomeLive do
use MyAppWeb, :live_view
# ...
end
This injects imports like:
import MyAppWeb.Gettext
import MyAppWeb.CoreComponents
import MyAppWeb.Router.Helpers
As a developer, it’s really hard to tell what’s my actual business logic vs framework-generated code that happens to use my app’s namespace. When I see MyAppWeb.Gettext
, my brain thinks “oh, this is code I wrote” but it’s actually just a Phoenix framework wrapper.
File Navigation Confusion
This confusion extends beyond just imports. When browsing my repo directory tree, I often click into files like lib/my_app_web/gettext.ex
or lib/my_app_web/telemetry.ex
thinking “let me understand this code I wrote,” only to realize it’s boilerplate framework code. Then I have to back out and continue looking for my actual application logic. It’s a small friction, but it adds up over time when you’re trying to navigate your own codebase efficiently.
Acknowledging the Design Intent
I absolutely recognize that the current approach is thoughtful - having lib/my_app_web/my_app_web.ex
as a configuration point gives us flexibility to customize what gets injected. The Phoenix team clearly intended this as a way for developers to have control over their application’s setup.
However, I think there’s room to improve the default developer experience while preserving that flexibility.
Possible Ideas
Option 1: Opt-in customization
mix phx.new my_app --web-config=custom
# Only then generates the MyAppWeb configuration files
# Default could be cleaner with framework namespaces
Option 2: Different namespace
use Phoenix.App, :live_view # or Phoenix.Web, :live_view
# Makes it clearer this is framework machinery
Option 3: More explicit imports
use MyAppWeb, :live_view, explicit: true
# Could optionally require manual imports for clarity
Option 4: Separate directory structure
lib/
my_app/ # My actual business logic
my_app_web/ # My actual web layer code
my_app_generated/ # All framework boilerplate (when customization needed)
Option 5: Configuration-driven generation
# Only generate MyAppWeb.* files when I actually want to customize them
# Default behavior uses clean framework namespaces
The Goal
I’d love a way to easily distinguish:
MyApp.Users
- my actual domain codeMyAppWeb.UserLive
- my actual web layer codeFramework/generated code - Phoenix machinery (kept separate until customization needed)
The idea would be preserving the powerful customization capabilities for those who need them, while providing a cleaner default experience for those who don’t.
Has anyone else experienced this confusion? Are there existing patterns I’m missing that make this clearer?
Thanks for considering! Love to hear everyone’s thoughts on this.