Hey, friends. Let's talk about Phoenix's error page. I think we can do a lot of improvement here.

This design has served Phoenix and better_errors well for a while, but it can use some improvement.
How about something more like this?

Gone is the weird frame-like scrolling; instead, it scrolls down naturally like a page would. (except for the stack trace... you should be able to scroll it down on its own iframe-like container.)
You'll see that above the fold, most the relevant things are what immediately draws your attention.
By putting all the "more info" stuff at the bottom, we get more space to do more interesting things. How links to search Google for the error? Or maybe link to the relevant hexdocs?
This is a rough draft of course, but if you like where this is going I'd be happy to polish it up and implement it.
I'm the author of the original better_errors error page, which I believe Phoenix's is based off of :)
This is so elegant, thank you! :heart: :green_heart: :blue_heart: :yellow_heart: :purple_heart:
The exception messages are limited to one line (tho more info can be shown on hover). This is kind of cumbersome, considering many Elixir errors can span multiple lines.
This has been my biggest pet peeve and you solved it perfectly! I absolutely love the links to search and docs too. Well done!
Btw, the debug pages come from Plug. Here is the source: https://github.com/elixir-lang/plug/blob/master/lib/plug/debugger.ex and here is the template: https://github.com/elixir-lang/plug/blob/master/lib/plug/templates/debugger.eex
I would merge this PR in a heartbeat. :) Let me know if there is anything I can do to help!
I'm the author of the original better_errors error page, which I believe Phoenix's is based off of :)
Yes! I emailed you 3 years ago to ask for your blessing. :D
oh man I'm so sorry I didn't see your email on that, haha, but it's all MIT license so it's all good!
(Oh, you may have emailed Charlie @charliesome鈥攈e's the author of better_errors, I just contributed frontend work to his project)
@rstacruz No problems! I e-mailed you both but went ahead because of MIT anyway. :D
@rstacruz this looks amazing! I love every change you're proposing. Your work on better_errors is something I include in every talk I give about having "pretty errors", and this would take it over the top :)
We'd love to have this in place if you're up for it. Since this is on the plug side, we'll need to think how to best get this in plug, but also allow it to be extensible so we can include the help links that are dep specific. Thanks!
Neat! What would be the best way to put together a little development setup to hack Plug.Debugger? (I'm guessing maybe something like a mini-phoenix app with deps/plug being part of elixirc_paths and Phoenix.CodeReloader reloadable_paths?)
but also allow it to be extensible so we can include the help links
After giving this some thought, I realized that feature might have been thinking way too far ahead鈥攆or a first iteration, maybe something that just implements the baseline functionality that the current version has would be best.
yes that sounds like a good firs step in plug. With some hooks to plug debugger I think we could make it extensible, but getting baseline in place first is a good start
And if we decide to go ahead with the links anyway, I can help with making them configurable. :)
@rstacruz if you clone both phoenix and plug locally and depend on plug as {:plug, path: "../path/to/plug"}, I believe it should recompile it automatically. If not, you can start Phoenix with iex -S mix phoenix.server and call r Plug.Debugger whenever you change the template.
okay, that's quick and easy. thanks for the tips!
@rstacruz if you need help I can certainly lend you a hand
hmm, r Plug.Debugger isn't quite reloading template changes for me.
@rstacruz I will investigate soon and provide a small Plug app that does code reloading only for Plug.Debugger. :D
haha, cool, i'm doing ctrl+c - up - enter for now :D
@rstacruz if you create a file named app.exs at the root of your Plug checkout with the following contents:
defmodule MyRouter do
use Plug.Router
use Plug.Debugger
plug :reload
plug :match
plug :dispatch
defp reload(conn, _) do
IEx.Helpers.r(Plug.Debugger)
conn
end
get "/oops" do
_ = conn
raise "oops"
end
end
{:ok, _} = Plug.Adapters.Cowboy.http MyRouter, port: 4000
You can start it with mix run --no-halt app.exs and now you access localhost:4000/oops for a custom exception or any route for a function clause error. Live reloading should work (although it is a hack :D).
Thanks for everyone who's volunteering to help! I have it working on this branch, feel free to try it out and break it (maybe with @josevalim's test code up there). Just a few more refinements and I'll open up a PR. PR opened (https://github.com/elixir-lang/plug/pull/423).

Okay, that's done! I'd imagine this is next:
https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/code_reloader.ex
@rstacruz yes, that would definitely be the next step. I have changed Phoenix master to depend on Plug 1.2-dev in case you want to give it a try inside Phoenix.
Actually, we still need to change the code reloader error pages. So I am reopening this. :D
Most helpful comment
Thanks for everyone who's volunteering to help! I have it working on this branch, feel free to try it out and break it (maybe with @josevalim's test code up there).
Just a few more refinements and I'll open up a PR.PR opened (https://github.com/elixir-lang/plug/pull/423).